@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.
Files changed (40) hide show
  1. package/build/config.d.ts +5 -0
  2. package/build/config.d.ts.map +1 -1
  3. package/build/config.js +26 -1
  4. package/build/config.test.js +23 -1
  5. package/build/construct-maker-target.d.ts +2 -0
  6. package/build/construct-maker-target.d.ts.map +1 -1
  7. package/build/construct-maker-target.js +3 -1
  8. package/build/debug.js +11 -11
  9. package/build/debug.test.js +9 -2
  10. package/build/errors.d.ts +3 -0
  11. package/build/errors.d.ts.map +1 -1
  12. package/build/errors.js +31 -23
  13. package/build/errors.test.d.ts +2 -0
  14. package/build/errors.test.d.ts.map +1 -0
  15. package/build/errors.test.js +24 -0
  16. package/build/identity.d.ts +3 -0
  17. package/build/identity.d.ts.map +1 -0
  18. package/build/identity.js +88 -0
  19. package/build/index.d.ts +2 -1
  20. package/build/index.d.ts.map +1 -1
  21. package/build/index.js +3 -2
  22. package/build/process-state.d.ts +2 -0
  23. package/build/process-state.d.ts.map +1 -0
  24. package/build/process-state.js +15 -0
  25. package/build/telemetry.d.ts +24 -0
  26. package/build/telemetry.d.ts.map +1 -0
  27. package/build/telemetry.js +721 -0
  28. package/build/telemetry.test.d.ts +2 -0
  29. package/build/telemetry.test.d.ts.map +1 -0
  30. package/build/telemetry.test.js +1501 -0
  31. package/build/terraform.d.ts +10 -1
  32. package/build/terraform.d.ts.map +1 -1
  33. package/build/terraform.js +43 -8
  34. package/build/terraform.test.d.ts +2 -0
  35. package/build/terraform.test.d.ts.map +1 -0
  36. package/build/terraform.test.js +136 -0
  37. package/package.json +3 -3
  38. package/build/checkpoint.d.ts +0 -19
  39. package/build/checkpoint.d.ts.map +0 -1
  40. 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