@cdktn/commons 0.25.0-pre.53 → 0.25.0-pre.55
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/build/config.d.ts +5 -0
- package/build/config.d.ts.map +1 -1
- package/build/config.js +26 -1
- package/build/config.test.js +23 -1
- package/build/construct-maker-target.d.ts +2 -0
- package/build/construct-maker-target.d.ts.map +1 -1
- package/build/construct-maker-target.js +3 -1
- package/build/debug.js +11 -11
- package/build/debug.test.js +9 -2
- package/build/errors.d.ts +3 -0
- package/build/errors.d.ts.map +1 -1
- package/build/errors.js +31 -23
- package/build/errors.test.d.ts +2 -0
- package/build/errors.test.d.ts.map +1 -0
- package/build/errors.test.js +24 -0
- package/build/identity.d.ts +3 -0
- package/build/identity.d.ts.map +1 -0
- package/build/identity.js +88 -0
- package/build/index.d.ts +2 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +3 -2
- package/build/process-state.d.ts +2 -0
- package/build/process-state.d.ts.map +1 -0
- package/build/process-state.js +15 -0
- package/build/telemetry.d.ts +24 -0
- package/build/telemetry.d.ts.map +1 -0
- package/build/telemetry.js +721 -0
- package/build/telemetry.test.d.ts +2 -0
- package/build/telemetry.test.d.ts.map +1 -0
- package/build/telemetry.test.js +1501 -0
- package/build/terraform.d.ts +10 -1
- package/build/terraform.d.ts.map +1 -1
- package/build/terraform.js +43 -8
- package/build/terraform.test.d.ts +2 -0
- package/build/terraform.test.d.ts.map +1 -0
- package/build/terraform.test.js +136 -0
- package/package.json +3 -3
- package/build/checkpoint.d.ts +0 -19
- package/build/checkpoint.d.ts.map +0 -1
- package/build/checkpoint.js +0 -185
|
@@ -0,0 +1,721 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.SYNTH_ORIGINS = exports.PACKAGE_MANAGERS = exports.COMMAND_ERROR_TYPES = void 0;
|
|
40
|
+
exports.getUsageTelemetryConsent = getUsageTelemetryConsent;
|
|
41
|
+
exports.normalizePackageManager = normalizePackageManager;
|
|
42
|
+
exports.setUsageTelemetryEnabled = setUsageTelemetryEnabled;
|
|
43
|
+
exports.hasCapturedUsageTelemetryDecision = hasCapturedUsageTelemetryDecision;
|
|
44
|
+
exports.isUsageTelemetryEnabled = isUsageTelemetryEnabled;
|
|
45
|
+
exports.getProjectTargetAttributes = getProjectTargetAttributes;
|
|
46
|
+
exports.setProjectTargetAttributes = setProjectTargetAttributes;
|
|
47
|
+
exports.sendErrorTelemetry = sendErrorTelemetry;
|
|
48
|
+
exports.flushTelemetry = flushTelemetry;
|
|
49
|
+
exports.startCommandTelemetry = startCommandTelemetry;
|
|
50
|
+
exports.resetCommandTelemetry = resetCommandTelemetry;
|
|
51
|
+
exports.sendTelemetry = sendTelemetry;
|
|
52
|
+
// Copyright (c) HashiCorp, Inc
|
|
53
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
54
|
+
const config_1 = require("./config");
|
|
55
|
+
const Sentry = __importStar(require("@sentry/node"));
|
|
56
|
+
const path = __importStar(require("path"));
|
|
57
|
+
const fs = __importStar(require("fs-extra"));
|
|
58
|
+
const semver = __importStar(require("semver"));
|
|
59
|
+
const ci_info_1 = __importDefault(require("ci-info"));
|
|
60
|
+
const logging_1 = require("./logging");
|
|
61
|
+
const config_2 = require("./config");
|
|
62
|
+
const gradle_1 = require("./gradle");
|
|
63
|
+
const node_package_manager_1 = require("./node-package-manager");
|
|
64
|
+
const process_state_1 = require("./process-state");
|
|
65
|
+
const terraform_module_1 = require("./terraform-module");
|
|
66
|
+
const terraform_1 = require("./terraform");
|
|
67
|
+
exports.COMMAND_ERROR_TYPES = [
|
|
68
|
+
"Usage",
|
|
69
|
+
"External",
|
|
70
|
+
"Internal",
|
|
71
|
+
"unexpected",
|
|
72
|
+
];
|
|
73
|
+
// Never throws: telemetry also runs outside a project. Raw, because commons
|
|
74
|
+
// cannot import cli-core's typed config.
|
|
75
|
+
function readRawCdktfJson(projectPath) {
|
|
76
|
+
try {
|
|
77
|
+
return JSON.parse(fs.readFileSync(path.resolve(projectPath, "cdktf.json"), "utf8"));
|
|
78
|
+
}
|
|
79
|
+
catch (_a) {
|
|
80
|
+
return {};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// undefined: unset, malformed, or no readable cdktf.json
|
|
84
|
+
function getUsageTelemetryConsent(projectPath = process.cwd()) {
|
|
85
|
+
const cdktfJson = readRawCdktfJson(projectPath);
|
|
86
|
+
if (!("sendUsageTelemetry" in cdktfJson)) {
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
return (0, config_1.normalizeConsentFlag)("sendUsageTelemetry", cdktfJson.sendUsageTelemetry);
|
|
90
|
+
}
|
|
91
|
+
// Shared by both bundle copies: the handlers' copy captures the decision and
|
|
92
|
+
// starts the run, the entrypoint's copy counts the failure.
|
|
93
|
+
const state = (0, process_state_1.processState)("cdktn.commandTelemetry", () => ({}));
|
|
94
|
+
exports.PACKAGE_MANAGERS = [
|
|
95
|
+
"npm",
|
|
96
|
+
"pnpm",
|
|
97
|
+
"yarn",
|
|
98
|
+
"yarn-berry",
|
|
99
|
+
"pip",
|
|
100
|
+
"pipenv",
|
|
101
|
+
"maven",
|
|
102
|
+
"gradle",
|
|
103
|
+
"nuget",
|
|
104
|
+
"go",
|
|
105
|
+
];
|
|
106
|
+
// Only members of the closed set become an attribute: a `packageManager`
|
|
107
|
+
// field carries a version and a hash, and a detector may grow new values.
|
|
108
|
+
function normalizePackageManager(value) {
|
|
109
|
+
return exports.PACKAGE_MANAGERS.find((name) => name === value);
|
|
110
|
+
}
|
|
111
|
+
// The package manager `provider add` would drive, decided the way cli-core's
|
|
112
|
+
// PackageManager.forLanguage does. undefined outside a supported project.
|
|
113
|
+
function detectPackageManager(projectPath, cdktfJson) {
|
|
114
|
+
try {
|
|
115
|
+
switch (cdktfJson.language) {
|
|
116
|
+
case config_2.Language.TYPESCRIPT:
|
|
117
|
+
return normalizePackageManager((0, node_package_manager_1.detectNodePackageManager)(projectPath));
|
|
118
|
+
case config_2.Language.PYTHON:
|
|
119
|
+
if (typeof cdktfJson.app !== "string") {
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
122
|
+
return cdktfJson.app.includes("pipenv") ? "pipenv" : "pip";
|
|
123
|
+
case config_2.Language.JAVA:
|
|
124
|
+
return (0, gradle_1.isGradleProject)(projectPath) ? "gradle" : "maven";
|
|
125
|
+
case config_2.Language.CSHARP:
|
|
126
|
+
return "nuget";
|
|
127
|
+
case config_2.Language.GO:
|
|
128
|
+
return "go";
|
|
129
|
+
default:
|
|
130
|
+
return undefined;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
catch (err) {
|
|
134
|
+
logging_1.logger.debug(`Could not detect the package manager: ${err}`);
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// Free-text payload fields are validated before they become attributes so a
|
|
139
|
+
// misconfigured or hand-edited value never carries arbitrary text.
|
|
140
|
+
const CONSTRAINT_PART = /^(=|!=|>=|<=|>|<|~>)?\s*(\d+(?:\.\d+){0,2})$/;
|
|
141
|
+
const RELEASE_VERSION = /^\d+\.\d+\.\d+/;
|
|
142
|
+
// Terraform's built-in backend kinds; anything else is sent as "other"
|
|
143
|
+
const BACKEND_KINDS = [
|
|
144
|
+
"local",
|
|
145
|
+
"remote",
|
|
146
|
+
"cloud",
|
|
147
|
+
"s3",
|
|
148
|
+
"gcs",
|
|
149
|
+
"azurerm",
|
|
150
|
+
"http",
|
|
151
|
+
"consul",
|
|
152
|
+
"kubernetes",
|
|
153
|
+
"pg",
|
|
154
|
+
"oss",
|
|
155
|
+
"cos",
|
|
156
|
+
"etcdv3",
|
|
157
|
+
"artifactory",
|
|
158
|
+
"swift",
|
|
159
|
+
"manta",
|
|
160
|
+
];
|
|
161
|
+
function normalizeBackendKind(backend) {
|
|
162
|
+
if (typeof backend !== "string") {
|
|
163
|
+
return "unknown";
|
|
164
|
+
}
|
|
165
|
+
return BACKEND_KINDS.includes(backend) ? backend : "other";
|
|
166
|
+
}
|
|
167
|
+
// Terraform resource type grammar; the stack-level override keys (stack,
|
|
168
|
+
// backend, output, local, terraform_remote_state) are identifiers too.
|
|
169
|
+
const RESOURCE_TYPE = /^[a-z][a-z0-9_]*$/;
|
|
170
|
+
// MAJOR.MINOR.PATCH only: prerelease and build identifiers are free text
|
|
171
|
+
// (a wrapper's version line or a locally built library can carry anything).
|
|
172
|
+
function releaseVersion(value) {
|
|
173
|
+
var _a;
|
|
174
|
+
return (_a = RELEASE_VERSION.exec(value !== null && value !== void 0 ? value : "")) === null || _a === void 0 ? void 0 : _a[0];
|
|
175
|
+
}
|
|
176
|
+
// Normalized so spacing variants collapse into one value. Hyphen ranges are
|
|
177
|
+
// written " - ", so a hyphen right after a digit is always a prerelease:
|
|
178
|
+
// free text (see releaseVersion), which rejects the range.
|
|
179
|
+
function semverRangeOrInvalid(value) {
|
|
180
|
+
const range = value.length <= 64 ? semver.validRange(value) : null;
|
|
181
|
+
return range && !/\d[-+]/.test(value) ? range : "invalid";
|
|
182
|
+
}
|
|
183
|
+
// Re-joined as "~> 5.0, != 5.1.0" so spacing variants are one value. The
|
|
184
|
+
// constraint is user-authored, so a prerelease identifier or an over-long
|
|
185
|
+
// value rejects it whole.
|
|
186
|
+
function normalizeProviderConstraint(value) {
|
|
187
|
+
if (value.length > 64) {
|
|
188
|
+
return "invalid";
|
|
189
|
+
}
|
|
190
|
+
const parts = [];
|
|
191
|
+
for (const part of value.split(",")) {
|
|
192
|
+
const match = CONSTRAINT_PART.exec(part.trim());
|
|
193
|
+
if (!match) {
|
|
194
|
+
return "invalid";
|
|
195
|
+
}
|
|
196
|
+
const [, operator, version] = match;
|
|
197
|
+
parts.push(operator ? `${operator} ${version}` : version);
|
|
198
|
+
}
|
|
199
|
+
return parts.join(", ");
|
|
200
|
+
}
|
|
201
|
+
function setUsageTelemetryEnabled(enabled) {
|
|
202
|
+
state.usageTelemetryEnabled = enabled;
|
|
203
|
+
}
|
|
204
|
+
// Once captured, the decision stands for the process; reporting is not
|
|
205
|
+
// initialized a second time.
|
|
206
|
+
function hasCapturedUsageTelemetryDecision() {
|
|
207
|
+
return state.usageTelemetryEnabled !== undefined;
|
|
208
|
+
}
|
|
209
|
+
// Precedence: CHECKPOINT_DISABLE > the decision captured at command start >
|
|
210
|
+
// `sendUsageTelemetry` in cdktf.json > enabled.
|
|
211
|
+
function isUsageTelemetryEnabled(projectPath = process.cwd()) {
|
|
212
|
+
if (process.env.CHECKPOINT_DISABLE) {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
if (state.usageTelemetryEnabled !== undefined) {
|
|
216
|
+
return state.usageTelemetryEnabled;
|
|
217
|
+
}
|
|
218
|
+
return getUsageTelemetryConsent(projectPath) !== false;
|
|
219
|
+
}
|
|
220
|
+
// Falls back to the CLI defaults, so every metric carries the ranges the
|
|
221
|
+
// command validated against.
|
|
222
|
+
function getProjectTargetAttributes(projectPath = process.cwd()) {
|
|
223
|
+
const cdktfJson = readRawCdktfJson(projectPath);
|
|
224
|
+
const declared = cdktfJson.targetVersions &&
|
|
225
|
+
typeof cdktfJson.targetVersions === "object" &&
|
|
226
|
+
!Array.isArray(cdktfJson.targetVersions)
|
|
227
|
+
? cdktfJson.targetVersions
|
|
228
|
+
: undefined;
|
|
229
|
+
const targets = declared !== null && declared !== void 0 ? declared : config_2.DEFAULT_TARGET_VERSIONS;
|
|
230
|
+
const attributes = {
|
|
231
|
+
targets_declared: declared !== undefined,
|
|
232
|
+
validate_installed_binary: cdktfJson.validateInstalledBinary === true,
|
|
233
|
+
};
|
|
234
|
+
if (typeof targets.terraform === "string") {
|
|
235
|
+
attributes.target_terraform = semverRangeOrInvalid(targets.terraform);
|
|
236
|
+
}
|
|
237
|
+
if (typeof targets.opentofu === "string") {
|
|
238
|
+
attributes.target_opentofu = semverRangeOrInvalid(targets.opentofu);
|
|
239
|
+
}
|
|
240
|
+
return attributes;
|
|
241
|
+
}
|
|
242
|
+
function setProjectTargetAttributes(attributes) {
|
|
243
|
+
state.projectTargetAttributes = attributes;
|
|
244
|
+
}
|
|
245
|
+
async function getBinaryAttributes() {
|
|
246
|
+
const cli = await (0, terraform_1.terraformCli)();
|
|
247
|
+
const attributes = { binary: cli.name };
|
|
248
|
+
// an unrecognised product's version is the first version-like token of
|
|
249
|
+
// its output, which can be anything (a wrapper's "connected to 10.0.0.1")
|
|
250
|
+
const release = cli.name === "terraform" || cli.name === "opentofu"
|
|
251
|
+
? releaseVersion(cli.version)
|
|
252
|
+
: undefined;
|
|
253
|
+
if (release) {
|
|
254
|
+
attributes.binary_version = release;
|
|
255
|
+
}
|
|
256
|
+
return attributes;
|
|
257
|
+
}
|
|
258
|
+
// By type and command only: message and context can carry paths and user
|
|
259
|
+
// input.
|
|
260
|
+
function sendErrorTelemetry(type, command) {
|
|
261
|
+
try {
|
|
262
|
+
if (!isUsageTelemetryEnabled()) {
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
Sentry.metrics.count("cli.error", 1, { attributes: { type, command } });
|
|
266
|
+
}
|
|
267
|
+
catch (err) {
|
|
268
|
+
logging_1.logger.debug(`Could not send error telemetry: ${err}`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
// Call before an explicit process.exit(): Sentry buffers asynchronously and
|
|
272
|
+
// a hard exit drops the buffer.
|
|
273
|
+
async function flushTelemetry(timeoutMs = 4000) {
|
|
274
|
+
try {
|
|
275
|
+
await Sentry.flush(timeoutMs);
|
|
276
|
+
}
|
|
277
|
+
catch (err) {
|
|
278
|
+
logging_1.logger.debug(`Could not flush telemetry: ${err}`);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
const PUBLIC_PROVIDER_REGISTRIES = [
|
|
282
|
+
"registry.terraform.io",
|
|
283
|
+
"registry.opentofu.org",
|
|
284
|
+
];
|
|
285
|
+
const PROVIDER_SEGMENT = /^[a-z0-9][a-z0-9_-]*$/;
|
|
286
|
+
const PROVIDER_HOST = /^(localhost|[a-z0-9-]+(\.[a-z0-9-]+)+)(:\d+)?$/;
|
|
287
|
+
// Registry identities are bounded so an over-long hand-written source cannot
|
|
288
|
+
// carry free text through the segment grammar.
|
|
289
|
+
function withinIdentityLimits(segments) {
|
|
290
|
+
return (segments.every((segment) => segment.length <= 64) &&
|
|
291
|
+
segments.join("/").length <= 128);
|
|
292
|
+
}
|
|
293
|
+
// Only a public-registry `namespace/type` is sent (`aws`, `hashicorp/aws@~>5`
|
|
294
|
+
// and `registry.terraform.io/hashicorp/aws` are one); other hosts become
|
|
295
|
+
// "private-registry", paths and malformed input "other".
|
|
296
|
+
function normalizeProviderSource(source) {
|
|
297
|
+
const segments = source.trim().toLowerCase().split("@")[0].split("/");
|
|
298
|
+
if (segments.length === 3) {
|
|
299
|
+
const host = segments.shift();
|
|
300
|
+
if (!PUBLIC_PROVIDER_REGISTRIES.includes(host)) {
|
|
301
|
+
return PROVIDER_HOST.test(host) ? "private-registry" : "other";
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
if (segments.length === 1) {
|
|
305
|
+
segments.unshift("hashicorp");
|
|
306
|
+
}
|
|
307
|
+
return segments.length === 2 &&
|
|
308
|
+
segments.every((s) => PROVIDER_SEGMENT.test(s)) &&
|
|
309
|
+
withinIdentityLimits(segments)
|
|
310
|
+
? segments.join("/")
|
|
311
|
+
: "other";
|
|
312
|
+
}
|
|
313
|
+
// Comparison key for generated-vs-prebuilt, never sent: public sources
|
|
314
|
+
// normalize, anything else stays raw so two unrelated private sources (both
|
|
315
|
+
// "private-registry" on the metric) never match each other.
|
|
316
|
+
function providerIdentity(source) {
|
|
317
|
+
const normalized = normalizeProviderSource(source);
|
|
318
|
+
return normalized === "private-registry" || normalized === "other"
|
|
319
|
+
? source.trim().toLowerCase().split("@")[0]
|
|
320
|
+
: normalized;
|
|
321
|
+
}
|
|
322
|
+
// From `terraformProviders` in cdktf.json (`"aws@~>5.0"` strings or
|
|
323
|
+
// `{ name, source }` objects); a stack provider not listed there is prebuilt.
|
|
324
|
+
function getGeneratedProviderSources(projectPath = process.cwd()) {
|
|
325
|
+
const entries = readRawCdktfJson(projectPath).terraformProviders;
|
|
326
|
+
if (!Array.isArray(entries)) {
|
|
327
|
+
return [];
|
|
328
|
+
}
|
|
329
|
+
return entries.flatMap((entry) => {
|
|
330
|
+
var _a;
|
|
331
|
+
if (typeof entry === "string") {
|
|
332
|
+
return [providerIdentity(entry)];
|
|
333
|
+
}
|
|
334
|
+
const source = (_a = entry === null || entry === void 0 ? void 0 : entry.source) !== null && _a !== void 0 ? _a : entry === null || entry === void 0 ? void 0 : entry.name;
|
|
335
|
+
return typeof source === "string" ? [providerIdentity(source)] : [];
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
function classifyProviderBinding(source, generatedSources) {
|
|
339
|
+
return generatedSources.includes(providerIdentity(source))
|
|
340
|
+
? "generated"
|
|
341
|
+
: "prebuilt";
|
|
342
|
+
}
|
|
343
|
+
// Public registry addresses are `namespace/name/provider` with plain segments;
|
|
344
|
+
// a dot, colon or `~` in a segment marks a hostname, bucket or home path that
|
|
345
|
+
// go-getter would resolve instead.
|
|
346
|
+
const REGISTRY_SEGMENT = /^[a-z0-9][a-z0-9_-]*$/;
|
|
347
|
+
// Forced getters, URLs and well-known object-store or forge hosts.
|
|
348
|
+
const REMOTE_SOURCE = /^(?:git|hg|s3|gcs)::|^git@|:\/\/|^github\.com\/|^bitbucket\.org\/|amazonaws\.com\/|googleapis\.com\//i;
|
|
349
|
+
// Only public registry sources are sent as-is; anything else could carry a
|
|
350
|
+
// path, hostname, bucket or organization and is reduced to its kind.
|
|
351
|
+
function classifyModuleSource(source) {
|
|
352
|
+
const trimmed = source.trim();
|
|
353
|
+
if ((0, config_2.isLocalModule)(trimmed) || path.isAbsolute(trimmed)) {
|
|
354
|
+
return "local";
|
|
355
|
+
}
|
|
356
|
+
if (REMOTE_SOURCE.test(trimmed)) {
|
|
357
|
+
return "git";
|
|
358
|
+
}
|
|
359
|
+
if (!(0, terraform_module_1.isRegistryModule)(trimmed)) {
|
|
360
|
+
return "other";
|
|
361
|
+
}
|
|
362
|
+
const segments = trimmed.toLowerCase().split("/");
|
|
363
|
+
if (segments.length === 4) {
|
|
364
|
+
return "private-registry";
|
|
365
|
+
}
|
|
366
|
+
return segments.every((segment) => REGISTRY_SEGMENT.test(segment)) &&
|
|
367
|
+
withinIdentityLimits(segments)
|
|
368
|
+
? segments.join("/")
|
|
369
|
+
: "other";
|
|
370
|
+
}
|
|
371
|
+
/** What triggered a synth other than the command itself. */
|
|
372
|
+
exports.SYNTH_ORIGINS = ["watch"];
|
|
373
|
+
// Scalar payload fields forwarded as attributes, per command, each with the
|
|
374
|
+
// type (and where enumerable, the values) it must have. Anything not listed
|
|
375
|
+
// here, of the wrong type or off the value set stays out of the metric.
|
|
376
|
+
const SCALAR_ATTRIBUTES = {
|
|
377
|
+
synth: {
|
|
378
|
+
synthOrigin: {
|
|
379
|
+
attribute: "synth_origin",
|
|
380
|
+
type: "string",
|
|
381
|
+
values: exports.SYNTH_ORIGINS,
|
|
382
|
+
},
|
|
383
|
+
},
|
|
384
|
+
init: {
|
|
385
|
+
// reduced to a built-in template name or "remote" by templateTelemetryName
|
|
386
|
+
template: { attribute: "template", type: "string" },
|
|
387
|
+
isRemote: { attribute: "is_remote", type: "boolean" },
|
|
388
|
+
},
|
|
389
|
+
convert: {
|
|
390
|
+
numberOfModules: { attribute: "module_count", type: "number" },
|
|
391
|
+
numberOfProviders: { attribute: "provider_count", type: "number" },
|
|
392
|
+
convertedLines: { attribute: "converted_lines", type: "number" },
|
|
393
|
+
},
|
|
394
|
+
};
|
|
395
|
+
function scalarAttributeValue(value, spec) {
|
|
396
|
+
if (typeof value !== spec.type) {
|
|
397
|
+
return undefined;
|
|
398
|
+
}
|
|
399
|
+
if (spec.type === "number" && !Number.isFinite(value)) {
|
|
400
|
+
return undefined;
|
|
401
|
+
}
|
|
402
|
+
if (spec.values && !spec.values.includes(value)) {
|
|
403
|
+
return undefined;
|
|
404
|
+
}
|
|
405
|
+
return value;
|
|
406
|
+
}
|
|
407
|
+
// `overrides: { aws_s3_bucket: ["tags", "region"] }` gives { aws_s3_bucket: 2 }
|
|
408
|
+
function groupSizes(group) {
|
|
409
|
+
const sizes = {};
|
|
410
|
+
if (group && typeof group === "object" && !Array.isArray(group)) {
|
|
411
|
+
for (const [key, entries] of Object.entries(group)) {
|
|
412
|
+
sizes[key] = Array.isArray(entries) ? entries.length : 0;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
return sizes;
|
|
416
|
+
}
|
|
417
|
+
function sum(sizes) {
|
|
418
|
+
return Object.values(sizes).reduce((total, size) => total + size, 0);
|
|
419
|
+
}
|
|
420
|
+
// Override keys are provider schema names, except module overrides which
|
|
421
|
+
// carry the module source and are reduced to its kind.
|
|
422
|
+
function overrideResourceType(key) {
|
|
423
|
+
const resourceType = key.startsWith("module.")
|
|
424
|
+
? `module.${classifyModuleSource(key.slice("module.".length))}`
|
|
425
|
+
: key;
|
|
426
|
+
return resourceType.length <= 64 &&
|
|
427
|
+
(RESOURCE_TYPE.test(resourceType) || resourceType.startsWith("module."))
|
|
428
|
+
? resourceType
|
|
429
|
+
: "other";
|
|
430
|
+
}
|
|
431
|
+
// Distinct identities reported per metric and run. A project's size must not
|
|
432
|
+
// decide how many events one run sends, so the rest folds into one event.
|
|
433
|
+
const MAX_STACK_GROUPS = 8;
|
|
434
|
+
const MAX_STACK_PROVIDERS = 32;
|
|
435
|
+
const MAX_STACK_OVERRIDE_TYPES = 32;
|
|
436
|
+
const MAX_BINDING_SOURCES = 32;
|
|
437
|
+
// What an aggregated metric adds to the command attributes, with the type
|
|
438
|
+
// each must have; anything else stays out of the metric.
|
|
439
|
+
const AGGREGATE_ATTRIBUTES = {
|
|
440
|
+
"cli.stack": {
|
|
441
|
+
backend: "string",
|
|
442
|
+
cloud: "boolean",
|
|
443
|
+
library_version: "string",
|
|
444
|
+
override_count: "number",
|
|
445
|
+
import_count: "number",
|
|
446
|
+
moved_count: "number",
|
|
447
|
+
truncated: "boolean",
|
|
448
|
+
},
|
|
449
|
+
"cli.stack.provider": {
|
|
450
|
+
provider: "string",
|
|
451
|
+
version_constraint: "string",
|
|
452
|
+
binding: "string",
|
|
453
|
+
truncated: "boolean",
|
|
454
|
+
},
|
|
455
|
+
"cli.stack.override": {
|
|
456
|
+
resource_type: "string",
|
|
457
|
+
override_count: "number",
|
|
458
|
+
truncated: "boolean",
|
|
459
|
+
},
|
|
460
|
+
"cli.get.provider": { provider: "string", truncated: "boolean" },
|
|
461
|
+
"cli.get.module": { module: "string", truncated: "boolean" },
|
|
462
|
+
"cli.init.provider": { provider: "string", truncated: "boolean" },
|
|
463
|
+
};
|
|
464
|
+
function addSums(target, sums) {
|
|
465
|
+
var _a;
|
|
466
|
+
for (const [name, count] of Object.entries(sums)) {
|
|
467
|
+
target[name] = ((_a = target[name]) !== null && _a !== void 0 ? _a : 0) + count;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
// The identity must hold normalised values only: grouping on a raw source
|
|
471
|
+
// would send one event per distinct private host. A member (a stack) that
|
|
472
|
+
// reaches a group twice is counted once.
|
|
473
|
+
function countInto(groups, member, identity, sums = {}) {
|
|
474
|
+
const key = JSON.stringify(identity);
|
|
475
|
+
let group = groups.get(key);
|
|
476
|
+
if (!group) {
|
|
477
|
+
group = { identity, sums: {}, value: 0 };
|
|
478
|
+
groups.set(key, group);
|
|
479
|
+
}
|
|
480
|
+
if (group.lastMember !== member) {
|
|
481
|
+
group.lastMember = member;
|
|
482
|
+
group.value += 1;
|
|
483
|
+
}
|
|
484
|
+
addSums(group.sums, sums);
|
|
485
|
+
}
|
|
486
|
+
// One counter per group, the most counted first (ties by identity, so the
|
|
487
|
+
// kept set is stable); the groups past `limit` fold into one event without
|
|
488
|
+
// identity, which keeps the metric's total.
|
|
489
|
+
function emitGroups(metric, limit, groups, attributes) {
|
|
490
|
+
const sorted = [...groups.entries()]
|
|
491
|
+
.sort(([keyA, a], [keyB, b]) => b.value - a.value || (keyA < keyB ? -1 : 1))
|
|
492
|
+
.map(([, group]) => group);
|
|
493
|
+
const emitted = sorted.slice(0, limit);
|
|
494
|
+
const folded = sorted.slice(limit);
|
|
495
|
+
if (folded.length > 0) {
|
|
496
|
+
const residual = {
|
|
497
|
+
identity: { truncated: true },
|
|
498
|
+
sums: {},
|
|
499
|
+
value: 0,
|
|
500
|
+
};
|
|
501
|
+
for (const group of folded) {
|
|
502
|
+
residual.value += group.value;
|
|
503
|
+
addSums(residual.sums, group.sums);
|
|
504
|
+
}
|
|
505
|
+
emitted.push(residual);
|
|
506
|
+
}
|
|
507
|
+
const allowed = AGGREGATE_ATTRIBUTES[metric];
|
|
508
|
+
for (const group of emitted) {
|
|
509
|
+
const own = {};
|
|
510
|
+
for (const [name, raw] of Object.entries({
|
|
511
|
+
...group.identity,
|
|
512
|
+
...group.sums,
|
|
513
|
+
})) {
|
|
514
|
+
const value = name in allowed
|
|
515
|
+
? scalarAttributeValue(raw, { type: allowed[name] })
|
|
516
|
+
: undefined;
|
|
517
|
+
if (value !== undefined) {
|
|
518
|
+
own[name] = value;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
Sentry.metrics.count(metric, group.value, {
|
|
522
|
+
attributes: { ...attributes, ...own },
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
// counts and allow-listed kinds only, never names or ids
|
|
527
|
+
function sendStackTelemetry(stackMetadata, requiredProviders, attributes) {
|
|
528
|
+
var _a;
|
|
529
|
+
const generatedSources = (_a = state.generatedProviderSources) !== null && _a !== void 0 ? _a : getGeneratedProviderSources();
|
|
530
|
+
const stacks = new Map();
|
|
531
|
+
const overrides = new Map();
|
|
532
|
+
const providers = new Map();
|
|
533
|
+
stackMetadata.forEach((entry, index) => {
|
|
534
|
+
// a null or non-object entry is not a stack: counting one would inflate
|
|
535
|
+
// the stack count with metadata the library never wrote
|
|
536
|
+
if (!entry || typeof entry !== "object") {
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
const metadata = entry;
|
|
540
|
+
const overrideSizes = groupSizes(metadata.overrides);
|
|
541
|
+
const stack = {
|
|
542
|
+
backend: normalizeBackendKind(metadata.backend),
|
|
543
|
+
cloud: typeof metadata.cloud === "string",
|
|
544
|
+
};
|
|
545
|
+
const libraryVersion = releaseVersion(metadata.version);
|
|
546
|
+
if (libraryVersion) {
|
|
547
|
+
stack.library_version = libraryVersion;
|
|
548
|
+
}
|
|
549
|
+
countInto(stacks, index, stack, {
|
|
550
|
+
override_count: sum(overrideSizes),
|
|
551
|
+
import_count: sum(groupSizes(metadata.imports)),
|
|
552
|
+
moved_count: sum(groupSizes(metadata.moved)),
|
|
553
|
+
});
|
|
554
|
+
for (const [key, count] of Object.entries(overrideSizes)) {
|
|
555
|
+
countInto(overrides, index, { resource_type: overrideResourceType(key) }, { override_count: count });
|
|
556
|
+
}
|
|
557
|
+
const required = requiredProviders[index];
|
|
558
|
+
if (!required || typeof required !== "object") {
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
for (const [type, constraint] of Object.entries(required)) {
|
|
562
|
+
const source = typeof (constraint === null || constraint === void 0 ? void 0 : constraint.source) === "string" ? constraint.source : type;
|
|
563
|
+
const provider = {
|
|
564
|
+
provider: normalizeProviderSource(source),
|
|
565
|
+
};
|
|
566
|
+
if (typeof (constraint === null || constraint === void 0 ? void 0 : constraint.version) === "string") {
|
|
567
|
+
provider.version_constraint = normalizeProviderConstraint(constraint.version);
|
|
568
|
+
}
|
|
569
|
+
provider.binding = classifyProviderBinding(source, generatedSources);
|
|
570
|
+
countInto(providers, index, provider);
|
|
571
|
+
}
|
|
572
|
+
});
|
|
573
|
+
emitGroups("cli.stack", MAX_STACK_GROUPS, stacks, attributes);
|
|
574
|
+
emitGroups("cli.stack.provider", MAX_STACK_PROVIDERS, providers, attributes);
|
|
575
|
+
emitGroups("cli.stack.override", MAX_STACK_OVERRIDE_TYPES, overrides, attributes);
|
|
576
|
+
}
|
|
577
|
+
function sendSourceTelemetry(metric, attribute, sources, normalize, attributes) {
|
|
578
|
+
const groups = new Map();
|
|
579
|
+
sources.forEach((source, index) => countInto(groups, index, { [attribute]: normalize(source) }));
|
|
580
|
+
emitGroups(metric, MAX_BINDING_SOURCES, groups, attributes);
|
|
581
|
+
}
|
|
582
|
+
// targets: one `{ type, source }` per generated binding
|
|
583
|
+
function targetSources(targets, type) {
|
|
584
|
+
return targets
|
|
585
|
+
.filter((target) => (target === null || target === void 0 ? void 0 : target.type) === type)
|
|
586
|
+
.map((target) => target.source);
|
|
587
|
+
}
|
|
588
|
+
async function commandAttributes(command, language) {
|
|
589
|
+
var _a;
|
|
590
|
+
const ci = ci_info_1.default.isCI ? ci_info_1.default.name || "unknown" : false;
|
|
591
|
+
const attributes = {
|
|
592
|
+
command,
|
|
593
|
+
ci: ci === false ? false : ci,
|
|
594
|
+
os: process.platform,
|
|
595
|
+
arch: process.arch,
|
|
596
|
+
...((_a = state.projectTargetAttributes) !== null && _a !== void 0 ? _a : getProjectTargetAttributes()),
|
|
597
|
+
...(await getBinaryAttributes()),
|
|
598
|
+
};
|
|
599
|
+
if (config_2.LANGUAGES.includes(language)) {
|
|
600
|
+
attributes.language = language;
|
|
601
|
+
}
|
|
602
|
+
if (state.packageManager !== undefined) {
|
|
603
|
+
attributes.package_manager = state.packageManager;
|
|
604
|
+
}
|
|
605
|
+
return attributes;
|
|
606
|
+
}
|
|
607
|
+
// Counts the attempt, whatever its outcome. Runs after consent is captured
|
|
608
|
+
// and Sentry initialized; later calls in the same process are no-ops.
|
|
609
|
+
async function startCommandTelemetry(command, projectPath = process.cwd()) {
|
|
610
|
+
if (state.startedCommand !== undefined) {
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
613
|
+
state.startedCommand = command;
|
|
614
|
+
const cdktfJson = readRawCdktfJson(projectPath);
|
|
615
|
+
state.language = cdktfJson.language;
|
|
616
|
+
state.packageManager = detectPackageManager(projectPath, cdktfJson);
|
|
617
|
+
state.generatedProviderSources = getGeneratedProviderSources(projectPath);
|
|
618
|
+
try {
|
|
619
|
+
if (!isUsageTelemetryEnabled()) {
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
622
|
+
const attributes = await commandAttributes(command, state.language);
|
|
623
|
+
Sentry.metrics.count("cli.command.invoked", 1, { attributes });
|
|
624
|
+
}
|
|
625
|
+
catch (err) {
|
|
626
|
+
logging_1.logger.debug(`Could not send telemetry data: ${err}`);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
/** Forgets the started run; tests run many commands in one process. */
|
|
630
|
+
function resetCommandTelemetry() {
|
|
631
|
+
state.startedCommand = undefined;
|
|
632
|
+
state.language = undefined;
|
|
633
|
+
state.packageManager = undefined;
|
|
634
|
+
state.generatedProviderSources = undefined;
|
|
635
|
+
state.stackMetricsSent = undefined;
|
|
636
|
+
}
|
|
637
|
+
// Payload fields reach the attributes only through the allow-lists above.
|
|
638
|
+
// A no-op when usage telemetry is disabled or Sentry is not initialized;
|
|
639
|
+
// `payload.error` counts the run as cli.command.error instead.
|
|
640
|
+
async function sendTelemetry(command, payload) {
|
|
641
|
+
var _a, _b;
|
|
642
|
+
try {
|
|
643
|
+
if (!isUsageTelemetryEnabled()) {
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
const attributes = await commandAttributes(command, (_a = payload.language) !== null && _a !== void 0 ? _a : state.language);
|
|
647
|
+
for (const [key, spec] of Object.entries((_b = SCALAR_ATTRIBUTES[command]) !== null && _b !== void 0 ? _b : {})) {
|
|
648
|
+
const value = scalarAttributeValue(payload[key], spec);
|
|
649
|
+
if (value !== undefined) {
|
|
650
|
+
attributes[spec.attribute] = value;
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
if (payload.error) {
|
|
654
|
+
attributes.error_type = exports.COMMAND_ERROR_TYPES.includes(payload.errorType)
|
|
655
|
+
? payload.errorType
|
|
656
|
+
: "unexpected";
|
|
657
|
+
Sentry.metrics.count("cli.command.error", 1, { attributes });
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
const generated = command === "get" && Array.isArray(payload.targets)
|
|
661
|
+
? {
|
|
662
|
+
providers: targetSources(payload.targets, "provider"),
|
|
663
|
+
modules: targetSources(payload.targets, "module"),
|
|
664
|
+
}
|
|
665
|
+
: undefined;
|
|
666
|
+
const addedProviders = command === "init" && Array.isArray(payload.addedProviders)
|
|
667
|
+
? payload.addedProviders
|
|
668
|
+
: undefined;
|
|
669
|
+
if (generated) {
|
|
670
|
+
attributes.provider_count = generated.providers.length;
|
|
671
|
+
attributes.module_count = generated.modules.length;
|
|
672
|
+
}
|
|
673
|
+
if (addedProviders) {
|
|
674
|
+
attributes.provider_count = addedProviders.length;
|
|
675
|
+
}
|
|
676
|
+
// The run's outcome goes first: nothing in the per-source and stack
|
|
677
|
+
// metrics below can then cost the run its command metric.
|
|
678
|
+
const nested = state.startedCommand !== undefined && state.startedCommand !== command;
|
|
679
|
+
// a run that failed, with or without a failed stack, is not completed: the
|
|
680
|
+
// failure thrown next is counted as cli.command.error by the entrypoint's
|
|
681
|
+
// reporter
|
|
682
|
+
const failedStackCount = typeof payload.failedStackCount === "number"
|
|
683
|
+
? payload.failedStackCount
|
|
684
|
+
: 0;
|
|
685
|
+
if (failedStackCount > 0) {
|
|
686
|
+
Sentry.metrics.count("cli.stack.failed", failedStackCount, {
|
|
687
|
+
attributes,
|
|
688
|
+
});
|
|
689
|
+
}
|
|
690
|
+
else if (!nested && payload.runFailed !== true) {
|
|
691
|
+
Sentry.metrics.count("cli.command.completed", 1, { attributes });
|
|
692
|
+
}
|
|
693
|
+
if (typeof payload.totalTime === "number") {
|
|
694
|
+
Sentry.metrics.distribution("cli.synth.duration", payload.totalTime, {
|
|
695
|
+
unit: "millisecond",
|
|
696
|
+
attributes,
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
if (generated) {
|
|
700
|
+
sendSourceTelemetry("cli.get.provider", "provider", generated.providers, normalizeProviderSource, attributes);
|
|
701
|
+
sendSourceTelemetry("cli.get.module", "module", generated.modules, classifyModuleSource, attributes);
|
|
702
|
+
}
|
|
703
|
+
if (addedProviders) {
|
|
704
|
+
sendSourceTelemetry("cli.init.provider", "provider", addedProviders, normalizeProviderSource, attributes);
|
|
705
|
+
}
|
|
706
|
+
// A synth nested in another command describes every stack of the app;
|
|
707
|
+
// the command reports the stacks it selected, under its own name.
|
|
708
|
+
if (Array.isArray(payload.stackMetadata) &&
|
|
709
|
+
!state.stackMetricsSent &&
|
|
710
|
+
!(nested && command === "synth")) {
|
|
711
|
+
state.stackMetricsSent = true;
|
|
712
|
+
sendStackTelemetry(payload.stackMetadata, Array.isArray(payload.requiredProviders)
|
|
713
|
+
? payload.requiredProviders
|
|
714
|
+
: [], attributes);
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
catch (err) {
|
|
718
|
+
logging_1.logger.debug(`Could not send telemetry data: ${err}`);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVsZW1ldHJ5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3RlbGVtZXRyeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUE2Q0EsNERBV0M7QUFpREQsMERBSUM7QUFxR0QsNERBRUM7QUFJRCw4RUFFQztBQUlELDBEQVFDO0FBSUQsZ0VBc0JDO0FBRUQsZ0VBSUM7QUFtQkQsZ0RBU0M7QUFJRCx3Q0FNQztBQXNhRCxzREFxQkM7QUFHRCxzREFNQztBQUtELHNDQXNIQztBQTMyQkQsK0JBQStCO0FBQy9CLG1DQUFtQztBQUNuQyxxQ0FBZ0Q7QUFDaEQscURBQXVDO0FBQ3ZDLDJDQUE2QjtBQUM3Qiw2Q0FBK0I7QUFDL0IsK0NBQWlDO0FBQ2pDLHNEQUE2QjtBQUM3Qix1Q0FBbUM7QUFDbkMscUNBS2tCO0FBQ2xCLHFDQUEyQztBQUMzQyxpRUFBa0U7QUFDbEUsbURBQStDO0FBQy9DLHlEQUFzRDtBQUN0RCwyQ0FBMkM7QUFLOUIsUUFBQSxtQkFBbUIsR0FBRztJQUNqQyxPQUFPO0lBQ1AsVUFBVTtJQUNWLFVBQVU7SUFDVixZQUFZO0NBQ0osQ0FBQztBQUdYLDRFQUE0RTtBQUM1RSx5Q0FBeUM7QUFDekMsU0FBUyxnQkFBZ0IsQ0FBQyxXQUFtQjtJQUMzQyxJQUFJLENBQUM7UUFDSCxPQUFPLElBQUksQ0FBQyxLQUFLLENBQ2YsRUFBRSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxZQUFZLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FDakUsQ0FBQztJQUNKLENBQUM7SUFBQyxXQUFNLENBQUM7UUFDUCxPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUM7QUFDSCxDQUFDO0FBRUQseURBQXlEO0FBQ3pELFNBQWdCLHdCQUF3QixDQUN0QyxXQUFXLEdBQUcsT0FBTyxDQUFDLEdBQUcsRUFBRTtJQUUzQixNQUFNLFNBQVMsR0FBRyxnQkFB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LEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDeEQsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgKGMpIEhhc2hpQ29ycCwgSW5jXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogTVBMLTIuMFxuaW1wb3J0IHsgbm9ybWFsaXplQ29uc2VudEZsYWcgfSBmcm9tIFwiLi9jb25maWdcIjtcbmltcG9ydCAqIGFzIFNlbnRyeSBmcm9tIFwiQHNlbnRyeS9ub2RlXCI7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgKiBhcyBmcyBmcm9tIFwiZnMtZXh0cmFcIjtcbmltcG9ydCAqIGFzIHNlbXZlciBmcm9tIFwic2VtdmVyXCI7XG5pbXBvcnQgY2lJbmZvIGZyb20gXCJjaS1pbmZvXCI7XG5pbXBvcnQgeyBsb2dnZXIgfSBmcm9tIFwiLi9sb2dnaW5nXCI7XG5pbXBvcnQge1xuICBERUZBVUxUX1RBUkdFVF9WRVJTSU9OUyxcbiAgTGFuZ3VhZ2UsXG4gIExBTkdVQUdFUyxcbiAgaXNMb2NhbE1vZHVsZSxcbn0gZnJvbSBcIi4vY29uZmlnXCI7XG5pbXBvcnQgeyBpc0dyYWRsZVByb2plY3QgfSBmcm9tIFwiLi9ncmFkbGVcIjtcbmltcG9ydCB7IGRldGVjdE5vZGVQYWNrYWdlTWFuYWdlciB9IGZyb20gXCIuL25vZGUtcGFja2FnZS1tYW5hZ2VyXCI7XG5pbXBvcnQgeyBwcm9jZXNzU3RhdGUgfSBmcm9tIFwiLi9wcm9jZXNzLXN0YXRlXCI7XG5pbXBvcnQgeyBpc1JlZ2lzdHJ5TW9kdWxlIH0gZnJvbSBcIi4vdGVycmFmb3JtLW1vZHVsZVwiO1xuaW1wb3J0IHsgdGVycmFmb3JtQ2xpIH0gZnJvbSBcIi4vdGVycmFmb3JtXCI7XG5cbnR5cGUgQXR0cmlidXRlVmFsdWUgPSBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuO1xudHlwZSBBdHRyaWJ1dGVzID0gUmVjb3JkPHN0cmluZywgQXR0cmlidXRlVmFsdWU+O1xuXG5leHBvcnQgY29uc3QgQ09NTUFORF9FUlJPUl9UWVBFUyA9IFtcbiAgXCJVc2FnZVwiLFxuICBcIkV4dGVybmFsXCIsXG4gIFwiSW50ZXJuYWxcIixcbiAgXCJ1bmV4cGVjdGVkXCIsXG5dIGFzIGNvbnN0O1xuZXhwb3J0IHR5cGUgQ29tbWFuZEVycm9yVHlwZSA9ICh0eXBlb2YgQ09NTUFORF9FUlJPUl9UWVBFUylbbnVtYmVyXTtcblxuLy8gTmV2ZXIgdGhyb3dzOiB0ZWxlbWV0cnkgYWxzbyBydW5zIG91dHNpZGUgYSBwcm9qZWN0LiBSYXcsIGJlY2F1c2UgY29tbW9uc1xuLy8gY2Fubm90IGltcG9ydCBjbGktY29yZSdzIHR5cGVkIGNvbmZpZy5cbmZ1bmN0aW9uIHJlYWRSYXdDZGt0Zkpzb24ocHJvamVjdFBhdGg6IHN0cmluZyk6IFJlY29yZDxzdHJpbmcsIGFueT4ge1xuICB0cnkge1xuICAgIHJldHVybiBKU09OLnBhcnNlKFxuICAgICAgZnMucmVhZEZpbGVTeW5jKHBhdGgucmVzb2x2ZShwcm9qZWN0UGF0aCwgXCJjZGt0Zi5qc29uXCIpLCBcInV0ZjhcIiksXG4gICAgKTtcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIHt9O1xuICB9XG59XG5cbi8vIHVuZGVmaW5lZDogdW5zZXQsIG1hbGZvcm1lZCwgb3Igbm8gcmVhZGFibGUgY2RrdGYuanNvblxuZXhwb3J0IGZ1bmN0aW9uIGdldFVzYWdlVGVsZW1ldHJ5Q29uc2VudChcbiAgcHJvamVjdFBhdGggPSBwcm9jZXNzLmN3ZCgpLFxuKTogYm9vbGVhbiB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IGNka3RmSnNvbiA9IHJlYWRSYXdDZGt0Zkpzb24ocHJvamVjdFBhdGgpO1xuICBpZiAoIShcInNlbmRVc2FnZVRlbGVtZXRyeVwiIGluIGNka3RmSnNvbikpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG4gIHJldHVybiBub3JtYWxpemVDb25zZW50RmxhZyhcbiAgICBcInNlbmRVc2FnZVRlbGVtZXRyeVwiLFxuICAgIGNka3RmSnNvbi5zZW5kVXNhZ2VUZWxlbWV0cnksXG4gICk7XG59XG5cbnR5cGUgQ29tbWFuZFRlbGVtZXRyeVN0YXRlID0ge1xuICAvLyBDYXB0dXJlZCBieSBpbml0aWFsaXpFcnJvclJlcG9ydGluZyAoY2xpLWNvcmUpIHdoaWxlIHN0aWxsIGluIHRoZSB1c2VyJ3NcbiAgLy8gY3dkOiBgY29udmVydGAgY2hkaXJzIGludG8gYSB0aHJvd2F3YXkgcHJvamVjdCBiZWZvcmUgZW1pdHRpbmcsIHNvXG4gIC8vIHJlLXJlYWRpbmcgY2RrdGYuanNvbiBhdCBlbWlzc2lvbiB0aW1lIHdvdWxkIGNvbnN1bHQgdGhlIHdyb25nIHByb2plY3QuXG4gIHVzYWdlVGVsZW1ldHJ5RW5hYmxlZD86IGJvb2xlYW47XG4gIC8vIFRoZSBjb21tYW5kIHRoaXMgcnVuIHdhcyBzdGFydGVkIGFzOyBzZXQgb25jZSBieSBzdGFydENvbW1hbmRUZWxlbWV0cnkgc29cbiAgLy8gdGhlIG9wZXJhdGlvbnMgYSBjb21tYW5kIGRyaXZlcyAoYSBkZXBsb3kncyBzeW50aCwgdGhlIGdldCBvZiBpbml0IG9yXG4gIC8vIHByb3ZpZGVyIGFkZCkgbmV2ZXIgY291bnQgYXMgcnVucy5cbiAgc3RhcnRlZENvbW1hbmQ/OiBzdHJpbmc7XG4gIC8vIFRoZSByYXcgYGxhbmd1YWdlYCBvZiB0aGUgcHJvamVjdCB0aGUgcnVuIHN0YXJ0ZWQgaW4sIHNvIGV2ZXJ5IG1ldHJpYyBvZlxuICAvLyB0aGUgcnVuICh0aGUgZXJyb3IgbWV0cmljIGhhcyBubyBwYXlsb2FkKSBjYXJyaWVzIHRoZSBvbmUgYGludm9rZWRgIGRpZC5cbiAgbGFuZ3VhZ2U/OiB1bmtub3duO1xuICAvLyBkZXRlY3RlZCBpbiB0aGUgcHJvamVjdCB0aGUgcnVuIHN0YXJ0ZWQgaW4sIGZvciB0aGUgc2FtZSByZWFzb25cbiAgcGFja2FnZU1hbmFnZXI/OiBQYWNrYWdlTWFuYWdlcjtcbiAgLy8gY2FwdHVyZWQgd2l0aCB0aGUgY29uc2VudCBkZWNpc2lvbiwgZm9yIHRoZSBzYW1lIHJlYXNvblxuICBwcm9qZWN0VGFyZ2V0QXR0cmlidXRlcz86IEF0dHJpYnV0ZXM7XG4gIC8vIENhcHR1cmVkIGF0IHN0YXJ0IGxpa2UgYGxhbmd1YWdlYDogdGhlIGJpbmRpbmdzIHRoZSBzdGFydGVkIHByb2plY3RcbiAgLy8gZ2VuZXJhdGVzLCB3aGF0ZXZlciBkaXJlY3RvcnkgdGhlIHJ1biBpcyBpbiB3aGVuIGl0IHJlcG9ydHMgaXRzIHN0YWNrcy5cbiAgZ2VuZXJhdGVkUHJvdmlkZXJTb3VyY2VzPzogc3RyaW5nW107XG4gIC8vIEEgcnVuIHJlcG9ydHMgaXRzIHN0YWNrcyBvbmNlOiBhIHdhdGNoIHNlc3Npb24gcmVkZXBsb3lzIHRoZSBzYW1lIGFwcFxuICAvLyBmb3IgaG91cnMgYW5kIHdvdWxkIHJlcGVhdCB0aGVtIG9uIGV2ZXJ5IGZpbGUgY2hhbmdlLlxuICBzdGFja01ldHJpY3NTZW50PzogYm9vbGVhbjtcbn07XG5cbi8vIFNoYXJlZCBieSBib3RoIGJ1bmRsZSBjb3BpZXM6IHRoZSBoYW5kbGVycycgY29weSBjYXB0dXJlcyB0aGUgZGVjaXNpb24gYW5kXG4vLyBzdGFydHMgdGhlIHJ1biwgdGhlIGVudHJ5cG9pbnQncyBjb3B5IGNvdW50cyB0aGUgZmFpbHVyZS5cbmNvbnN0IHN0YXRlID0gcHJvY2Vzc1N0YXRlPENvbW1hbmRUZWxlbWV0cnlTdGF0ZT4oXG4gIFwiY2RrdG4uY29tbWFuZFRlbGVtZXRyeVwiLFxuICAoKSA9PiAoe30pLFxuKTtcblxuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfTUFOQUdFUlMgPSBbXG4gIFwibnBtXCIsXG4gIFwicG5wbVwiLFxuICBcInlhcm5cIixcbiAgXCJ5YXJuLWJlcnJ5XCIsXG4gIFwicGlwXCIsXG4gIFwicGlwZW52XCIsXG4gIFwibWF2ZW5cIixcbiAgXCJncmFkbGVcIixcbiAgXCJudWdldFwiLFxuICBcImdvXCIsXG5dIGFzIGNvbnN0O1xuZXhwb3J0IHR5cGUgUGFja2FnZU1hbmFnZXIgPSAodHlwZW9mIFBBQ0tBR0VfTUFOQUdFUlMpW251bWJlcl07XG5cbi8vIE9ubHkgbWVtYmVycyBvZiB0aGUgY2xvc2VkIHNldCBiZWNvbWUgYW4gYXR0cmlidXRlOiBhIGBwYWNrYWdlTWFuYWdlcmBcbi8vIGZpZWxkIGNhcnJpZXMgYSB2ZXJzaW9uIGFuZCBhIGhhc2gsIGFuZCBhIGRldGVjdG9yIG1heSBncm93IG5ldyB2YWx1ZXMuXG5leHBvcnQgZnVuY3Rpb24gbm9ybWFsaXplUGFja2FnZU1hbmFnZXIoXG4gIHZhbHVlOiB1bmtub3duLFxuKTogUGFja2FnZU1hbmFnZXIgfCB1bmRlZmluZWQge1xuICByZXR1cm4gUEFDS0FHRV9NQU5BR0VSUy5maW5kKChuYW1lKSA9PiBuYW1lID09PSB2YWx1ZSk7XG59XG5cbi8vIFRoZSBwYWNrYWdlIG1hbmFnZXIgYHByb3ZpZGVyIGFkZGAgd291bGQgZHJpdmUsIGRlY2lkZWQgdGhlIHdheSBjbGktY29yZSdzXG4vLyBQYWNrYWdlTWFuYWdlci5mb3JMYW5ndWFnZSBkb2VzLiB1bmRlZmluZWQgb3V0c2lkZSBhIHN1cHBvcnRlZCBwcm9qZWN0LlxuZnVuY3Rpb24gZGV0ZWN0UGFja2FnZU1hbmFnZXIoXG4gIHByb2plY3RQYXRoOiBzdHJpbmcsXG4gIGNka3RmSnNvbjogUmVjb3JkPHN0cmluZywgYW55Pixcbik6IFBhY2thZ2VNYW5hZ2VyIHwgdW5kZWZpbmVkIHtcbiAgdHJ5IHtcbiAgICBzd2l0Y2ggKGNka3RmSnNvbi5sYW5ndWFnZSkge1xuICAgICAgY2FzZSBMYW5ndWFnZS5UWVBFU0NSSVBUOlxuICAgICAgICByZXR1cm4gbm9ybWFsaXplUGFja2FnZU1hbmFnZXIoZGV0ZWN0Tm9kZVBhY2thZ2VNYW5hZ2VyKHByb2plY3RQYXRoKSk7XG4gICAgICBjYXNlIExhbmd1YWdlLlBZVEhPTjpcbiAgICAgICAgaWYgKHR5cGVvZiBjZGt0Zkpzb24uYXBwICE9PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY2RrdGZKc29uLmFwcC5pbmNsdWRlcyhcInBpcGVudlwiKSA/IFwicGlwZW52XCIgOiBcInBpcFwiO1xuICAgICAgY2FzZSBMYW5ndWFnZS5KQVZBOlxuICAgICAgICByZXR1cm4gaXNHcmFkbGVQcm9qZWN0KHByb2plY3RQYXRoKSA/IFwiZ3JhZGxlXCIgOiBcIm1hdmVuXCI7XG4gICAgICBjYXNlIExhbmd1YWdlLkNTSEFSUDpcbiAgICAgICAgcmV0dXJuIFwibnVnZXRcIjtcbiAgICAgIGNhc2UgTGFuZ3VhZ2UuR086XG4gICAgICAgIHJldHVybiBcImdvXCI7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgbG9nZ2VyLmRlYnVnKGBDb3VsZCBub3QgZGV0ZWN0IHRoZSBwYWNrYWdlIG1hbmFnZXI6ICR7ZXJyfWApO1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn1cblxuLy8gRnJlZS10ZXh0IHBheWxvYWQgZmllbGRzIGFyZSB2YWxpZGF0ZWQgYmVmb3JlIHRoZXkgYmVjb21lIGF0dHJpYnV0ZXMgc28gYVxuLy8gbWlzY29uZmlndXJlZCBvciBoYW5kLWVkaXRlZCB2YWx1ZSBuZXZlciBjYXJyaWVzIGFyYml0cmFyeSB0ZXh0LlxuY29uc3QgQ09OU1RSQUlOVF9QQVJUID0gL14oPXwhPXw+PXw8PXw+fDx8fj4pP1xccyooXFxkKyg/OlxcLlxcZCspezAsMn0pJC87XG5jb25zdCBSRUxFQVNFX1ZFUlNJT04gPSAvXlxcZCtcXC5cXGQrXFwuXFxkKy87XG5cbi8vIFRlcnJhZm9ybSdzIGJ1aWx0LWluIGJhY2tlbmQga2luZHM7IGFueXRoaW5nIGVsc2UgaXMgc2VudCBhcyBcIm90aGVyXCJcbmNvbnN0IEJBQ0tFTkRfS0lORFMgPSBbXG4gIFwibG9jYWxcIixcbiAgXCJyZW1vdGVcIixcbiAgXCJjbG91ZFwiLFxuICBcInMzXCIsXG4gIFwiZ2NzXCIsXG4gIFwiYXp1cmVybVwiLFxuICBcImh0dHBcIixcbiAgXCJjb25zdWxcIixcbiAgXCJrdWJlcm5ldGVzXCIsXG4gIFwicGdcIixcbiAgXCJvc3NcIixcbiAgXCJjb3NcIixcbiAgXCJldGNkdjNcIixcbiAgXCJhcnRpZmFjdG9yeVwiLFxuICBcInN3aWZ0XCIsXG4gIFwibWFudGFcIixcbl07XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZUJhY2tlbmRLaW5kKGJhY2tlbmQ6IHVua25vd24pOiBzdHJpbmcge1xuICBpZiAodHlwZW9mIGJhY2tlbmQgIT09IFwic3RyaW5nXCIpIHtcbiAgICByZXR1cm4gXCJ1bmtub3duXCI7XG4gIH1cbiAgcmV0dXJuIEJBQ0tFTkRfS0lORFMuaW5jbHVkZXMoYmFja2VuZCkgPyBiYWNrZW5kIDogXCJvdGhlclwiO1xufVxuXG4vLyBUZXJyYWZvcm0gcmVzb3VyY2UgdHlwZSBncmFtbWFyOyB0aGUgc3RhY2stbGV2ZWwgb3ZlcnJpZGUga2V5cyAoc3RhY2ssXG4vLyBiYWNrZW5kLCBvdXRwdXQsIGxvY2FsLCB0ZXJyYWZvcm1fcmVtb3RlX3N0YXRlKSBhcmUgaWRlbnRpZmllcnMgdG9vLlxuY29uc3QgUkVTT1VSQ0VfVFlQRSA9IC9eW2Etel1bYS16MC05X10qJC87XG5cbi8vIE1BSk9SLk1JTk9SLlBBVENIIG9ubHk6IHByZXJlbGVhc2UgYW5kIGJ1aWxkIGlkZW50aWZpZXJzIGFyZSBmcmVlIHRleHRcbi8vIChhIHdyYXBwZXIncyB2ZXJzaW9uIGxpbmUgb3IgYSBsb2NhbGx5IGJ1aWx0IGxpYnJhcnkgY2FuIGNhcnJ5IGFueXRoaW5nKS5cbmZ1bmN0aW9uIHJlbGVhc2VWZXJzaW9uKHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICByZXR1cm4gUkVMRUFTRV9WRVJTSU9OLmV4ZWModmFsdWUgPz8gXCJcIik/LlswXTtcbn1cblxuLy8gTm9ybWFsaXplZCBzbyBzcGFjaW5nIHZhcmlhbnRzIGNvbGxhcHNlIGludG8gb25lIHZhbHVlLiBIeXBoZW4gcmFuZ2VzIGFyZVxuLy8gd3JpdHRlbiBcIiAtIFwiLCBzbyBhIGh5cGhlbiByaWdodCBhZnRlciBhIGRpZ2l0IGlzIGFsd2F5cyBhIHByZXJlbGVhc2U6XG4vLyBmcmVlIHRleHQgKHNlZSByZWxlYXNlVmVyc2lvbiksIHdoaWNoIHJlamVjdHMgdGhlIHJhbmdlLlxuZnVuY3Rpb24gc2VtdmVyUmFuZ2VPckludmFsaWQodmFsdWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHJhbmdlID0gdmFsdWUubGVuZ3RoIDw9IDY0ID8gc2VtdmVyLnZhbGlkUmFuZ2UodmFsdWUpIDogbnVsbDtcbiAgcmV0dXJuIHJhbmdlICYmICEvXFxkWy0rXS8udGVzdCh2YWx1ZSkgPyByYW5nZSA6IFwiaW52YWxpZFwiO1xufVxuXG4vLyBSZS1qb2luZWQgYXMgXCJ+PiA1LjAsICE9IDUuMS4wXCIgc28gc3BhY2luZyB2YXJpYW50cyBhcmUgb25lIHZhbHVlLiBUaGVcbi8vIGNvbnN0cmFpbnQgaXMgdXNlci1hdXRob3JlZCwgc28gYSBwcmVyZWxlYXNlIGlkZW50aWZpZXIgb3IgYW4gb3Zlci1sb25nXG4vLyB2YWx1ZSByZWplY3RzIGl0IHdob2xlLlxuZnVuY3Rpb24gbm9ybWFsaXplUHJvdmlkZXJDb25zdHJhaW50KHZhbHVlOiBzdHJpbmcpOiBzdHJpbmcge1xuICBpZiAodmFsdWUubGVuZ3RoID4gNjQpIHtcbiAgICByZXR1cm4gXCJpbnZhbGlkXCI7XG4gIH1cbiAgY29uc3QgcGFydHM6IHN0cmluZ1tdID0gW107XG4gIGZvciAoY29uc3QgcGFydCBvZiB2YWx1ZS5zcGxpdChcIixcIikpIHtcbiAgICBjb25zdCBtYXRjaCA9IENPTlNUUkFJTlRfUEFSVC5leGVjKHBhcnQudHJpbSgpKTtcbiAgICBpZiAoIW1hdGNoKSB7XG4gICAgICByZXR1cm4gXCJpbnZhbGlkXCI7XG4gICAgfVxuICAgIGNvbnN0IFssIG9wZXJhdG9yLCB2ZXJzaW9uXSA9IG1hdGNoO1xuICAgIHBhcnRzLnB1c2gob3BlcmF0b3IgPyBgJHtvcGVyYXRvcn0gJHt2ZXJzaW9ufWAgOiB2ZXJzaW9uKTtcbiAgfVxuICByZXR1cm4gcGFydHMuam9pbihcIiwgXCIpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2V0VXNhZ2VUZWxlbWV0cnlFbmFibGVkKGVuYWJsZWQ6IGJvb2xlYW4gfCB1bmRlZmluZWQpOiB2b2lkIHtcbiAgc3RhdGUudXNhZ2VUZWxlbWV0cnlFbmFibGVkID0gZW5hYmxlZDtcbn1cblxuLy8gT25jZSBjYXB0dXJlZCwgdGhlIGRlY2lzaW9uIHN0YW5kcyBmb3IgdGhlIHByb2Nlc3M7IHJlcG9ydGluZyBpcyBub3Rcbi8vIGluaXRpYWxpemVkIGEgc2Vjb25kIHRpbWUuXG5leHBvcnQgZnVuY3Rpb24gaGFzQ2FwdHVyZWRVc2FnZVRlbGVtZXRyeURlY2lzaW9uKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gc3RhdGUudXNhZ2VUZWxlbWV0cnlFbmFibGVkICE9PSB1bmRlZmluZWQ7XG59XG5cbi8vIFByZWNlZGVuY2U6IENIRUNLUE9JTlRfRElTQUJMRSA+IHRoZSBkZWNpc2lvbiBjYXB0dXJlZCBhdCBjb21tYW5kIHN0YXJ0ID5cbi8vIGBzZW5kVXNhZ2VUZWxlbWV0cnlgIGluIGNka3RmLmpzb24gPiBlbmFibGVkLlxuZXhwb3J0IGZ1bmN0aW9uIGlzVXNhZ2VUZWxlbWV0cnlFbmFibGVkKHByb2plY3RQYXRoID0gcHJvY2Vzcy5jd2QoKSk6IGJvb2xlYW4ge1xuICBpZiAocHJvY2Vzcy5lbnYuQ0hFQ0tQT0lOVF9ESVNBQkxFKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGlmIChzdGF0ZS51c2FnZVRlbGVtZXRyeUVuYWJsZWQgIT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiBzdGF0ZS51c2FnZVRlbGVtZXRyeUVuYWJsZWQ7XG4gIH1cbiAgcmV0dXJuIGdldFVzYWdlVGVsZW1ldHJ5Q29uc2VudChwcm9qZWN0UGF0aCkgIT09IGZhbHNlO1xufVxuXG4vLyBGYWxscyBiYWNrIHRvIHRoZSBDTEkgZGVmYXVsdHMsIHNvIGV2ZXJ5IG1ldHJpYyBjYXJyaWVzIHRoZSByYW5nZXMgdGhlXG4vLyBjb21tYW5kIHZhbGlkYXRlZCBhZ2FpbnN0LlxuZXhwb3J0IGZ1bmN0aW9uIGdldFByb2plY3RUYXJnZXRBdHRyaWJ1dGVzKFxuICBwcm9qZWN0UGF0aCA9IHByb2Nlc3MuY3dkKCksXG4pOiBBdHRyaWJ1dGVzIHtcbiAgY29uc3QgY2RrdGZKc29uID0gcmVhZFJhd0Nka3RmSnNvbihwcm9qZWN0UGF0aCk7XG4gIGNvbnN0IGRlY2xhcmVkID1cbiAgICBjZGt0Zkpzb24udGFyZ2V0VmVyc2lvbnMgJiZcbiAgICB0eXBlb2YgY2RrdGZKc29uLnRhcmdldFZlcnNpb25zID09PSBcIm9iamVjdFwiICYmXG4gICAgIUFycmF5LmlzQXJyYXkoY2RrdGZKc29uLnRhcmdldFZlcnNpb25zKVxuICAgICAgPyBjZGt0Zkpzb24udGFyZ2V0VmVyc2lvbnNcbiAgICAgIDogdW5kZWZpbmVkO1xuICBjb25zdCB0YXJnZXRzOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IGRlY2xhcmVkID8/IERFRkFVTFRfVEFSR0VUX1ZFUlNJT05TO1xuICBjb25zdCBhdHRyaWJ1dGVzOiBBdHRyaWJ1dGVzID0ge1xuICAgIHRhcmdldHNfZGVjbGFyZWQ6IGRlY2xhcmVkICE9PSB1bmRlZmluZWQsXG4gICAgdmFsaWRhdGVfaW5zdGFsbGVkX2JpbmFyeTogY2RrdGZKc29uLnZhbGlkYXRlSW5zdGFsbGVkQmluYXJ5ID09PSB0cnVlLFxuICB9O1xuICBpZiAodHlwZW9mIHRhcmdldHMudGVycmFmb3JtID09PSBcInN0cmluZ1wiKSB7XG4gICAgYXR0cmlidXRlcy50YXJnZXRfdGVycmFmb3JtID0gc2VtdmVyUmFuZ2VPckludmFsaWQodGFyZ2V0cy50ZXJyYWZvcm0pO1xuICB9XG4gIGlmICh0eXBlb2YgdGFyZ2V0cy5vcGVudG9mdSA9PT0gXCJzdHJpbmdcIikge1xuICAgIGF0dHJpYnV0ZXMudGFyZ2V0X29wZW50b2Z1ID0gc2VtdmVyUmFuZ2VPckludmFsaWQodGFyZ2V0cy5vcGVudG9mdSk7XG4gIH1cbiAgcmV0dXJuIGF0dHJpYnV0ZXM7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRQcm9qZWN0VGFyZ2V0QXR0cmlidXRlcyhcbiAgYXR0cmlidXRlczogQXR0cmlidXRlcyB8IHVuZGVmaW5lZCxcbik6IHZvaWQge1xuICBzdGF0ZS5wcm9qZWN0VGFyZ2V0QXR0cmlidXRlcyA9IGF0dHJpYnV0ZXM7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldEJpbmFyeUF0dHJpYnV0ZXMoKTogUHJvbWlzZTxBdHRyaWJ1dGVzPiB7XG4gIGNvbnN0IGNsaSA9IGF3YWl0IHRlcnJhZm9ybUNsaSgpO1xuICBjb25zdCBhdHRyaWJ1dGVzOiBBdHRyaWJ1dGVzID0geyBiaW5hcnk6IGNsaS5uYW1lIH07XG4gIC8vIGFuIHVucmVjb2duaXNlZCBwcm9kdWN0J3MgdmVyc2lvbiBpcyB0aGUgZmlyc3QgdmVyc2lvbi1saWtlIHRva2VuIG9mXG4gIC8vIGl0cyBvdXRwdXQsIHdoaWNoIGNhbiBiZSBhbnl0aGluZyAoYSB3cmFwcGVyJ3MgXCJjb25uZWN0ZWQgdG8gMTAuMC4wLjFcIilcbiAgY29uc3QgcmVsZWFzZSA9XG4gICAgY2xpLm5hbWUgPT09IFwidGVycmFmb3JtXCIgfHwgY2xpLm5hbWUgPT09IFwib3BlbnRvZnVcIlxuICAgICAgPyByZWxlYXNlVmVyc2lvbihjbGkudmVyc2lvbilcbiAgICAgIDogdW5kZWZpbmVkO1xuICBpZiAocmVsZWFzZSkge1xuICAgIGF0dHJpYnV0ZXMuYmluYXJ5X3ZlcnNpb24gPSByZWxlYXNlO1xuICB9XG4gIHJldHVybiBhdHRyaWJ1dGVzO1xufVxuXG4vLyBCeSB0eXBlIGFuZCBjb21tYW5kIG9ubHk6IG1lc3NhZ2UgYW5kIGNvbnRleHQgY2FuIGNhcnJ5IHBhdGhzIGFuZCB1c2VyXG4vLyBpbnB1dC5cbmV4cG9ydCBmdW5jdGlvbiBzZW5kRXJyb3JUZWxlbWV0cnkodHlwZTogc3RyaW5nLCBjb21tYW5kOiBzdHJpbmcpOiB2b2lkIHtcbiAgdHJ5IHtcbiAgICBpZiAoIWlzVXNhZ2VUZWxlbWV0cnlFbmFibGVkKCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgU2VudHJ5Lm1ldHJpY3MuY291bnQoXCJjbGkuZXJyb3JcIiwgMSwgeyBhdHRyaWJ1dGVzOiB7IHR5cGUsIGNvbW1hbmQgfSB9KTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgbG9nZ2VyLmRlYnVnKGBDb3VsZCBub3Qgc2VuZCBlcnJvciB0ZWxlbWV0cnk6ICR7ZXJyfWApO1xuICB9XG59XG5cbi8vIENhbGwgYmVmb3JlIGFuIGV4cGxpY2l0IHByb2Nlc3MuZXhpdCgpOiBTZW50cnkgYnVmZmVycyBhc3luY2hyb25vdXNseSBhbmRcbi8vIGEgaGFyZCBleGl0IGRyb3BzIHRoZSBidWZmZXIuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZmx1c2hUZWxlbWV0cnkodGltZW91dE1zID0gNDAwMCk6IFByb21pc2U8dm9pZD4ge1xuICB0cnkge1xuICAgIGF3YWl0IFNlbnRyeS5mbHVzaCh0aW1lb3V0TXMpO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBsb2dnZXIuZGVidWcoYENvdWxkIG5vdCBmbHVzaCB0ZWxlbWV0cnk6ICR7ZXJyfWApO1xuICB9XG59XG5cbmNvbnN0IFBVQkxJQ19QUk9WSURFUl9SRUdJU1RSSUVTID0gW1xuICBcInJlZ2lzdHJ5LnRlcnJhZm9ybS5pb1wiLFxuICBcInJlZ2lzdHJ5Lm9wZW50b2Z1Lm9yZ1wiLFxuXTtcbmNvbnN0IFBST1ZJREVSX1NFR01FTlQgPSAvXlthLXowLTldW2EtejAtOV8tXSokLztcbmNvbnN0IFBST1ZJREVSX0hPU1QgPSAvXihsb2NhbGhvc3R8W2EtejAtOS1dKyhcXC5bYS16MC05LV0rKSspKDpcXGQrKT8kLztcblxuLy8gUmVnaXN0cnkgaWRlbnRpdGllcyBhcmUgYm91bmRlZCBzbyBhbiBvdmVyLWxvbmcgaGFuZC13cml0dGVuIHNvdXJjZSBjYW5ub3Rcbi8vIGNhcnJ5IGZyZWUgdGV4dCB0aHJvdWdoIHRoZSBzZWdtZW50IGdyYW1tYXIuXG5mdW5jdGlvbiB3aXRoaW5JZGVudGl0eUxpbWl0cyhzZWdtZW50czogc3RyaW5nW10pOiBib29sZWFuIHtcbiAgcmV0dXJuIChcbiAgICBzZWdtZW50cy5ldmVyeSgoc2VnbWVudCkgPT4gc2VnbWVudC5sZW5ndGggPD0gNjQpICYmXG4gICAgc2VnbWVudHMuam9pbihcIi9cIikubGVuZ3RoIDw9IDEyOFxuICApO1xufVxuXG4vLyBPbmx5IGEgcHVibGljLXJlZ2lzdHJ5IGBuYW1lc3BhY2UvdHlwZWAgaXMgc2VudCAoYGF3c2AsIGBoYXNoaWNvcnAvYXdzQH4+NWBcbi8vIGFuZCBgcmVnaXN0cnkudGVycmFmb3JtLmlvL2hhc2hpY29ycC9hd3NgIGFyZSBvbmUpOyBvdGhlciBob3N0cyBiZWNvbWVcbi8vIFwicHJpdmF0ZS1yZWdpc3RyeVwiLCBwYXRocyBhbmQgbWFsZm9ybWVkIGlucHV0IFwib3RoZXJcIi5cbmZ1bmN0aW9uIG5vcm1hbGl6ZVByb3ZpZGVyU291cmNlKHNvdXJjZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3Qgc2VnbWVudHMgPSBzb3VyY2UudHJpbSgpLnRvTG93ZXJDYXNlKCkuc3BsaXQoXCJAXCIpWzBdLnNwbGl0KFwiL1wiKTtcbiAgaWYgKHNlZ21lbnRzLmxlbmd0aCA9PT0gMykge1xuICAgIGNvbnN0IGhvc3QgPSBzZWdtZW50cy5zaGlmdCgpITtcbiAgICBpZiAoIVBVQkxJQ19QUk9WSURFUl9SRUdJU1RSSUVTLmluY2x1ZGVzKGhvc3QpKSB7XG4gICAgICByZXR1cm4gUFJPVklERVJfSE9TVC50ZXN0KGhvc3QpID8gXCJwcml2YXRlLXJlZ2lzdHJ5XCIgOiBcIm90aGVyXCI7XG4gICAgfVxuICB9XG4gIGlmIChzZWdtZW50cy5sZW5ndGggPT09IDEpIHtcbiAgICBzZWdtZW50cy51bnNoaWZ0KFwiaGFzaGljb3JwXCIpO1xuICB9XG4gIHJldHVybiBzZWdtZW50cy5sZW5ndGggPT09IDIgJiZcbiAgICBzZWdtZW50cy5ldmVyeSgocykgPT4gUFJPVklERVJfU0VHTUVOVC50ZXN0KHMpKSAmJlxuICAgIHdpdGhpbklkZW50aXR5TGltaXRzKHNlZ21lbnRzKVxuICAgID8gc2VnbWVudHMuam9pbihcIi9cIilcbiAgICA6IFwib3RoZXJcIjtcbn1cblxuLy8gQ29tcGFyaXNvbiBrZXkgZm9yIGdlbmVyYXRlZC12cy1wcmVidWlsdCwgbmV2ZXIgc2VudDogcHVibGljIHNvdXJjZXNcbi8vIG5vcm1hbGl6ZSwgYW55dGhpbmcgZWxzZSBzdGF5cyByYXcgc28gdHdvIHVucmVsYXRlZCBwcml2YXRlIHNvdXJjZXMgKGJvdGhcbi8vIFwicHJpdmF0ZS1yZWdpc3RyeVwiIG9uIHRoZSBtZXRyaWMpIG5ldmVyIG1hdGNoIGVhY2ggb3RoZXIuXG5mdW5jdGlvbiBwcm92aWRlcklkZW50aXR5KHNvdXJjZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3Qgbm9ybWFsaXplZCA9IG5vcm1hbGl6ZVByb3ZpZGVyU291cmNlKHNvdXJjZSk7XG4gIHJldHVybiBub3JtYWxpemVkID09PSBcInByaXZhdGUtcmVnaXN0cnlcIiB8fCBub3JtYWxpemVkID09PSBcIm90aGVyXCJcbiAgICA/IHNvdXJjZS50cmltKCkudG9Mb3dlckNhc2UoKS5zcGxpdChcIkBcIilbMF1cbiAgICA6IG5vcm1hbGl6ZWQ7XG59XG5cbi8vIEZyb20gYHRlcnJhZm9ybVByb3ZpZGVyc2AgaW4gY2RrdGYuanNvbiAoYFwiYXdzQH4+NS4wXCJgIHN0cmluZ3Mgb3Jcbi8vIGB7IG5hbWUsIHNvdXJjZSB9YCBvYmplY3RzKTsgYSBzdGFjayBwcm92aWRlciBub3QgbGlzdGVkIHRoZXJlIGlzIHByZWJ1aWx0LlxuZnVuY3Rpb24gZ2V0R2VuZXJhdGVkUHJvdmlkZXJTb3VyY2VzKHByb2plY3RQYXRoID0gcHJvY2Vzcy5jd2QoKSk6IHN0cmluZ1tdIHtcbiAgY29uc3QgZW50cmllcyA9IHJlYWRSYXdDZGt0Zkpzb24ocHJvamVjdFBhdGgpLnRlcnJhZm9ybVByb3ZpZGVycztcbiAgaWYgKCFBcnJheS5pc0FycmF5KGVudHJpZXMpKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG4gIHJldHVybiBlbnRyaWVzLmZsYXRNYXAoKGVudHJ5KSA9PiB7XG4gICAgaWYgKHR5cGVvZiBlbnRyeSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgcmV0dXJuIFtwcm92aWRlcklkZW50aXR5KGVudHJ5KV07XG4gICAgfVxuICAgIGNvbnN0IHNvdXJjZSA9IGVudHJ5Py5zb3VyY2UgPz8gZW50cnk/Lm5hbWU7XG4gICAgcmV0dXJuIHR5cGVvZiBzb3VyY2UgPT09IFwic3RyaW5nXCIgPyBbcHJvdmlkZXJJZGVudGl0eShzb3VyY2UpXSA6IFtdO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gY2xhc3NpZnlQcm92aWRlckJpbmRpbmcoXG4gIHNvdXJjZTogc3RyaW5nLFxuICBnZW5lcmF0ZWRTb3VyY2VzOiBzdHJpbmdbXSxcbik6IFwiZ2VuZXJhdGVkXCIgfCBcInByZWJ1aWx0XCIge1xuICByZXR1cm4gZ2VuZXJhdGVkU291cmNlcy5pbmNsdWRlcyhwcm92aWRlcklkZW50aXR5KHNvdXJjZSkpXG4gICAgPyBcImdlbmVyYXRlZFwiXG4gICAgOiBcInByZWJ1aWx0XCI7XG59XG5cbi8vIFB1YmxpYyByZWdpc3RyeSBhZGRyZXNzZXMgYXJlIGBuYW1lc3BhY2UvbmFtZS9wcm92aWRlcmAgd2l0aCBwbGFpbiBzZWdtZW50cztcbi8vIGEgZG90LCBjb2xvbiBvciBgfmAgaW4gYSBzZWdtZW50IG1hcmtzIGEgaG9zdG5hbWUsIGJ1Y2tldCBvciBob21lIHBhdGggdGhhdFxuLy8gZ28tZ2V0dGVyIHdvdWxkIHJlc29sdmUgaW5zdGVhZC5cbmNvbnN0IFJFR0lTVFJZX1NFR01FTlQgPSAvXlthLXowLTldW2EtejAtOV8tXSokLztcblxuLy8gRm9yY2VkIGdldHRlcnMsIFVSTHMgYW5kIHdlbGwta25vd24gb2JqZWN0LXN0b3JlIG9yIGZvcmdlIGhvc3RzLlxuY29uc3QgUkVNT1RFX1NPVVJDRSA9XG4gIC9eKD86Z2l0fGhnfHMzfGdjcyk6OnxeZ2l0QHw6XFwvXFwvfF5naXRodWJcXC5jb21cXC98XmJpdGJ1Y2tldFxcLm9yZ1xcL3xhbWF6b25hd3NcXC5jb21cXC98Z29vZ2xlYXBpc1xcLmNvbVxcLy9pO1xuXG4vLyBPbmx5IHB1YmxpYyByZWdpc3RyeSBzb3VyY2VzIGFyZSBzZW50IGFzLWlzOyBhbnl0aGluZyBlbHNlIGNvdWxkIGNhcnJ5IGFcbi8vIHBhdGgsIGhvc3RuYW1lLCBidWNrZXQgb3Igb3JnYW5pemF0aW9uIGFuZCBpcyByZWR1Y2VkIHRvIGl0cyBraW5kLlxuZnVuY3Rpb24gY2xhc3NpZnlNb2R1bGVTb3VyY2Uoc291cmNlOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCB0cmltbWVkID0gc291cmNlLnRyaW0oKTtcbiAgaWYgKGlzTG9jYWxNb2R1bGUodHJpbW1lZCkgfHwgcGF0aC5pc0Fic29sdXRlKHRyaW1tZWQpKSB7XG4gICAgcmV0dXJuIFwibG9jYWxcIjtcbiAgfVxuICBpZiAoUkVNT1RFX1NPVVJDRS50ZXN0KHRyaW1tZWQpKSB7XG4gICAgcmV0dXJuIFwiZ2l0XCI7XG4gIH1cbiAgaWYgKCFpc1JlZ2lzdHJ5TW9kdWxlKHRyaW1tZWQpKSB7XG4gICAgcmV0dXJuIFwib3RoZXJcIjtcbiAgfVxuICBjb25zdCBzZWdtZW50cyA9IHRyaW1tZWQudG9Mb3dlckNhc2UoKS5zcGxpdChcIi9cIik7XG4gIGlmIChzZWdtZW50cy5sZW5ndGggPT09IDQpIHtcbiAgICByZXR1cm4gXCJwcml2YXRlLXJlZ2lzdHJ5XCI7XG4gIH1cbiAgcmV0dXJuIHNlZ21lbnRzLmV2ZXJ5KChzZWdtZW50KSA9PiBSRUdJU1RSWV9TRUdNRU5ULnRlc3Qoc2VnbWVudCkpICYmXG4gICAgd2l0aGluSWRlbnRpdHlMaW1pdHMoc2VnbWVudHMpXG4gICAgPyBzZWdtZW50cy5qb2luKFwiL1wiKVxuICAgIDogXCJvdGhlclwiO1xufVxuXG4vKiogV2hhdCB0cmlnZ2VyZWQgYSBzeW50aCBvdGhlciB0aGFuIHRoZSBjb21tYW5kIGl0c2VsZi4gKi9cbmV4cG9ydCBjb25zdCBTWU5USF9PUklHSU5TID0gW1wid2F0Y2hcIl0gYXMgY29uc3Q7XG5leHBvcnQgdHlwZSBTeW50aE9yaWdpbiA9ICh0eXBlb2YgU1lOVEhfT1JJR0lOUylbbnVtYmVyXTtcblxudHlwZSBTY2FsYXJBdHRyaWJ1dGUgPSB7XG4gIGF0dHJpYnV0ZTogc3RyaW5nO1xuICB0eXBlOiBcInN0cmluZ1wiIHwgXCJudW1iZXJcIiB8IFwiYm9vbGVhblwiO1xuICAvKiogRW51bWVyYXRlZCB2YWx1ZXM7IGEgdmFsdWUgb3V0c2lkZSB0aGUgc2V0IGlzIGRyb3BwZWQuICovXG4gIHZhbHVlcz86IHJlYWRvbmx5IHN0cmluZ1tdO1xufTtcblxuLy8gU2NhbGFyIHBheWxvYWQgZmllbGRzIGZvcndhcmRlZCBhcyBhdHRyaWJ1dGVzLCBwZXIgY29tbWFuZCwgZWFjaCB3aXRoIHRoZVxuLy8gdHlwZSAoYW5kIHdoZXJlIGVudW1lcmFibGUsIHRoZSB2YWx1ZXMpIGl0IG11c3QgaGF2ZS4gQW55dGhpbmcgbm90IGxpc3RlZFxuLy8gaGVyZSwgb2YgdGhlIHdyb25nIHR5cGUgb3Igb2ZmIHRoZSB2YWx1ZSBzZXQgc3RheXMgb3V0IG9mIHRoZSBtZXRyaWMuXG5jb25zdCBTQ0FMQVJfQVRUUklCVVRFUzogUmVjb3JkPHN0cmluZywgUmVjb3JkPHN0cmluZywgU2NhbGFyQXR0cmlidXRlPj4gPSB7XG4gIHN5bnRoOiB7XG4gICAgc3ludGhPcmlnaW46IHtcbiAgICAgIGF0dHJpYnV0ZTogXCJzeW50aF9vcmlnaW5cIixcbiAgICAgIHR5cGU6IFwic3RyaW5nXCIsXG4gICAgICB2YWx1ZXM6IFNZTlRIX09SSUdJTlMsXG4gICAgfSxcbiAgfSxcbiAgaW5pdDoge1xuICAgIC8vIHJlZHVjZWQgdG8gYSBidWlsdC1pbiB0ZW1wbGF0ZSBuYW1lIG9yIFwicmVtb3RlXCIgYnkgdGVtcGxhdGVUZWxlbWV0cnlOYW1lXG4gICAgdGVtcGxhdGU6IHsgYXR0cmlidXRlOiBcInRlbXBsYXRlXCIsIHR5cGU6IFwic3RyaW5nXCIgfSxcbiAgICBpc1JlbW90ZTogeyBhdHRyaWJ1dGU6IFwiaXNfcmVtb3RlXCIsIHR5cGU6IFwiYm9vbGVhblwiIH0sXG4gIH0sXG4gIGNvbnZlcnQ6IHtcbiAgICBudW1iZXJPZk1vZHVsZXM6IHsgYXR0cmlidXRlOiBcIm1vZHVsZV9jb3VudFwiLCB0eXBlOiBcIm51bWJlclwiIH0sXG4gICAgbnVtYmVyT2ZQcm92aWRlcnM6IHsgYXR0cmlidXRlOiBcInByb3ZpZGVyX2NvdW50XCIsIHR5cGU6IFwibnVtYmVyXCIgfSxcbiAgICBjb252ZXJ0ZWRMaW5lczogeyBhdHRyaWJ1dGU6IFwiY29udmVydGVkX2xpbmVzXCIsIHR5cGU6IFwibnVtYmVyXCIgfSxcbiAgfSxcbn07XG5cbmZ1bmN0aW9uIHNjYWxhckF0dHJpYnV0ZVZhbHVlKFxuICB2YWx1ZTogdW5rbm93bixcbiAgc3BlYzogUGljazxTY2FsYXJBdHRyaWJ1dGUsIFwidHlwZVwiIHwgXCJ2YWx1ZXNcIj4sXG4pOiBBdHRyaWJ1dGVWYWx1ZSB8IHVuZGVmaW5lZCB7XG4gIGlmICh0eXBlb2YgdmFsdWUgIT09IHNwZWMudHlwZSkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbiAgaWYgKHNwZWMudHlwZSA9PT0gXCJudW1iZXJcIiAmJiAhTnVtYmVyLmlzRmluaXRlKHZhbHVlKSkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbiAgaWYgKHNwZWMudmFsdWVzICYmICFzcGVjLnZhbHVlcy5pbmNsdWRlcyh2YWx1ZSBhcyBzdHJpbmcpKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuICByZXR1cm4gdmFsdWUgYXMgQXR0cmlidXRlVmFsdWU7XG59XG5cbi8vIGBvdmVycmlkZXM6IHsgYXdzX3MzX2J1Y2tldDogW1widGFnc1wiLCBcInJlZ2lvblwiXSB9YCBnaXZlcyB7IGF3c19zM19idWNrZXQ6IDIgfVxuZnVuY3Rpb24gZ3JvdXBTaXplcyhncm91cDogdW5rbm93bik6IFJlY29yZDxzdHJpbmcsIG51bWJlcj4ge1xuICBjb25zdCBzaXplczogUmVjb3JkPHN0cmluZywgbnVtYmVyPiA9IHt9O1xuICBpZiAoZ3JvdXAgJiYgdHlwZW9mIGdyb3VwID09PSBcIm9iamVjdFwiICYmICFBcnJheS5pc0FycmF5KGdyb3VwKSkge1xuICAgIGZvciAoY29uc3QgW2tleSwgZW50cmllc10gb2YgT2JqZWN0LmVudHJpZXMoZ3JvdXApKSB7XG4gICAgICBzaXplc1trZXldID0gQXJyYXkuaXNBcnJheShlbnRyaWVzKSA/IGVudHJpZXMubGVuZ3RoIDogMDtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHNpemVzO1xufVxuXG5mdW5jdGlvbiBzdW0oc2l6ZXM6IFJlY29yZDxzdHJpbmcsIG51bWJlcj4pOiBudW1iZXIge1xuICByZXR1cm4gT2JqZWN0LnZhbHVlcyhzaXplcykucmVkdWNlKCh0b3RhbCwgc2l6ZSkgPT4gdG90YWwgKyBzaXplLCAwKTtcbn1cblxuLy8gT3ZlcnJpZGUga2V5cyBhcmUgcHJvdmlkZXIgc2NoZW1hIG5hbWVzLCBleGNlcHQgbW9kdWxlIG92ZXJyaWRlcyB3aGljaFxuLy8gY2FycnkgdGhlIG1vZHVsZSBzb3VyY2UgYW5kIGFyZSByZWR1Y2VkIHRvIGl0cyBraW5kLlxuZnVuY3Rpb24gb3ZlcnJpZGVSZXNvdXJjZVR5cGUoa2V5OiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCByZXNvdXJjZVR5cGUgPSBrZXkuc3RhcnRzV2l0aChcIm1vZHVsZS5cIilcbiAgICA/IGBtb2R1bGUuJHtjbGFzc2lmeU1vZHVsZVNvdXJjZShrZXkuc2xpY2UoXCJtb2R1bGUuXCIubGVuZ3RoKSl9YFxuICAgIDoga2V5O1xuICByZXR1cm4gcmVzb3VyY2VUeXBlLmxlbmd0aCA8PSA2NCAmJlxuICAgIChSRVNPVVJDRV9UWVBFLnRlc3QocmVzb3VyY2VUeXBlKSB8fCByZXNvdXJjZVR5cGUuc3RhcnRzV2l0aChcIm1vZHVsZS5cIikpXG4gICAgPyByZXNvdXJjZVR5cGVcbiAgICA6IFwib3RoZXJcIjtcbn1cblxuLy8gRGlzdGluY3QgaWRlbnRpdGllcyByZXBvcnRlZCBwZXIgbWV0cmljIGFuZCBydW4uIEEgcHJvamVjdCdzIHNpemUgbXVzdCBub3Rcbi8vIGRlY2lkZSBob3cgbWFueSBldmVudHMgb25lIHJ1biBzZW5kcywgc28gdGhlIHJlc3QgZm9sZHMgaW50byBvbmUgZXZlbnQuXG5jb25zdCBNQVhfU1RBQ0tfR1JPVVBTID0gODtcbmNvbnN0IE1BWF9TVEFDS19QUk9WSURFUlMgPSAzMjtcbmNvbnN0IE1BWF9TVEFDS19PVkVSUklERV9UWVBFUyA9IDMyO1xuY29uc3QgTUFYX0JJTkRJTkdfU09VUkNFUyA9IDMyO1xuXG4vLyBXaGF0IGFuIGFnZ3JlZ2F0ZWQgbWV0cmljIGFkZHMgdG8gdGhlIGNvbW1hbmQgYXR0cmlidXRlcywgd2l0aCB0aGUgdHlwZVxuLy8gZWFjaCBtdXN0IGhhdmU7IGFueXRoaW5nIGVsc2Ugc3RheXMgb3V0IG9mIHRoZSBtZXRyaWMuXG5jb25zdCBBR0dSRUdBVEVfQVRUUklCVVRFUzogUmVjb3JkPFxuICBzdHJpbmcsXG4gIFJlY29yZDxzdHJpbmcsIFNjYWxhckF0dHJpYnV0ZVtcInR5cGVcIl0+XG4+ID0ge1xuICBcImNsaS5zdGFja1wiOiB7XG4gICAgYmFja2VuZDogXCJzdHJpbmdcIixcbiAgICBjbG91ZDogXCJib29sZWFuXCIsXG4gICAgbGlicmFyeV92ZXJzaW9uOiBcInN0cmluZ1wiLFxuICAgIG92ZXJyaWRlX2NvdW50OiBcIm51bWJlclwiLFxuICAgIGltcG9ydF9jb3VudDogXCJudW1iZXJcIixcbiAgICBtb3ZlZF9jb3VudDogXCJudW1iZXJcIixcbiAgICB0cnVuY2F0ZWQ6IFwiYm9vbGVhblwiLFxuICB9LFxuICBcImNsaS5zdGFjay5wcm92aWRlclwiOiB7XG4gICAgcHJvdmlkZXI6IFwic3RyaW5nXCIsXG4gICAgdmVyc2lvbl9jb25zdHJhaW50OiBcInN0cmluZ1wiLFxuICAgIGJpbmRpbmc6IFwic3RyaW5nXCIsXG4gICAgdHJ1bmNhdGVkOiBcImJvb2xlYW5cIixcbiAgfSxcbiAgXCJjbGkuc3RhY2sub3ZlcnJpZGVcIjoge1xuICAgIHJlc291cmNlX3R5cGU6IFwic3RyaW5nXCIsXG4gICAgb3ZlcnJpZGVfY291bnQ6IFwibnVtYmVyXCIsXG4gICAgdHJ1bmNhdGVkOiBcImJvb2xlYW5cIixcbiAgfSxcbiAgXCJjbGkuZ2V0LnByb3ZpZGVyXCI6IHsgcHJvdmlkZXI6IFwic3RyaW5nXCIsIHRydW5jYXRlZDogXCJib29sZWFuXCIgfSxcbiAgXCJjbGkuZ2V0Lm1vZHVsZVwiOiB7IG1vZHVsZTogXCJzdHJpbmdcIiwgdHJ1bmNhdGVkOiBcImJvb2xlYW5cIiB9LFxuICBcImNsaS5pbml0LnByb3ZpZGVyXCI6IHsgcHJvdmlkZXI6IFwic3RyaW5nXCIsIHRydW5jYXRlZDogXCJib29sZWFuXCIgfSxcbn07XG5cbnR5cGUgTWV0cmljR3JvdXAgPSB7XG4gIGlkZW50aXR5OiBBdHRyaWJ1dGVzO1xuICBzdW1zOiBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+O1xuICB2YWx1ZTogbnVtYmVyO1xuICBsYXN0TWVtYmVyPzogbnVtYmVyO1xufTtcbnR5cGUgTWV0cmljR3JvdXBzID0gTWFwPHN0cmluZywgTWV0cmljR3JvdXA+O1xuXG5mdW5jdGlvbiBhZGRTdW1zKHRhcmdldDogUmVjb3JkPHN0cmluZywgbnVtYmVyPiwgc3VtczogUmVjb3JkPHN0cmluZywgbnVtYmVyPikge1xuICBmb3IgKGNvbnN0IFtuYW1lLCBjb3VudF0gb2YgT2JqZWN0LmVudHJpZXMoc3VtcykpIHtcbiAgICB0YXJnZXRbbmFtZV0gPSAodGFyZ2V0W25hbWVdID8/IDApICsgY291bnQ7XG4gIH1cbn1cblxuLy8gVGhlIGlkZW50aXR5IG11c3QgaG9sZCBub3JtYWxpc2VkIHZhbHVlcyBvbmx5OiBncm91cGluZyBvbiBhIHJhdyBzb3VyY2Vcbi8vIHdvdWxkIHNlbmQgb25lIGV2ZW50IHBlciBkaXN0aW5jdCBwcml2YXRlIGhvc3QuIEEgbWVtYmVyIChhIHN0YWNrKSB0aGF0XG4vLyByZWFjaGVzIGEgZ3JvdXAgdHdpY2UgaXMgY291bnRlZCBvbmNlLlxuZnVuY3Rpb24gY291bnRJbnRvKFxuICBncm91cHM6IE1ldHJpY0dyb3VwcyxcbiAgbWVtYmVyOiBudW1iZXIsXG4gIGlkZW50aXR5OiBBdHRyaWJ1dGVzLFxuICBzdW1zOiBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+ID0ge30sXG4pOiB2b2lkIHtcbiAgY29uc3Qga2V5ID0gSlNPTi5zdHJpbmdpZnkoaWRlbnRpdHkpO1xuICBsZXQgZ3JvdXAgPSBncm91cHMuZ2V0KGtleSk7XG4gIGlmICghZ3JvdXApIHtcbiAgICBncm91cCA9IHsgaWRlbnRpdHksIHN1bXM6IHt9LCB2YWx1ZTogMCB9O1xuICAgIGdyb3Vwcy5zZXQoa2V5LCBncm91cCk7XG4gIH1cbiAgaWYgKGdyb3VwLmxhc3RNZW1iZXIgIT09IG1lbWJlcikge1xuICAgIGdyb3VwLmxhc3RNZW1iZXIgPSBtZW1iZXI7XG4gICAgZ3JvdXAudmFsdWUgKz0gMTtcbiAgfVxuICBhZGRTdW1zKGdyb3VwLnN1bXMsIHN1bXMpO1xufVxuXG4vLyBPbmUgY291bnRlciBwZXIgZ3JvdXAsIHRoZSBtb3N0IGNvdW50ZWQgZmlyc3QgKHRpZXMgYnkgaWRlbnRpdHksIHNvIHRoZVxuLy8ga2VwdCBzZXQgaXMgc3RhYmxlKTsgdGhlIGdyb3VwcyBwYXN0IGBsaW1pdGAgZm9sZCBpbnRvIG9uZSBldmVudCB3aXRob3V0XG4vLyBpZGVudGl0eSwgd2hpY2gga2VlcHMgdGhlIG1ldHJpYydzIHRvdGFsLlxuZnVuY3Rpb24gZW1pdEdyb3VwcyhcbiAgbWV0cmljOiBzdHJpbmcsXG4gIGxpbWl0OiBudW1iZXIsXG4gIGdyb3VwczogTWV0cmljR3JvdXBzLFxuICBhdHRyaWJ1dGVzOiBBdHRyaWJ1dGVzLFxuKTogdm9pZCB7XG4gIGNvbnN0IHNvcnRlZCA9IFsuLi5ncm91cHMuZW50cmllcygpXVxuICAgIC5zb3J0KChba2V5QSwgYV0sIFtrZXlCLCBiXSkgPT4gYi52YWx1ZSAtIGEudmFsdWUgfHwgKGtleUEgPCBrZXlCID8gLTEgOiAxKSlcbiAgICAubWFwKChbLCBncm91cF0pID0+IGdyb3VwKTtcbiAgY29uc3QgZW1pdHRlZCA9IHNvcnRlZC5zbGljZSgwLCBsaW1pdCk7XG4gIGNvbnN0IGZvbGRlZCA9IHNvcnRlZC5zbGljZShsaW1pdCk7XG4gIGlmIChmb2xkZWQubGVuZ3RoID4gMCkge1xuICAgIGNvbnN0IHJlc2lkdWFsOiBNZXRyaWNHcm91cCA9IHtcbiAgICAgIGlkZW50aXR5OiB7IHRydW5jYXRlZDogdHJ1ZSB9LFxuICAgICAgc3Vtczoge30sXG4gICAgICB2YWx1ZTogMCxcbiAgICB9O1xuICAgIGZvciAoY29uc3QgZ3JvdXAgb2YgZm9sZGVkKSB7XG4gICAgICByZXNpZHVhbC52YWx1ZSArPSBncm91cC52YWx1ZTtcbiAgICAgIGFkZFN1bXMocmVzaWR1YWwuc3VtcywgZ3JvdXAuc3Vtcyk7XG4gICAgfVxuICAgIGVtaXR0ZWQucHVzaChyZXNpZHVhbCk7XG4gIH1cbiAgY29uc3QgYWxsb3dlZCA9IEFHR1JFR0FURV9BVFRSSUJVVEVTW21ldHJpY107XG4gIGZvciAoY29uc3QgZ3JvdXAgb2YgZW1pdHRlZCkge1xuICAgIGNvbnN0IG93bjogQXR0cmlidXRlcyA9IHt9O1xuICAgIGZvciAoY29uc3QgW25hbWUsIHJhd10gb2YgT2JqZWN0LmVudHJpZXMoe1xuICAgICAgLi4uZ3JvdXAuaWRlbnRpdHksXG4gICAgICAuLi5ncm91cC5zdW1zLFxuICAgIH0pKSB7XG4gICAgICBjb25zdCB2YWx1ZSA9XG4gICAgICAgIG5hbWUgaW4gYWxsb3dlZFxuICAgICAgICAgID8gc2NhbGFyQXR0cmlidXRlVmFsdWUocmF3LCB7IHR5cGU6IGFsbG93ZWRbbmFtZV0gfSlcbiAgICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIG93bltuYW1lXSA9IHZhbHVlO1xuICAgICAgfVxuICAgIH1cbiAgICBTZW50cnkubWV0cmljcy5jb3VudChtZXRyaWMsIGdyb3VwLnZhbHVlLCB7XG4gICAgICBhdHRyaWJ1dGVzOiB7IC4uLmF0dHJpYnV0ZXMsIC4uLm93biB9LFxuICAgIH0pO1xuICB9XG59XG5cbi8vIGNvdW50cyBhbmQgYWxsb3ctbGlzdGVkIGtpbmRzIG9ubHksIG5ldmVyIG5hbWVzIG9yIGlkc1xuZnVuY3Rpb24gc2VuZFN0YWNrVGVsZW1ldHJ5KFxuICBzdGFja01ldGFkYXRhOiB1bmtub3duW10sXG4gIHJlcXVpcmVkUHJvdmlkZXJzOiB1bmtub3duW10sXG4gIGF0dHJpYnV0ZXM6IEF0dHJpYnV0ZXMsXG4pOiB2b2lkIHtcbiAgY29uc3QgZ2VuZXJhdGVkU291cmNlcyA9XG4gICAgc3RhdGUuZ2VuZXJhdGVkUHJvdmlkZXJTb3VyY2VzID8/IGdldEdlbmVyYXRlZFByb3ZpZGVyU291cmNlcygpO1xuICBjb25zdCBzdGFja3M6IE1ldHJpY0dyb3VwcyA9IG5ldyBNYXAoKTtcbiAgY29uc3Qgb3ZlcnJpZGVzOiBNZXRyaWNHcm91cHMgPSBuZXcgTWFwKCk7XG4gIGNvbnN0IHByb3ZpZGVyczogTWV0cmljR3JvdXBzID0gbmV3IE1hcCgpO1xuICBzdGFja01ldGFkYXRhLmZvckVhY2goKGVudHJ5LCBpbmRleCkgPT4ge1xuICAgIC8vIGEgbnVsbCBvciBub24tb2JqZWN0IGVudHJ5IGlzIG5vdCBhIHN0YWNrOiBjb3VudGluZyBvbmUgd291bGQgaW5mbGF0ZVxuICAgIC8vIHRoZSBzdGFjayBjb3VudCB3aXRoIG1ldGFkYXRhIHRoZSBsaWJyYXJ5IG5ldmVyIHdyb3RlXG4gICAgaWYgKCFlbnRyeSB8fCB0eXBlb2YgZW50cnkgIT09IFwib2JqZWN0XCIpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgbWV0YWRhdGEgPSBlbnRyeSBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICAgIGNvbnN0IG92ZXJyaWRlU2l6ZXMgPSBncm91cFNpemVzKG1ldGFkYXRhLm92ZXJyaWRlcyk7XG4gICAgY29uc3Qgc3RhY2s6IEF0dHJpYnV0ZXMgPSB7XG4gICAgICBiYWNrZW5kOiBub3JtYWxpemVCYWNrZW5kS2luZChtZXRhZGF0YS5iYWNrZW5kKSxcbiAgICAgIGNsb3VkOiB0eXBlb2YgbWV0YWRhdGEuY2xvdWQgPT09IFwic3RyaW5nXCIsXG4gICAgfTtcbiAgICBjb25zdCBsaWJyYXJ5VmVyc2lvbiA9IHJlbGVhc2VWZXJzaW9uKG1ldGFkYXRhLnZlcnNpb24pO1xuICAgIGlmIChsaWJyYXJ5VmVyc2lvbikge1xuICAgICAgc3RhY2subGlicmFyeV92ZXJzaW9uID0gbGlicmFyeVZlcnNpb247XG4gICAgfVxuICAgIGNvdW50SW50byhzdGFja3MsIGluZGV4LCBzdGFjaywge1xuICAgICAgb3ZlcnJpZGVfY291bnQ6IHN1bShvdmVycmlkZVNpemVzKSxcbiAgICAgIGltcG9ydF9jb3VudDogc3VtKGdyb3VwU2l6ZXMobWV0YWRhdGEuaW1wb3J0cykpLFxuICAgICAgbW92ZWRfY291bnQ6IHN1bShncm91cFNpemVzKG1ldGFkYXRhLm1vdmVkKSksXG4gICAgfSk7XG5cbiAgICBmb3IgKGNvbnN0IFtrZXksIGNvdW50XSBvZiBPYmplY3QuZW50cmllcyhvdmVycmlkZVNpemVzKSkge1xuICAgICAgY291bnRJbnRvKFxuICAgICAgICBvdmVycmlkZXMsXG4gICAgICAgIGluZGV4LFxuICAgICAgICB7IHJlc291cmNlX3R5cGU6IG92ZXJyaWRlUmVzb3VyY2VUeXBlKGtleSkgfSxcbiAgICAgICAgeyBvdmVycmlkZV9jb3VudDogY291bnQgfSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgcmVxdWlyZWQgPSByZXF1aXJlZFByb3ZpZGVyc1tpbmRleF07XG4gICAgaWYgKCFyZXF1aXJlZCB8fCB0eXBlb2YgcmVxdWlyZWQgIT09IFwib2JqZWN0XCIpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZm9yIChjb25zdCBbdHlwZSwgY29uc3RyYWludF0gb2YgT2JqZWN0LmVudHJpZXMoXG4gICAgICByZXF1aXJlZCBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+LFxuICAgICkpIHtcbiAgICAgIGNvbnN0IHNvdXJjZSA9XG4gICAgICAgIHR5cGVvZiBjb25zdHJhaW50Py5zb3VyY2UgPT09IFwic3RyaW5nXCIgPyBjb25zdHJhaW50LnNvdXJjZSA6IHR5cGU7XG4gICAgICBjb25zdCBwcm92aWRlcjogQXR0cmlidXRlcyA9IHtcbiAgICAgICAgcHJvdmlkZXI6IG5vcm1hbGl6ZVByb3ZpZGVyU291cmNlKHNvdXJjZSksXG4gICAgICB9O1xuICAgICAgaWYgKHR5cGVvZiBjb25zdHJhaW50Py52ZXJzaW9uID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIHByb3ZpZGVyLnZlcnNpb25fY29uc3RyYWludCA9IG5vcm1hbGl6ZVByb3ZpZGVyQ29uc3RyYWludChcbiAgICAgICAgICBjb25zdHJhaW50LnZlcnNpb24sXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBwcm92aWRlci5iaW5kaW5nID0gY2xhc3NpZnlQcm92aWRlckJpbmRpbmcoc291cmNlLCBnZW5lcmF0ZWRTb3VyY2VzKTtcbiAgICAgIGNvdW50SW50byhwcm92aWRlcnMsIGluZGV4LCBwcm92aWRlcik7XG4gICAgfVxuICB9KTtcbiAgZW1pdEdyb3VwcyhcImNsaS5zdGFja1wiLCBNQVhfU1RBQ0tfR1JPVVBTLCBzdGFja3MsIGF0dHJpYnV0ZXMpO1xuICBlbWl0R3JvdXBzKFwiY2xpLnN0YWNrLnByb3ZpZGVyXCIsIE1BWF9TVEFDS19QUk9WSURFUlMsIHByb3ZpZGVycywgYXR0cmlidXRlcyk7XG4gIGVtaXRHcm91cHMoXG4gICAgXCJjbGkuc3RhY2sub3ZlcnJpZGVcIixcbiAgICBNQVhfU1RBQ0tfT1ZFUlJJREVfVFlQRVMsXG4gICAgb3ZlcnJpZGVzLFxuICAgIGF0dHJpYnV0ZXMsXG4gICk7XG59XG5cbmZ1bmN0aW9uIHNlbmRTb3VyY2VUZWxlbWV0cnkoXG4gIG1ldHJpYzogc3RyaW5nLFxuICBhdHRyaWJ1dGU6IHN0cmluZyxcbiAgc291cmNlczogc3RyaW5nW10sXG4gIG5vcm1hbGl6ZTogKHNvdXJjZTogc3RyaW5nKSA9PiBzdHJpbmcsXG4gIGF0dHJpYnV0ZXM6IEF0dHJpYnV0ZXMsXG4pOiB2b2lkIHtcbiAgY29uc3QgZ3JvdXBzOiBNZXRyaWNHcm91cHMgPSBuZXcgTWFwKCk7XG4gIHNvdXJjZXMuZm9yRWFjaCgoc291cmNlLCBpbmRleCkgPT5cbiAgICBjb3VudEludG8oZ3JvdXBzLCBpbmRleCwgeyBbYXR0cmlidXRlXTogbm9ybWFsaXplKHNvdXJjZSkgfSksXG4gICk7XG4gIGVtaXRHcm91cHMobWV0cmljLCBNQVhfQklORElOR19TT1VSQ0VTLCBncm91cHMsIGF0dHJpYnV0ZXMpO1xufVxuXG4vLyB0YXJnZXRzOiBvbmUgYHsgdHlwZSwgc291cmNlIH1gIHBlciBnZW5lcmF0ZWQgYmluZGluZ1xuZnVuY3Rpb24gdGFyZ2V0U291cmNlcyh0YXJnZXRzOiBhbnlbXSwgdHlwZTogc3RyaW5nKTogc3RyaW5nW10ge1xuICByZXR1cm4gdGFyZ2V0c1xuICAgIC5maWx0ZXIoKHRhcmdldCkgPT4gdGFyZ2V0Py50eXBlID09PSB0eXBlKVxuICAgIC5tYXAoKHRhcmdldCkgPT4gdGFyZ2V0LnNvdXJjZSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGNvbW1hbmRBdHRyaWJ1dGVzKFxuICBjb21tYW5kOiBzdHJpbmcsXG4gIGxhbmd1YWdlOiB1bmtub3duLFxuKTogUHJvbWlzZTxBdHRyaWJ1dGVzPiB7XG4gIGNvbnN0IGNpOiBzdHJpbmcgfCBmYWxzZSA9IGNpSW5mby5pc0NJID8gY2lJbmZvLm5hbWUgfHwgXCJ1bmtub3duXCIgOiBmYWxzZTtcbiAgY29uc3QgYXR0cmlidXRlczogQXR0cmlidXRlcyA9IHtcbiAgICBjb21tYW5kLFxuICAgIGNpOiBjaSA9PT0gZmFsc2UgPyBmYWxzZSA6IGNpLFxuICAgIG9zOiBwcm9jZXNzLnBsYXRmb3JtLFxuICAgIGFyY2g6IHByb2Nlc3MuYXJjaCxcbiAgICAuLi4oc3RhdGUucHJvamVjdFRhcmdldEF0dHJpYnV0ZXMgPz8gZ2V0UHJvamVjdFRhcmdldEF0dHJpYnV0ZXMoKSksXG4gICAgLi4uKGF3YWl0IGdldEJpbmFyeUF0dHJpYnV0ZXMoKSksXG4gIH07XG4gIGlmIChMQU5HVUFHRVMuaW5jbHVkZXMobGFuZ3VhZ2UgYXMgYW55KSkge1xuICAgIGF0dHJpYnV0ZXMubGFuZ3VhZ2UgPSBsYW5ndWFnZSBhcyBzdHJpbmc7XG4gIH1cbiAgaWYgKHN0YXRlLnBhY2thZ2VNYW5hZ2VyICE9PSB1bmRlZmluZWQpIHtcbiAgICBhdHRyaWJ1dGVzLnBhY2thZ2VfbWFuYWdlciA9IHN0YXRlLnBhY2thZ2VNYW5hZ2VyO1xuICB9XG4gIHJldHVybiBhdHRyaWJ1dGVzO1xufVxuXG4vLyBDb3VudHMgdGhlIGF0dGVtcHQsIHdoYXRldmVyIGl0cyBvdXRjb21lLiBSdW5zIGFmdGVyIGNvbnNlbnQgaXMgY2FwdHVyZWRcbi8vIGFuZCBTZW50cnkgaW5pdGlhbGl6ZWQ7IGxhdGVyIGNhbGxzIGluIHRoZSBzYW1lIHByb2Nlc3MgYXJlIG5vLW9wcy5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzdGFydENvbW1hbmRUZWxlbWV0cnkoXG4gIGNvbW1hbmQ6IHN0cmluZyxcbiAgcHJvamVjdFBhdGggPSBwcm9jZXNzLmN3ZCgpLFxuKTogUHJvbWlzZTx2b2lkPiB7XG4gIGlmIChzdGF0ZS5zdGFydGVkQ29tbWFuZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHN0YXRlLnN0YXJ0ZWRDb21tYW5kID0gY29tbWFuZDtcbiAgY29uc3QgY2RrdGZKc29uID0gcmVhZFJhd0Nka3RmSnNvbihwcm9qZWN0UGF0aCk7XG4gIHN0YXRlLmxhbmd1YWdlID0gY2RrdGZKc29uLmxhbmd1YWdlO1xuICBzdGF0ZS5wYWNrYWdlTWFuYWdlciA9IGRldGVjdFBhY2thZ2VNYW5hZ2VyKHByb2plY3RQYXRoLCBjZGt0Zkpzb24pO1xuICBzdGF0ZS5nZW5lcmF0ZWRQcm92aWRlclNvdXJjZXMgPSBnZXRHZW5lcmF0ZWRQcm92aWRlclNvdXJjZXMocHJvamVjdFBhdGgpO1xuICB0cnkge1xuICAgIGlmICghaXNVc2FnZVRlbGVtZXRyeUVuYWJsZWQoKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBhdHRyaWJ1dGVzID0gYXdhaXQgY29tbWFuZEF0dHJpYnV0ZXMoY29tbWFuZCwgc3RhdGUubGFuZ3VhZ2UpO1xuICAgIFNlbnRyeS5tZXRyaWNzLmNvdW50KFwiY2xpLmNvbW1hbmQuaW52b2tlZFwiLCAxLCB7IGF0dHJpYnV0ZXMgfSk7XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGxvZ2dlci5kZWJ1ZyhgQ291bGQgbm90IHNlbmQgdGVsZW1ldHJ5IGRhdGE6ICR7ZXJyfWApO1xuICB9XG59XG5cbi8qKiBGb3JnZXRzIHRoZSBzdGFydGVkIHJ1bjsgdGVzdHMgcnVuIG1hbnkgY29tbWFuZHMgaW4gb25lIHByb2Nlc3MuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzZXRDb21tYW5kVGVsZW1ldHJ5KCk6IHZvaWQge1xuICBzdGF0ZS5zdGFydGVkQ29tbWFuZCA9IHVuZGVmaW5lZDtcbiAgc3RhdGUubGFuZ3VhZ2UgPSB1bmRlZmluZWQ7XG4gIHN0YXRlLnBhY2thZ2VNYW5hZ2VyID0gdW5kZWZpbmVkO1xuICBzdGF0ZS5nZW5lcmF0ZWRQcm92aWRlclNvdXJjZXMgPSB1bmRlZmluZWQ7XG4gIHN0YXRlLnN0YWNrTWV0cmljc1NlbnQgPSB1bmRlZmluZWQ7XG59XG5cbi8vIFBheWxvYWQgZmllbGRzIHJlYWNoIHRoZSBhdHRyaWJ1dGVzIG9ubHkgdGhyb3VnaCB0aGUgYWxsb3ctbGlzdHMgYWJvdmUuXG4vLyBBIG5vLW9wIHdoZW4gdXNhZ2UgdGVsZW1ldHJ5IGlzIGRpc2FibGVkIG9yIFNlbnRyeSBpcyBub3QgaW5pdGlhbGl6ZWQ7XG4vLyBgcGF5bG9hZC5lcnJvcmAgY291bnRzIHRoZSBydW4gYXMgY2xpLmNvbW1hbmQuZXJyb3IgaW5zdGVhZC5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZW5kVGVsZW1ldHJ5KFxuICBjb21tYW5kOiBzdHJpbmcsXG4gIHBheWxvYWQ6IFJlY29yZDxzdHJpbmcsIGFueT4sXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgdHJ5IHtcbiAgICBpZiAoIWlzVXNhZ2VUZWxlbWV0cnlFbmFibGVkKCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBhdHRyaWJ1dGVzID0gYXdhaXQgY29tbWFuZEF0dHJpYnV0ZXMoXG4gICAgICBjb21tYW5kLFxuICAgICAgcGF5bG9hZC5sYW5ndWFnZSA/PyBzdGF0ZS5sYW5ndWFnZSxcbiAgICApO1xuICAgIGZvciAoY29uc3QgW2tleSwgc3BlY10gb2YgT2JqZWN0LmVudHJpZXMoXG4gICAgICBTQ0FMQVJfQVRUUklCVVRFU1tjb21tYW5kXSA/PyB7fSxcbiAgICApKSB7XG4gICAgICBjb25zdCB2YWx1ZSA9IHNjYWxhckF0dHJpYnV0ZVZhbHVlKHBheWxvYWRba2V5XSwgc3BlYyk7XG4gICAgICBpZiAodmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBhdHRyaWJ1dGVzW3NwZWMuYXR0cmlidXRlXSA9IHZhbHVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChwYXlsb2FkLmVycm9yKSB7XG4gICAgICBhdHRyaWJ1dGVzLmVycm9yX3R5cGUgPSBDT01NQU5EX0VSUk9SX1RZUEVTLmluY2x1ZGVzKHBheWxvYWQuZXJyb3JUeXBlKVxuICAgICAgICA/IHBheWxvYWQuZXJyb3JUeXBlXG4gICAgICAgIDogXCJ1bmV4cGVjdGVkXCI7XG4gICAgICBTZW50cnkubWV0cmljcy5jb3VudChcImNsaS5jb21tYW5kLmVycm9yXCIsIDEsIHsgYXR0cmlidXRlcyB9KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBnZW5lcmF0ZWQgPVxuICAgICAgY29tbWFuZCA9PT0gXCJnZXRcIiAmJiBBcnJheS5pc0FycmF5KHBheWxvYWQudGFyZ2V0cylcbiAgICAgICAgPyB7XG4gICAgICAgICAgICBwcm92aWRlcnM6IHRhcmdldFNvdXJjZXMocGF5bG9hZC50YXJnZXRzLCBcInByb3ZpZGVyXCIpLFxuICAgICAgICAgICAgbW9kdWxlczogdGFyZ2V0U291cmNlcyhwYXlsb2FkLnRhcmdldHMsIFwibW9kdWxlXCIpLFxuICAgICAgICAgIH1cbiAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgY29uc3QgYWRkZWRQcm92aWRlcnM6IHN0cmluZ1tdIHwgdW5kZWZpbmVkID1cbiAgICAgIGNvbW1hbmQgPT09IFwiaW5pdFwiICYmIEFycmF5LmlzQXJyYXkocGF5bG9hZC5hZGRlZFByb3ZpZGVycylcbiAgICAgICAgPyBwYXlsb2FkLmFkZGVkUHJvdmlkZXJzXG4gICAgICAgIDogdW5kZWZpbmVkO1xuICAgIGlmIChnZW5lcmF0ZWQpIHtcbiAgICAgIGF0dHJpYnV0ZXMucHJvdmlkZXJfY291bnQgPSBnZW5lcmF0ZWQucHJvdmlkZXJzLmxlbmd0aDtcbiAgICAgIGF0dHJpYnV0ZXMubW9kdWxlX2NvdW50ID0gZ2VuZXJhdGVkLm1vZHVsZXMubGVuZ3RoO1xuICAgIH1cbiAgICBpZiAoYWRkZWRQcm92aWRlcnMpIHtcbiAgICAgIGF0dHJpYnV0ZXMucHJvdmlkZXJfY291bnQgPSBhZGRlZFByb3ZpZGVycy5sZW5ndGg7XG4gICAgfVxuXG4gICAgLy8gVGhlIHJ1bidzIG91dGNvbWUgZ29lcyBmaXJzdDogbm90aGluZyBpbiB0aGUgcGVyLXNvdXJjZSBhbmQgc3RhY2tcbiAgICAvLyBtZXRyaWNzIGJlbG93IGNhbiB0aGVuIGNvc3QgdGhlIHJ1biBpdHMgY29tbWFuZCBtZXRyaWMuXG4gICAgY29uc3QgbmVzdGVkID1cbiAgICAgIHN0YXRlLnN0YXJ0ZWRDb21tYW5kICE9PSB1bmRlZmluZWQgJiYgc3RhdGUuc3RhcnRlZENvbW1hbmQgIT09IGNvbW1hbmQ7XG4gICAgLy8gYSBydW4gdGhhdCBmYWlsZWQsIHdpdGggb3Igd2l0aG91dCBhIGZhaWxlZCBzdGFjaywgaXMgbm90IGNvbXBsZXRlZDogdGhlXG4gICAgLy8gZmFpbHVyZSB0aHJvd24gbmV4dCBpcyBjb3VudGVkIGFzIGNsaS5jb21tYW5kLmVycm9yIGJ5IHRoZSBlbnRyeXBvaW50J3NcbiAgICAvLyByZXBvcnRlclxuICAgIGNvbnN0IGZhaWxlZFN0YWNrQ291bnQgPVxuICAgICAgdHlwZW9mIHBheWxvYWQuZmFpbGVkU3RhY2tDb3VudCA9PT0gXCJudW1iZXJcIlxuICAgICAgICA/IHBheWxvYWQuZmFpbGVkU3RhY2tDb3VudFxuICAgICAgICA6IDA7XG4gICAgaWYgKGZhaWxlZFN0YWNrQ291bnQgPiAwKSB7XG4gICAgICBTZW50cnkubWV0cmljcy5jb3VudChcImNsaS5zdGFjay5mYWlsZWRcIiwgZmFpbGVkU3RhY2tDb3VudCwge1xuICAgICAgICBhdHRyaWJ1dGVzLFxuICAgICAgfSk7XG4gICAgfSBlbHNlIGlmICghbmVzdGVkICYmIHBheWxvYWQucnVuRmFpbGVkICE9PSB0cnVlKSB7XG4gICAgICBTZW50cnkubWV0cmljcy5jb3VudChcImNsaS5jb21tYW5kLmNvbXBsZXRlZFwiLCAxLCB7IGF0dHJpYnV0ZXMgfSk7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgcGF5bG9hZC50b3RhbFRpbWUgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgIFNlbnRyeS5tZXRyaWNzLmRpc3RyaWJ1dGlvbihcImNsaS5zeW50aC5kdXJhdGlvblwiLCBwYXlsb2FkLnRvdGFsVGltZSwge1xuICAgICAgICB1bml0OiBcIm1pbGxpc2Vjb25kXCIsXG4gICAgICAgIGF0dHJpYnV0ZXMsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAoZ2VuZXJhdGVkKSB7XG4gICAgICBzZW5kU291cmNlVGVsZW1ldHJ5KFxuICAgICAgICBcImNsaS5nZXQucHJvdmlkZXJcIixcbiAgICAgICAgXCJwcm92aWRlclwiLFxuICAgICAgICBnZW5lcmF0ZWQucHJvdmlkZXJzLFxuICAgICAgICBub3JtYWxpemVQcm92aWRlclNvdXJjZSxcbiAgICAgICAgYXR0cmlidXRlcyxcbiAgICAgICk7XG4gICAgICBzZW5kU291cmNlVGVsZW1ldHJ5KFxuICAgICAgICBcImNsaS5nZXQubW9kdWxlXCIsXG4gICAgICAgIFwibW9kdWxlXCIsXG4gICAgICAgIGdlbmVyYXRlZC5tb2R1bGVzLFxuICAgICAgICBjbGFzc2lmeU1vZHVsZVNvdXJjZSxcbiAgICAgICAgYXR0cmlidXRlcyxcbiAgICAgICk7XG4gICAgfVxuICAgIGlmIChhZGRlZFByb3ZpZGVycykge1xuICAgICAgc2VuZFNvdXJjZVRlbGVtZXRyeShcbiAgICAgICAgXCJjbGkuaW5pdC5wcm92aWRlclwiLFxuICAgICAgICBcInByb3ZpZGVyXCIsXG4gICAgICAgIGFkZGVkUHJvdmlkZXJzLFxuICAgICAgICBub3JtYWxpemVQcm92aWRlclNvdXJjZSxcbiAgICAgICAgYXR0cmlidXRlcyxcbiAgICAgICk7XG4gICAgfVxuICAgIC8vIEEgc3ludGggbmVzdGVkIGluIGFub3RoZXIgY29tbWFuZCBkZXNjcmliZXMgZXZlcnkgc3RhY2sgb2YgdGhlIGFwcDtcbiAgICAvLyB0aGUgY29tbWFuZCByZXBvcnRzIHRoZSBzdGFja3MgaXQgc2VsZWN0ZWQsIHVuZGVyIGl0cyBvd24gbmFtZS5cbiAgICBpZiAoXG4gICAgICBBcnJheS5pc0FycmF5KHBheWxvYWQuc3RhY2tNZXRhZGF0YSkgJiZcbiAgICAgICFzdGF0ZS5zdGFja01ldHJpY3NTZW50ICYmXG4gICAgICAhKG5lc3RlZCAmJiBjb21tYW5kID09PSBcInN5bnRoXCIpXG4gICAgKSB7XG4gICAgICBzdGF0ZS5zdGFja01ldHJpY3NTZW50ID0gdHJ1ZTtcbiAgICAgIHNlbmRTdGFja1RlbGVtZXRyeShcbiAgICAgICAgcGF5bG9hZC5zdGFja01ldGFkYXRhLFxuICAgICAgICBBcnJheS5pc0FycmF5KHBheWxvYWQucmVxdWlyZWRQcm92aWRlcnMpXG4gICAgICAgICAgPyBwYXlsb2FkLnJlcXVpcmVkUHJvdmlkZXJzXG4gICAgICAgICAgOiBbXSxcbiAgICAgICAgYXR0cmlidXRlcyxcbiAgICAgICk7XG4gICAgfVxuICB9IGNhdGNoIChlcnIpIHtcbiAgICBsb2dnZXIuZGVidWcoYENvdWxkIG5vdCBzZW5kIHRlbGVtZXRyeSBkYXRhOiAke2Vycn1gKTtcbiAgfVxufVxuIl19
|