@cdktn/provider-generator 0.23.0-pre.8 → 0.23.0
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/ambient.d.ts +0 -1
- package/{lib → build}/__tests__/edge-provider-schema/builder.d.ts +1 -0
- package/build/__tests__/edge-provider-schema/builder.js +106 -0
- package/build/__tests__/edge-provider-schema/cli.d.ts +2 -0
- package/build/__tests__/edge-provider-schema/cli.js +67 -0
- package/{lib → build}/__tests__/edge-provider-schema/index.d.ts +1 -0
- package/build/__tests__/edge-provider-schema/index.js +154 -0
- package/build/__tests__/edge-provider-schema.test.d.ts +2 -0
- package/build/__tests__/edge-provider-schema.test.js +46 -0
- package/build/__tests__/provider.test.d.ts +2 -0
- package/build/__tests__/provider.test.js +158 -0
- package/build/get/__tests__/constructs-maker.test.d.ts +2 -0
- package/build/get/__tests__/constructs-maker.test.js +113 -0
- package/build/get/__tests__/generator/complex-computed-types.test.d.ts +2 -0
- package/build/get/__tests__/generator/complex-computed-types.test.js +42 -0
- package/build/get/__tests__/generator/deep-nested-attributes.test.d.ts +2 -0
- package/build/get/__tests__/generator/deep-nested-attributes.test.js +50 -0
- package/build/get/__tests__/generator/description-escaping.test.d.ts +2 -0
- package/build/get/__tests__/generator/description-escaping.test.js +65 -0
- package/build/get/__tests__/generator/empty-provider-resources.test.d.ts +2 -0
- package/build/get/__tests__/generator/empty-provider-resources.test.js +40 -0
- package/build/get/__tests__/generator/export-sharding.test.d.ts +2 -0
- package/build/get/__tests__/generator/export-sharding.test.js +82 -0
- package/build/get/__tests__/generator/module-generator.test.d.ts +2 -0
- package/build/get/__tests__/generator/module-generator.test.js +476 -0
- package/build/get/__tests__/generator/nested-types.test.d.ts +2 -0
- package/build/get/__tests__/generator/nested-types.test.js +51 -0
- package/build/get/__tests__/generator/provider.test.d.ts +2 -0
- package/build/get/__tests__/generator/provider.test.js +51 -0
- package/build/get/__tests__/generator/resource-types.test.d.ts +2 -0
- package/build/get/__tests__/generator/resource-types.test.js +78 -0
- package/build/get/__tests__/generator/skipped-attributes.test.d.ts +2 -0
- package/build/get/__tests__/generator/skipped-attributes.test.js +55 -0
- package/build/get/__tests__/generator/types.test.d.ts +2 -0
- package/build/get/__tests__/generator/types.test.js +289 -0
- package/build/get/__tests__/generator/versions-file.test.d.ts +2 -0
- package/build/get/__tests__/generator/versions-file.test.js +74 -0
- package/{lib → build}/get/__tests__/util.d.ts +1 -0
- package/build/get/__tests__/util.js +59 -0
- package/{lib → build}/get/constructs-maker.d.ts +2 -1
- package/{lib → build}/get/constructs-maker.js +5 -2
- package/{lib → build}/get/generator/custom-defaults.d.ts +1 -0
- package/build/get/generator/custom-defaults.js +403 -0
- package/{lib → build}/get/generator/emitter/attributes-emitter.d.ts +1 -0
- package/build/get/generator/emitter/attributes-emitter.js +161 -0
- package/{lib → build}/get/generator/emitter/index.d.ts +1 -0
- package/{lib → build}/get/generator/emitter/index.js +1 -1
- package/{lib → build}/get/generator/emitter/resource-emitter.d.ts +1 -0
- package/build/get/generator/emitter/resource-emitter.js +147 -0
- package/{lib → build}/get/generator/emitter/struct-emitter.d.ts +1 -0
- package/build/get/generator/emitter/struct-emitter.js +500 -0
- package/{lib → build}/get/generator/loop-detection.d.ts +1 -0
- package/build/get/generator/loop-detection.js +56 -0
- package/{lib → build}/get/generator/models/attribute-model.d.ts +1 -0
- package/build/get/generator/models/attribute-model.js +160 -0
- package/{lib → build}/get/generator/models/attribute-type-model.d.ts +1 -0
- package/build/get/generator/models/attribute-type-model.js +376 -0
- package/{lib → build}/get/generator/models/index.d.ts +1 -0
- package/{lib → build}/get/generator/models/index.js +1 -1
- package/{lib → build}/get/generator/models/resource-model.d.ts +1 -0
- package/build/get/generator/models/resource-model.js +106 -0
- package/{lib → build}/get/generator/models/scope.d.ts +1 -0
- package/build/get/generator/models/scope.js +36 -0
- package/{lib → build}/get/generator/models/struct.d.ts +1 -0
- package/build/get/generator/models/struct.js +90 -0
- package/{lib → build}/get/generator/module-generator.d.ts +1 -0
- package/build/get/generator/module-generator.js +184 -0
- package/{lib → build}/get/generator/provider-generator.d.ts +1 -0
- package/build/get/generator/provider-generator.js +225 -0
- package/{lib → build}/get/generator/resource-parser.d.ts +1 -0
- package/build/get/generator/resource-parser.js +497 -0
- package/{lib → build}/get/generator/sanitized-comments.d.ts +1 -0
- package/build/get/generator/sanitized-comments.js +44 -0
- package/{lib → build}/get/generator/skipped-attributes.d.ts +1 -0
- package/build/get/generator/skipped-attributes.js +29 -0
- package/{lib → build}/index.d.ts +1 -0
- package/{lib → build}/index.js +1 -1
- package/{lib → build}/util.d.ts +1 -0
- package/build/util.js +30 -0
- package/package.json +13 -15
- package/{lib → src}/__tests__/__snapshots__/edge-provider-schema.test.ts.snap +1 -1
- package/{lib → src}/__tests__/__snapshots__/provider.test.ts.snap +14953 -890
- package/{lib → src}/get/__tests__/generator/__snapshots__/complex-computed-types.test.ts.snap +1 -1
- package/{lib → src}/get/__tests__/generator/__snapshots__/description-escaping.test.ts.snap +1 -1
- package/{lib → src}/get/__tests__/generator/__snapshots__/export-sharding.test.ts.snap +1 -1
- package/{lib → src}/get/__tests__/generator/__snapshots__/module-generator.test.ts.snap +10 -10
- package/{lib → src}/get/__tests__/generator/__snapshots__/nested-types.test.ts.snap +1 -1
- package/{lib → src}/get/__tests__/generator/__snapshots__/provider.test.ts.snap +1 -1
- package/{lib → src}/get/__tests__/generator/__snapshots__/resource-types.test.ts.snap +1 -1
- package/{lib → src}/get/__tests__/generator/__snapshots__/skipped-attributes.test.ts.snap +1 -1
- package/{lib → src}/get/__tests__/generator/__snapshots__/types.test.ts.snap +92 -1
- package/src/get/__tests__/generator/fixtures/map-of-map-of-string.test.fixture.json +27 -0
- package/tsconfig.json +6 -3
- package/lib/__tests__/edge-provider-schema/builder.js +0 -106
- package/lib/__tests__/edge-provider-schema/cli.d.ts +0 -1
- package/lib/__tests__/edge-provider-schema/cli.js +0 -67
- package/lib/__tests__/edge-provider-schema/index.js +0 -154
- package/lib/__tests__/edge-provider-schema.test.d.ts +0 -1
- package/lib/__tests__/edge-provider-schema.test.js +0 -46
- package/lib/__tests__/provider.test.d.ts +0 -1
- package/lib/__tests__/provider.test.js +0 -158
- package/lib/get/__tests__/constructs-maker.test.d.ts +0 -1
- package/lib/get/__tests__/constructs-maker.test.js +0 -113
- package/lib/get/__tests__/generator/complex-computed-types.test.d.ts +0 -1
- package/lib/get/__tests__/generator/complex-computed-types.test.js +0 -42
- package/lib/get/__tests__/generator/deep-nested-attributes.test.d.ts +0 -1
- package/lib/get/__tests__/generator/deep-nested-attributes.test.js +0 -50
- package/lib/get/__tests__/generator/description-escaping.test.d.ts +0 -1
- package/lib/get/__tests__/generator/description-escaping.test.js +0 -65
- package/lib/get/__tests__/generator/empty-provider-resources.test.d.ts +0 -1
- package/lib/get/__tests__/generator/empty-provider-resources.test.js +0 -40
- package/lib/get/__tests__/generator/export-sharding.test.d.ts +0 -1
- package/lib/get/__tests__/generator/export-sharding.test.js +0 -82
- package/lib/get/__tests__/generator/module-generator.test.d.ts +0 -1
- package/lib/get/__tests__/generator/module-generator.test.js +0 -476
- package/lib/get/__tests__/generator/nested-types.test.d.ts +0 -1
- package/lib/get/__tests__/generator/nested-types.test.js +0 -51
- package/lib/get/__tests__/generator/provider.test.d.ts +0 -1
- package/lib/get/__tests__/generator/provider.test.js +0 -51
- package/lib/get/__tests__/generator/resource-types.test.d.ts +0 -1
- package/lib/get/__tests__/generator/resource-types.test.js +0 -78
- package/lib/get/__tests__/generator/skipped-attributes.test.d.ts +0 -1
- package/lib/get/__tests__/generator/skipped-attributes.test.js +0 -55
- package/lib/get/__tests__/generator/types.test.d.ts +0 -1
- package/lib/get/__tests__/generator/types.test.js +0 -280
- package/lib/get/__tests__/generator/versions-file.test.d.ts +0 -1
- package/lib/get/__tests__/generator/versions-file.test.js +0 -74
- package/lib/get/__tests__/util.js +0 -59
- package/lib/get/generator/custom-defaults.js +0 -403
- package/lib/get/generator/emitter/attributes-emitter.js +0 -161
- package/lib/get/generator/emitter/resource-emitter.js +0 -144
- package/lib/get/generator/emitter/struct-emitter.js +0 -500
- package/lib/get/generator/loop-detection.js +0 -56
- package/lib/get/generator/models/attribute-model.js +0 -160
- package/lib/get/generator/models/attribute-type-model.js +0 -376
- package/lib/get/generator/models/resource-model.js +0 -106
- package/lib/get/generator/models/scope.js +0 -36
- package/lib/get/generator/models/struct.js +0 -90
- package/lib/get/generator/module-generator.js +0 -184
- package/lib/get/generator/provider-generator.js +0 -225
- package/lib/get/generator/resource-parser.js +0 -497
- package/lib/get/generator/sanitized-comments.js +0 -44
- package/lib/get/generator/skipped-attributes.js +0 -29
- package/lib/util.js +0 -30
- /package/{lib → src}/get/__tests__/generator/fixtures/aws-provider.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/aws_acm_certificate.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/aws_cloudfront_distribution.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/aws_fms_admin_account.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/aws_quicksight_template.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/aws_s3_bucket.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/aws_security_group.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/aws_wafv2_web_acl.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/block-type-nested-computed-list.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/block-type-set-list.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/boolean-list.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/boolean-map.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/comment-ending-sequence.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/computed-complex-nested.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/computed-complex.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/computed-optional-complex.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/data_aws_quicksight_analysis.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/datadog_dashboard.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/datadog_spans_metric.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/deep-attributes.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/deeply-nested-block-types.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/description-escaping.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/elasticstack-provider.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/empty-provider-resources.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/ignored-attributes.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/incompatible-attribute-names.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/incompatible-resource-names.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/list-list-object.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/list-list-string.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/list-of-string-map.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/map-of-string-list.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/markdown-description-with-code-blocks.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/module-get-x.test.fixture.tf +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/module-no-newline-1.test.fixture.tf +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/module-no-newline-2.test.fixture.tf +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/module-no-outputs.test.fixture.tf +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/module-no-variable-type.test.fixture.tf +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/module-with-star-default.test.fixture.tf +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/name-conflict.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/nested-type-without-attributes.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/nested-types.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/number-list.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/number-map.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/primitive-boolean.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/primitive-dynamic.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/primitive-number.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/primitive-string.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/single-block-type.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/string-list.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/string-map.test.fixture.json +0 -0
- /package/{lib → src}/get/__tests__/generator/fixtures/stripe-schema.test.fixture.json +0 -0
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ResourceParser = exports.sanitizeClassOrNamespaceName = void 0;
|
|
4
|
+
// Copyright (c) HashiCorp, Inc
|
|
5
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
6
|
+
const codemaker_1 = require("codemaker");
|
|
7
|
+
const commons_1 = require("@cdktn/commons");
|
|
8
|
+
const provider_schema_1 = require("@cdktn/provider-schema");
|
|
9
|
+
const models_1 = require("./models");
|
|
10
|
+
const loop_detection_1 = require("./loop-detection");
|
|
11
|
+
const skipped_attributes_1 = require("./skipped-attributes");
|
|
12
|
+
// Can't be used in expressions like "export * as <keyword> from ... "
|
|
13
|
+
// filtered from all keywords from: https://github.com/microsoft/TypeScript/blob/503604c884bd0557c851b11b699ef98cdb65b93b/src/compiler/types.ts#L114-L197
|
|
14
|
+
const RESERVED_KEYWORDS_FOR_NAMESPACES = [
|
|
15
|
+
"implements",
|
|
16
|
+
"interface",
|
|
17
|
+
"let",
|
|
18
|
+
"package",
|
|
19
|
+
"private",
|
|
20
|
+
"protected",
|
|
21
|
+
"public",
|
|
22
|
+
"static",
|
|
23
|
+
"yield",
|
|
24
|
+
"await",
|
|
25
|
+
];
|
|
26
|
+
const COLLIDING_NAMESPACE_NAMES = [
|
|
27
|
+
// e.g. hashicorp/consul – collides with the LICENSE file on case-insensitive filesystems in the Go package (#2627)
|
|
28
|
+
"license",
|
|
29
|
+
// collides for Go packages
|
|
30
|
+
"version",
|
|
31
|
+
];
|
|
32
|
+
const isReservedClassOrNamespaceName = (className) => {
|
|
33
|
+
return [
|
|
34
|
+
"string",
|
|
35
|
+
"object",
|
|
36
|
+
"function",
|
|
37
|
+
...RESERVED_KEYWORDS_FOR_NAMESPACES,
|
|
38
|
+
...COLLIDING_NAMESPACE_NAMES,
|
|
39
|
+
].includes(className.toLowerCase());
|
|
40
|
+
};
|
|
41
|
+
const isReservedStructClassName = (className) => {
|
|
42
|
+
return className.toLowerCase().endsWith("list");
|
|
43
|
+
};
|
|
44
|
+
const getFileName = (provider, baseName) => {
|
|
45
|
+
if (baseName === "index") {
|
|
46
|
+
return "index-resource/index.ts";
|
|
47
|
+
}
|
|
48
|
+
if (baseName === `${provider}_provider`) {
|
|
49
|
+
return "provider/index.ts";
|
|
50
|
+
}
|
|
51
|
+
return `${(0, codemaker_1.toSnakeCase)(baseName).replace(/_/g, "-")}/index.ts`;
|
|
52
|
+
};
|
|
53
|
+
function sanitizeClassOrNamespaceName(baseName, isProvider = false) {
|
|
54
|
+
const resourceIsNamedProvider = !isProvider && baseName === "provider";
|
|
55
|
+
if (isReservedClassOrNamespaceName(baseName) || resourceIsNamedProvider) {
|
|
56
|
+
return `${baseName}_resource`;
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
return baseName;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.sanitizeClassOrNamespaceName = sanitizeClassOrNamespaceName;
|
|
63
|
+
/**
|
|
64
|
+
* Remove attributes that may conflict after being snake cased
|
|
65
|
+
* Example: oci_core_ipsec_connection_tunnel_management (hashicorp/oci@=5.21.0) has bgp_ipv6_state and bgp_ipv6state
|
|
66
|
+
* (which both result in "bgpIpv6State" when camel-cased, with the second one being deprecated: true)
|
|
67
|
+
* As we currently don't handle any deprecated ones at all, we'll just delete one of the two attributes for now
|
|
68
|
+
* @param attributes
|
|
69
|
+
*/
|
|
70
|
+
function deduplicateAttributesWithSameName(attributes) {
|
|
71
|
+
return attributes.filter((attr, idx) => {
|
|
72
|
+
const hasOtherWithSameName = attributes
|
|
73
|
+
.slice(idx + 1) // only search after the index of the current attribute to avoid deleting both
|
|
74
|
+
.some((other) => other.name === attr.name && other !== attr);
|
|
75
|
+
return !hasOtherWithSameName;
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
class Parser {
|
|
79
|
+
constructor(classNames) {
|
|
80
|
+
this.classNames = classNames;
|
|
81
|
+
this.structs = new Array();
|
|
82
|
+
}
|
|
83
|
+
uniqueClassName(className) {
|
|
84
|
+
if (this.classNames.includes(className)) {
|
|
85
|
+
className = `${className}A`;
|
|
86
|
+
}
|
|
87
|
+
this.classNames.push(className);
|
|
88
|
+
return className;
|
|
89
|
+
}
|
|
90
|
+
resourceFrom(fqpn, type, schema, terraformSchemaType, constraint) {
|
|
91
|
+
let baseName = type;
|
|
92
|
+
const providerNameFromConstraint = constraint
|
|
93
|
+
? constraint.name
|
|
94
|
+
: undefined;
|
|
95
|
+
const providerNameFromFQPN = (0, provider_schema_1.parseFQPN)(fqpn).name;
|
|
96
|
+
if (baseName.startsWith(`${providerNameFromFQPN}_`)) {
|
|
97
|
+
baseName = baseName.substr(providerNameFromFQPN.length + 1);
|
|
98
|
+
}
|
|
99
|
+
const providerName = providerNameFromConstraint
|
|
100
|
+
? providerNameFromConstraint
|
|
101
|
+
: providerNameFromFQPN;
|
|
102
|
+
const isProvider = terraformSchemaType === "provider";
|
|
103
|
+
if (isProvider) {
|
|
104
|
+
baseName = `${providerName}_${baseName}`;
|
|
105
|
+
if (!("attributes" in schema.block)) {
|
|
106
|
+
schema.block = {
|
|
107
|
+
attributes: {},
|
|
108
|
+
block_types: schema.block.block_types || {},
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
// somehow missing from provider schema
|
|
112
|
+
schema.block.attributes["alias"] = {
|
|
113
|
+
type: "string",
|
|
114
|
+
description: "Alias name",
|
|
115
|
+
optional: true,
|
|
116
|
+
computed: false,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
baseName = sanitizeClassOrNamespaceName(baseName, isProvider);
|
|
120
|
+
const className = this.uniqueClassName((0, codemaker_1.toPascalCase)(baseName));
|
|
121
|
+
// avoid naming collision - see https://github.com/hashicorp/terraform-cdk/issues/299
|
|
122
|
+
const configStructName = this.uniqueClassName(`${className}Config`);
|
|
123
|
+
const fileName = getFileName(providerName, baseName);
|
|
124
|
+
const filePath = `providers/${(0, codemaker_1.toSnakeCase)(providerName)}/${fileName}`;
|
|
125
|
+
let attributes = this.renderAttributesForBlock(new models_1.Scope({
|
|
126
|
+
name: baseName,
|
|
127
|
+
isProvider,
|
|
128
|
+
parent: isProvider
|
|
129
|
+
? undefined
|
|
130
|
+
: new models_1.Scope({ name: providerName, isProvider: true }),
|
|
131
|
+
}), schema.block);
|
|
132
|
+
function getStructAttribute(attributes, path) {
|
|
133
|
+
const [first, ...rest] = path.split(".");
|
|
134
|
+
const attribute = attributes.find((att) => {
|
|
135
|
+
return att.terraformName === first;
|
|
136
|
+
});
|
|
137
|
+
if (!attribute)
|
|
138
|
+
throw new Error(`Expected to find recursive attribute at path: ${path}`);
|
|
139
|
+
if (!attribute.type.struct)
|
|
140
|
+
throw new Error(`Expected to find struct type attribute at path: ${path} but got ${attribute.type.storedClassType}`);
|
|
141
|
+
if (rest.length === 0)
|
|
142
|
+
return attribute;
|
|
143
|
+
return getStructAttribute(attribute.type.struct.attributes, rest.join("."));
|
|
144
|
+
}
|
|
145
|
+
// Introduce recursion for some attributes
|
|
146
|
+
const recursiveAttributePaths = (0, loop_detection_1.detectAttributeLoops)(attributes);
|
|
147
|
+
Object.entries(recursiveAttributePaths).forEach(([attributePath, structPath]) => {
|
|
148
|
+
// TODO: build this to be a bit more defensive (e.g. remove ! operator)
|
|
149
|
+
const recursionTargetStructAttribute = getStructAttribute(attributes, structPath);
|
|
150
|
+
const parts = attributePath.split(".");
|
|
151
|
+
const attributeName = parts.pop();
|
|
152
|
+
const parentAttribute = getStructAttribute(attributes, parts.join("."));
|
|
153
|
+
const indexToReplace = parentAttribute.type.struct.attributes.findIndex((att) => att.terraformName === attributeName);
|
|
154
|
+
if (indexToReplace === -1)
|
|
155
|
+
throw new Error("Can't find attribute at path " + attributePath);
|
|
156
|
+
const previousAttribute = parentAttribute.type.struct.attributes[indexToReplace];
|
|
157
|
+
parentAttribute.type.struct.attributes[indexToReplace] =
|
|
158
|
+
recursionTargetStructAttribute; // introduce recursion
|
|
159
|
+
// ugly, pls c̶a̶l̶l̶ refactor me maybe
|
|
160
|
+
// we store all structs in this.structs – now we need to dispose all structs that are part of previousAttribute
|
|
161
|
+
const disposeStructs = (attr) => {
|
|
162
|
+
if (attr.type.struct) {
|
|
163
|
+
attr.type.struct.attributes.forEach(disposeStructs);
|
|
164
|
+
this.structs = this.structs.filter((s) => s !== attr.type.struct);
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
disposeStructs(previousAttribute);
|
|
168
|
+
});
|
|
169
|
+
attributes = deduplicateAttributesWithSameName(attributes);
|
|
170
|
+
const resourceModel = new models_1.ResourceModel({
|
|
171
|
+
terraformType: type,
|
|
172
|
+
baseName,
|
|
173
|
+
fileName,
|
|
174
|
+
filePath,
|
|
175
|
+
className,
|
|
176
|
+
schema,
|
|
177
|
+
fqpn,
|
|
178
|
+
attributes,
|
|
179
|
+
terraformSchemaType,
|
|
180
|
+
structs: this.structs,
|
|
181
|
+
configStructName,
|
|
182
|
+
});
|
|
183
|
+
return resourceModel;
|
|
184
|
+
}
|
|
185
|
+
renderAttributeType(scope, attributeType, parentKind) {
|
|
186
|
+
const parent = scope[scope.length - 1];
|
|
187
|
+
if ((0, skipped_attributes_1.shouldSkipAttribute)(parent.baseName)) {
|
|
188
|
+
return new models_1.MapAttributeTypeModel(new models_1.SimpleAttributeTypeModel("any"));
|
|
189
|
+
}
|
|
190
|
+
if (typeof attributeType === "string") {
|
|
191
|
+
switch (attributeType) {
|
|
192
|
+
case "bool":
|
|
193
|
+
return new models_1.SimpleAttributeTypeModel("boolean");
|
|
194
|
+
case "string":
|
|
195
|
+
return new models_1.SimpleAttributeTypeModel("string");
|
|
196
|
+
case "number":
|
|
197
|
+
return new models_1.SimpleAttributeTypeModel("number");
|
|
198
|
+
case "dynamic":
|
|
199
|
+
return new models_1.MapAttributeTypeModel(new models_1.SimpleAttributeTypeModel("any"));
|
|
200
|
+
default:
|
|
201
|
+
throw new Error(`invalid primitive type ${attributeType}`);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
if (Array.isArray(attributeType)) {
|
|
205
|
+
if (attributeType.length !== 2) {
|
|
206
|
+
throw new Error(`unexpected array`);
|
|
207
|
+
}
|
|
208
|
+
const [kind, type] = attributeType;
|
|
209
|
+
if (kind === "set" || kind === "list") {
|
|
210
|
+
const elementType = this.renderAttributeType(scope, type, [kind, parentKind].join(""));
|
|
211
|
+
return kind === "list"
|
|
212
|
+
? new models_1.ListAttributeTypeModel(elementType, false, false)
|
|
213
|
+
: new models_1.SetAttributeTypeModel(elementType, false, false);
|
|
214
|
+
}
|
|
215
|
+
if (kind === "map") {
|
|
216
|
+
const valueType = this.renderAttributeType(scope, type, [kind, parentKind].join(""));
|
|
217
|
+
return new models_1.MapAttributeTypeModel(valueType);
|
|
218
|
+
}
|
|
219
|
+
if (kind === "object") {
|
|
220
|
+
const objAttributes = type;
|
|
221
|
+
const attributes = {};
|
|
222
|
+
for (const [name, type] of Object.entries(objAttributes)) {
|
|
223
|
+
attributes[name] = { type };
|
|
224
|
+
}
|
|
225
|
+
const struct = this.addAnonymousStruct(scope, attributes, parentKind !== null && parentKind !== void 0 ? parentKind : kind);
|
|
226
|
+
return new models_1.StructAttributeTypeModel(struct);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
if ((0, commons_1.isAttributeNestedType)(attributeType)) {
|
|
230
|
+
let struct = undefined;
|
|
231
|
+
let typeModel = undefined;
|
|
232
|
+
switch (attributeType.nesting_mode) {
|
|
233
|
+
case "list":
|
|
234
|
+
struct = this.addAnonymousStruct(scope, attributeType.attributes, attributeType.nesting_mode);
|
|
235
|
+
typeModel = new models_1.ListAttributeTypeModel(new models_1.StructAttributeTypeModel(struct), false, false);
|
|
236
|
+
break;
|
|
237
|
+
case "set":
|
|
238
|
+
struct = this.addAnonymousStruct(scope, attributeType.attributes, attributeType.nesting_mode);
|
|
239
|
+
typeModel = new models_1.SetAttributeTypeModel(new models_1.StructAttributeTypeModel(struct), false, false);
|
|
240
|
+
break;
|
|
241
|
+
case "map":
|
|
242
|
+
struct = this.addAnonymousStruct(scope, attributeType.attributes, attributeType.nesting_mode);
|
|
243
|
+
typeModel = new models_1.MapAttributeTypeModel(new models_1.StructAttributeTypeModel(struct));
|
|
244
|
+
break;
|
|
245
|
+
case "single":
|
|
246
|
+
struct = this.addAnonymousStruct(scope, attributeType.attributes, attributeType.nesting_mode);
|
|
247
|
+
typeModel = new models_1.StructAttributeTypeModel(struct);
|
|
248
|
+
break;
|
|
249
|
+
default: {
|
|
250
|
+
throw new Error(`nested_type with nesting_mode "${attributeType.nesting_mode}" not supported (attribute scope: ${scope
|
|
251
|
+
.map((s) => s.fullName)
|
|
252
|
+
.join(",")}`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return typeModel;
|
|
256
|
+
}
|
|
257
|
+
throw new Error(`unknown type ${JSON.stringify(attributeType)}`);
|
|
258
|
+
}
|
|
259
|
+
renderAttributesForBlock(parentType, block) {
|
|
260
|
+
const attributes = new Array();
|
|
261
|
+
for (const [terraformAttributeName, att] of Object.entries(block.attributes || {})) {
|
|
262
|
+
let type;
|
|
263
|
+
let forcePlainGetterType = false;
|
|
264
|
+
if ((0, skipped_attributes_1.shouldSkipAttribute)(parentType.fullName(terraformAttributeName))) {
|
|
265
|
+
type = new models_1.SkippedAttributeTypeModel();
|
|
266
|
+
forcePlainGetterType = true;
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
type = this.renderAttributeType([
|
|
270
|
+
parentType,
|
|
271
|
+
new models_1.Scope({
|
|
272
|
+
name: terraformAttributeName,
|
|
273
|
+
parent: parentType,
|
|
274
|
+
isProvider: parentType.isProvider,
|
|
275
|
+
isComputed: !!att.computed,
|
|
276
|
+
isOptional: !!att.optional,
|
|
277
|
+
isRequired: !!att.required,
|
|
278
|
+
isNestedType: (0, commons_1.isNestedTypeAttribute)(att),
|
|
279
|
+
}),
|
|
280
|
+
], att.type || att.nested_type);
|
|
281
|
+
}
|
|
282
|
+
const name = (0, codemaker_1.toCamelCase)(terraformAttributeName);
|
|
283
|
+
attributes.push(new models_1.AttributeModel({
|
|
284
|
+
terraformFullName: parentType.fullName(terraformAttributeName),
|
|
285
|
+
description: att.description,
|
|
286
|
+
name,
|
|
287
|
+
storageName: `_${name}`,
|
|
288
|
+
computed: !!att.computed,
|
|
289
|
+
optional: !!att.optional,
|
|
290
|
+
terraformName: terraformAttributeName,
|
|
291
|
+
type,
|
|
292
|
+
provider: parentType.isProvider,
|
|
293
|
+
required: !!att.required,
|
|
294
|
+
forcePlainGetterType,
|
|
295
|
+
}));
|
|
296
|
+
}
|
|
297
|
+
for (const [blockTypeName, blockType] of Object.entries(block.block_types || {})) {
|
|
298
|
+
if ((0, skipped_attributes_1.shouldSkipAttribute)(parentType.fullName(blockTypeName))) {
|
|
299
|
+
const name = (0, codemaker_1.toCamelCase)(blockTypeName);
|
|
300
|
+
const parent = new models_1.Scope({
|
|
301
|
+
name: blockTypeName,
|
|
302
|
+
parent: parentType,
|
|
303
|
+
isProvider: parentType.isProvider,
|
|
304
|
+
});
|
|
305
|
+
attributes.push(new models_1.AttributeModel({
|
|
306
|
+
name,
|
|
307
|
+
terraformName: blockTypeName,
|
|
308
|
+
terraformFullName: parent.fullName(blockTypeName),
|
|
309
|
+
type: new models_1.SkippedAttributeTypeModel(),
|
|
310
|
+
description: `${blockTypeName} block`,
|
|
311
|
+
storageName: `_${name}`,
|
|
312
|
+
optional: true,
|
|
313
|
+
computed: false,
|
|
314
|
+
provider: parentType.isProvider,
|
|
315
|
+
required: false,
|
|
316
|
+
}));
|
|
317
|
+
continue;
|
|
318
|
+
}
|
|
319
|
+
// create a struct for this block
|
|
320
|
+
let blockAttributes = this.renderAttributesForBlock(new models_1.Scope({
|
|
321
|
+
name: `${parentType.name}_${blockTypeName}`,
|
|
322
|
+
parent: parentType,
|
|
323
|
+
isProvider: parentType.isProvider,
|
|
324
|
+
inBlockType: true,
|
|
325
|
+
}), blockType.block);
|
|
326
|
+
blockAttributes = deduplicateAttributesWithSameName(blockAttributes);
|
|
327
|
+
const blockStruct = this.addStruct([
|
|
328
|
+
parentType,
|
|
329
|
+
new models_1.Scope({
|
|
330
|
+
name: blockTypeName,
|
|
331
|
+
parent: parentType,
|
|
332
|
+
isProvider: parentType.isProvider,
|
|
333
|
+
}),
|
|
334
|
+
], blockAttributes, blockType.nesting_mode, (blockType.nesting_mode === "list" ||
|
|
335
|
+
blockType.nesting_mode === "set") &&
|
|
336
|
+
blockType.max_items === 1);
|
|
337
|
+
// define the attribute
|
|
338
|
+
attributes.push(attributeForBlockType(blockTypeName, blockType, blockStruct, parentType.isProvider, parentType));
|
|
339
|
+
}
|
|
340
|
+
return attributes;
|
|
341
|
+
function attributeForBlockType(terraformName, blockType, struct, isProvider, parent) {
|
|
342
|
+
const name = (0, codemaker_1.toCamelCase)(terraformName);
|
|
343
|
+
let optional;
|
|
344
|
+
let required;
|
|
345
|
+
switch (blockType.nesting_mode) {
|
|
346
|
+
case "single":
|
|
347
|
+
optional = !struct.attributes.some((x) => !x.optional);
|
|
348
|
+
required = !struct.attributes.some((x) => !x.required);
|
|
349
|
+
// This is for bug #3570 as both optional and required evaluate to false under some circumstances
|
|
350
|
+
// (this then causes the computed block to not be part of assignableAttributes and thus skipped in the generated code)
|
|
351
|
+
// Hence: If both optional and required are false, set optional to true IF at least one
|
|
352
|
+
// attribute in the block has optional = true or required = true, as this would mean that at least something can be set
|
|
353
|
+
// and the block is not all computed.
|
|
354
|
+
if (!optional && !required) {
|
|
355
|
+
optional = struct.attributes.some((x) => x.optional || x.required);
|
|
356
|
+
}
|
|
357
|
+
return new models_1.AttributeModel({
|
|
358
|
+
name,
|
|
359
|
+
terraformName,
|
|
360
|
+
terraformFullName: parent.fullName(terraformName),
|
|
361
|
+
type: new models_1.StructAttributeTypeModel(struct),
|
|
362
|
+
description: `${terraformName} block`,
|
|
363
|
+
storageName: `_${name}`,
|
|
364
|
+
optional,
|
|
365
|
+
computed: false,
|
|
366
|
+
provider: isProvider,
|
|
367
|
+
required,
|
|
368
|
+
});
|
|
369
|
+
case "map":
|
|
370
|
+
return new models_1.AttributeModel({
|
|
371
|
+
name,
|
|
372
|
+
terraformName,
|
|
373
|
+
terraformFullName: parent.fullName(terraformName),
|
|
374
|
+
type: new models_1.MapAttributeTypeModel(new models_1.StructAttributeTypeModel(struct)),
|
|
375
|
+
description: `${terraformName} block`,
|
|
376
|
+
storageName: `_${name}`,
|
|
377
|
+
optional: false,
|
|
378
|
+
computed: false,
|
|
379
|
+
provider: isProvider,
|
|
380
|
+
required: false,
|
|
381
|
+
});
|
|
382
|
+
case "list":
|
|
383
|
+
case "set":
|
|
384
|
+
optional =
|
|
385
|
+
blockType.min_items === undefined ? true : blockType.min_items < 1;
|
|
386
|
+
required =
|
|
387
|
+
blockType.min_items === undefined ? false : blockType.min_items > 0;
|
|
388
|
+
return new models_1.AttributeModel({
|
|
389
|
+
name,
|
|
390
|
+
terraformName: terraformName,
|
|
391
|
+
terraformFullName: parent.fullName(terraformName),
|
|
392
|
+
type: blockType.nesting_mode === "list"
|
|
393
|
+
? new models_1.ListAttributeTypeModel(new models_1.StructAttributeTypeModel(struct), blockType.max_items === 1, true)
|
|
394
|
+
: new models_1.SetAttributeTypeModel(new models_1.StructAttributeTypeModel(struct), blockType.max_items === 1, true),
|
|
395
|
+
description: `${terraformName} block`,
|
|
396
|
+
storageName: `_${name}`,
|
|
397
|
+
optional,
|
|
398
|
+
computed: false,
|
|
399
|
+
provider: isProvider,
|
|
400
|
+
required,
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
addAnonymousStruct(scope, attrs, nesting_mode) {
|
|
406
|
+
let attributes = new Array();
|
|
407
|
+
const parent = scope[scope.length - 1];
|
|
408
|
+
if (attrs) {
|
|
409
|
+
for (const [terraformName, att] of Object.entries(attrs || {})) {
|
|
410
|
+
// nested types support computed, optional and required on attribute level
|
|
411
|
+
// if parent is computed, child always is computed as well
|
|
412
|
+
const computed = !!parent.isComputed || (parent.isNestedType && !!att.computed);
|
|
413
|
+
const optional = parent.isNestedType
|
|
414
|
+
? !!att.optional
|
|
415
|
+
: !!parent.isOptional;
|
|
416
|
+
const required = parent.isNestedType
|
|
417
|
+
? !!att.required
|
|
418
|
+
: !!parent.isRequired;
|
|
419
|
+
const name = (0, codemaker_1.toCamelCase)(terraformName);
|
|
420
|
+
const type = this.renderAttributeType([
|
|
421
|
+
...scope,
|
|
422
|
+
new models_1.Scope({
|
|
423
|
+
name: terraformName,
|
|
424
|
+
parent,
|
|
425
|
+
isProvider: parent.isProvider,
|
|
426
|
+
isComputed: computed,
|
|
427
|
+
isOptional: optional,
|
|
428
|
+
isRequired: required,
|
|
429
|
+
isNestedType: parent.isNestedType,
|
|
430
|
+
}),
|
|
431
|
+
], att.type || att.nested_type);
|
|
432
|
+
attributes.push(new models_1.AttributeModel({
|
|
433
|
+
name,
|
|
434
|
+
storageName: `_${name}`,
|
|
435
|
+
computed: computed,
|
|
436
|
+
description: att.description,
|
|
437
|
+
optional: optional,
|
|
438
|
+
terraformName,
|
|
439
|
+
terraformFullName: parent.fullName(terraformName),
|
|
440
|
+
type,
|
|
441
|
+
provider: parent.isProvider,
|
|
442
|
+
required: required,
|
|
443
|
+
}));
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
attributes = deduplicateAttributesWithSameName(attributes);
|
|
447
|
+
return this.addStruct(scope, attributes, nesting_mode);
|
|
448
|
+
}
|
|
449
|
+
addStruct(scope, attributes, nesting_mode, isSingleItem = false) {
|
|
450
|
+
const possibleName = (0, codemaker_1.toPascalCase)(scope.map((x) => (0, codemaker_1.toSnakeCase)(x.name)).join("_"));
|
|
451
|
+
const name = this.uniqueClassName(isReservedStructClassName(possibleName)
|
|
452
|
+
? `${possibleName}Struct`
|
|
453
|
+
: possibleName);
|
|
454
|
+
const parent = scope[scope.length - 1];
|
|
455
|
+
// blockType.nesting_mode => list/set & blockType.max_items === 1,
|
|
456
|
+
const isClass = (parent.isComputed && !parent.isOptional) || isSingleItem;
|
|
457
|
+
const isAnonymous = true;
|
|
458
|
+
const s = new models_1.Struct(name, attributes, isClass, isAnonymous, isSingleItem, nesting_mode);
|
|
459
|
+
this.structs.push(s);
|
|
460
|
+
return s;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
class ResourceParser {
|
|
464
|
+
constructor() {
|
|
465
|
+
this.uniqueClassnames = [];
|
|
466
|
+
this.resources = {};
|
|
467
|
+
}
|
|
468
|
+
parse(fqpn, type, schema, terraformType, constraint) {
|
|
469
|
+
if (this.resources[type]) {
|
|
470
|
+
return this.resources[type];
|
|
471
|
+
}
|
|
472
|
+
const parser = new Parser(this.uniqueClassnames);
|
|
473
|
+
const resource = parser.resourceFrom(fqpn, type, schema, terraformType, constraint);
|
|
474
|
+
this.resources[type] = resource;
|
|
475
|
+
return resource;
|
|
476
|
+
}
|
|
477
|
+
// Used by convert to determine the right name for a class
|
|
478
|
+
getClassNameForResource(terraformType) {
|
|
479
|
+
const resource = this.resources[terraformType];
|
|
480
|
+
return resource ? resource.className : "";
|
|
481
|
+
}
|
|
482
|
+
// Used by convert to determine the right name for a namespace
|
|
483
|
+
getNamespaceNameForResource(terraformType) {
|
|
484
|
+
// Special case external provider since the name of resource doesn't have a prefix
|
|
485
|
+
if (terraformType === "data_external_") {
|
|
486
|
+
terraformType = "data_external";
|
|
487
|
+
}
|
|
488
|
+
const resource = this.resources[terraformType];
|
|
489
|
+
if (!resource) {
|
|
490
|
+
return "";
|
|
491
|
+
}
|
|
492
|
+
const folder = `providers/${resource.provider}`;
|
|
493
|
+
return resource.filePath.replace(`${folder}/`, "").replace("/index.ts", "");
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
exports.ResourceParser = ResourceParser;
|
|
497
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzb3VyY2UtcGFyc2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2dldC9nZW5lcmF0b3IvcmVzb3VyY2UtcGFyc2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLCtCQUErQjtBQUMvQixtQ0FBbUM7QUFDbkMseUNBQW1FO0FBQ25FLDRDQVV3QjtBQUN4Qiw0REFBdUU7QUFDdkUscUNBWWtCO0FBQ2xCLHFEQUF3RDtBQUN4RCw2REFBMkQ7QUFFM0Qsc0VBQXNFO0FBQ3RFLHlKQUF5SjtBQUN6SixNQUFNLGdDQUFnQyxHQUFHO0lBQ3ZDLFlBQVk7SUFDWixXQUFXO0lBQ1gsS0FBSztJQUNMLFNBQVM7SUFDVCxTQUFTO0lBQ1QsV0FBVztJQUNYLFFBQVE7SUFDUixRQUFRO0lBQ1IsT0FBTztJQUNQLE9BQU87Q0FDUixDQUFDO0FBRUYsTUFBTSx5QkFBeUIsR0FBRztJQUNoQyxtSEFBbUg7SUFDbkgsU0FBUztJQUNULDJCQUEyQjtJQUMzQixTQUFTO0NBQ1YsQ0FBQztBQUVGLE1BQU0sOEJBQThCLEdBQUcsQ0FBQyxTQUFpQixFQUFXLEVBQUU7SUFDcEUsT0FBTztRQUNMLFFBQVE7UUFDUixRQUFRO1FBQ1IsVUFBVTtRQUNWLEdBQUcsZ0NBQWdDO1FBQ25DLEdBQUcseUJBQXlCO0tBQzdCLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO0FBQ3RDLENBQUMsQ0FBQztBQUVGLE1BQU0seUJBQXlCLEdBQUcsQ0FBQyxTQUFpQixFQUFXLEVBQUU7SUFDL0QsT0FBTyxTQUFTLENBQUMsV0FBVyxFQUFFLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQ2xELENBQUMsQ0FBQztBQUVGLE1BQU0sV0FBVyxHQUFHLENBQUMsUUFBc0IsRUFBRSxRQUFnQixFQUFVLEVBQUU7SUFDdkUsSUFBSSxRQUFRLEtBQUssT0FBTyxFQUFFLENBQUM7UUFDekIsT0FBTyx5QkFBeUIsQ0FB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LE1BQU0sRUFDTixhQUFhLEVBQ2IsVUFBVSxDQUNYLENBQUM7UUFDRixJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxHQUFHLFFBQVEsQ0FBQztRQUNoQyxPQUFPLFFBQVEsQ0FBQztJQUNsQixDQUFDO0lBRUQsMERBQTBEO0lBQ25ELHVCQUF1QixDQUFDLGFBQXFCO1FBQ2xELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDL0MsT0FBTyxRQUFRLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUM1QyxDQUFDO0lBRUQsOERBQThEO0lBQ3ZELDJCQUEyQixDQUFDLGFBQXFCO1FBQ3RELGtGQUFrRjtRQUNsRixJQUFJLGFBQWEsS0FBSyxnQkFBZ0IsRUFBRSxDQUFDO1lBQ3ZDLGFBQWEsR0FBRyxlQUFlLENBQUM7UUFDbEMsQ0FBQztRQUVELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDL0MsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ2QsT0FBTyxFQUFFLENBQUM7UUFDWixDQUFDO1FBQ0QsTUFBTSxNQUFNLEdBQUcsYUFBYSxRQUFRLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDaEQsT0FBTyxRQUFRLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxHQUFHLE1BQU0sR0FBRyxFQUFFLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDOUUsQ0FBQztDQUNGO0FBL0NELHdDQStDQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAoYykgSGFzaGlDb3JwLCBJbmNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBNUEwtMi4wXG5pbXBvcnQgeyB0b0NhbWVsQ2FzZSwgdG9QYXNjYWxDYXNlLCB0b1NuYWtlQ2FzZSB9IGZyb20gXCJjb2RlbWFrZXJcIjtcbmltcG9ydCB7XG4gIEF0dHJpYnV0ZSxcbiAgQXR0cmlidXRlTmVzdGVkVHlwZSxcbiAgQXR0cmlidXRlVHlwZSxcbiAgQmxvY2ssXG4gIEJsb2NrVHlwZSxcbiAgQ29uc3RydWN0c01ha2VyVGFyZ2V0LFxuICBpc0F0dHJpYnV0ZU5lc3RlZFR5cGUsXG4gIGlzTmVzdGVkVHlwZUF0dHJpYnV0ZSxcbiAgU2NoZW1hLFxufSBmcm9tIFwiQGNka3RuL2NvbW1vbnNcIjtcbmltcG9ydCB7IFByb3ZpZGVyTmFtZSwgRlFQTiwgcGFyc2VGUVBOIH0gZnJvbSBcIkBjZGt0bi9wcm92aWRlci1zY2hlbWFcIjtcbmltcG9ydCB7XG4gIFJlc291cmNlTW9kZWwsXG4gIEF0dHJpYnV0ZVR5cGVNb2RlbCxcbiAgU3RydWN0LFxuICBTY29wZSxcbiAgQXR0cmlidXRlTW9kZWwsXG4gIFNpbXBsZUF0dHJpYnV0ZVR5cGVNb2RlbCxcbiAgTGlzdEF0dHJpYnV0ZVR5cGVNb2RlbCxcbiAgU2V0QXR0cmlidXRlVHlwZU1vZGVsLFxuICBNYXBBdHRyaWJ1dGVUeXBlTW9kZWwsXG4gIFN0cnVjdEF0dHJpYnV0ZVR5cGVNb2RlbCxcbiAgU2tpcHBlZEF0dHJpYnV0ZVR5cGVNb2RlbCxcbn0gZnJvbSBcIi4vbW9kZWxzXCI7XG5pbXBvcnQgeyBkZXRlY3RBdHRyaWJ1dGVMb29wcyB9IGZyb20gXCIuL2xvb3AtZGV0ZWN0aW9uXCI7XG5pbXBvcnQgeyBzaG91bGRTa2lwQXR0cmlidXRlIH0gZnJvbSBcIi4vc2tpcHBlZC1hdHRyaWJ1dGVzXCI7XG5cbi8vIENhbid0IGJlIHVzZWQgaW4gZXhwcmVzc2lvbnMgbGlrZSBcImV4cG9ydCAqIGFzIDxrZXl3b3JkPiBmcm9tIC4uLiBcIlxuLy8gZmlsdGVyZWQgZnJvbSBhbGwga2V5d29yZHMgZnJvbTogaHR0cHM6Ly9naXRodWIuY29tL21pY3Jvc29mdC9UeXBlU2NyaXB0L2Jsb2IvNTAzNjA0Yzg4NGJkMDU1N2M4NTFiMTFiNjk5ZWY5OGNkYjY1YjkzYi9zcmMvY29tcGlsZXIvdHlwZXMudHMjTDExNC1MMTk3XG5jb25zdCBSRVNFUlZFRF9LRVlXT1JEU19GT1JfTkFNRVNQQUNFUyA9IFtcbiAgXCJpbXBsZW1lbnRzXCIsXG4gIFwiaW50ZXJmYWNlXCIsXG4gIFwibGV0XCIsXG4gIFwicGFja2FnZVwiLFxuICBcInByaXZhdGVcIixcbiAgXCJwcm90ZWN0ZWRcIixcbiAgXCJwdWJsaWNcIixcbiAgXCJzdGF0aWNcIixcbiAgXCJ5aWVsZFwiLFxuICBcImF3YWl0XCIsXG5dO1xuXG5jb25zdCBDT0xMSURJTkdfTkFNRVNQQUNFX05BTUVTID0gW1xuICAvLyBlLmcuIGhhc2hpY29ycC9jb25zdWwg4oCTIGNvbGxpZGVzIHdpdGggdGhlIExJQ0VOU0UgZmlsZSBvbiBjYXNlLWluc2Vuc2l0aXZlIGZpbGVzeXN0ZW1zIGluIHRoZSBHbyBwYWNrYWdlICgjMjYyNylcbiAgXCJsaWNlbnNlXCIsXG4gIC8vIGNvbGxpZGVzIGZvciBHbyBwYWNrYWdlc1xuICBcInZlcnNpb25cIixcbl07XG5cbmNvbnN0IGlzUmVzZXJ2ZWRDbGFzc09yTmFtZXNwYWNlTmFtZSA9IChjbGFzc05hbWU6IHN0cmluZyk6IGJvb2xlYW4gPT4ge1xuICByZXR1cm4gW1xuICAgIFwic3RyaW5nXCIsXG4gICAgXCJvYmplY3RcIixcbiAgICBcImZ1bmN0aW9uXCIsXG4gICAgLi4uUkVTRVJWRURfS0VZV09SRFNfRk9SX05BTUVTUEFDRVMsXG4gICAgLi4uQ09MTElESU5HX05BTUVTUEFDRV9OQU1FUyxcbiAgXS5pbmNsdWRlcyhjbGFzc05hbWUudG9Mb3dlckNhc2UoKSk7XG59O1xuXG5jb25zdCBpc1Jlc2VydmVkU3RydWN0Q2xhc3NOYW1lID0gKGNsYXNzTmFtZTogc3RyaW5nKTogYm9vbGVhbiA9PiB7XG4gIHJldHVybiBjbGFzc05hbWUudG9Mb3dlckNhc2UoKS5lbmRzV2l0aChcImxpc3RcIik7XG59O1xuXG5jb25zdCBnZXRGaWxlTmFtZSA9IChwcm92aWRlcjogUHJvdmlkZXJOYW1lLCBiYXNlTmFtZTogc3RyaW5nKTogc3RyaW5nID0+IHtcbiAgaWYgKGJhc2VOYW1lID09PSBcImluZGV4XCIpIHtcbiAgICByZXR1cm4gXCJpbmRleC1yZXNvdXJjZS9pbmRleC50c1wiO1xuICB9XG5cbiAgaWYgKGJhc2VOYW1lID09PSBgJHtwcm92aWRlcn1fcHJvdmlkZXJgKSB7XG4gICAgcmV0dXJuIFwicHJvdmlkZXIvaW5kZXgudHNcIjtcbiAgfVxuXG4gIHJldHVybiBgJHt0b1NuYWtlQ2FzZShiYXNlTmFtZSkucmVwbGFjZSgvXy9nLCBcIi1cIil9L2luZGV4LnRzYDtcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBzYW5pdGl6ZUNsYXNzT3JOYW1lc3BhY2VOYW1lKFxuICBiYXNlTmFtZTogc3RyaW5nLFxuICBpc1Byb3ZpZGVyID0gZmFsc2UsXG4pIHtcbiAgY29uc3QgcmVzb3VyY2VJc05hbWVkUHJvdmlkZXIgPSAhaXNQcm92aWRlciAmJiBiYXNlTmFtZSA9PT0gXCJwcm92aWRlclwiO1xuXG4gIGlmIChpc1Jlc2VydmVkQ2xhc3NPck5hbWVzcGFjZU5hbWUoYmFzZU5hbWUpIHx8IHJlc291cmNlSXNOYW1lZFByb3ZpZGVyKSB7XG4gICAgcmV0dXJuIGAke2Jhc2VOYW1lfV9yZXNvdXJjZWA7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGJhc2VOYW1lO1xuICB9XG59XG5cbi8qKlxuICogUmVtb3ZlIGF0dHJpYnV0ZXMgdGhhdCBtYXkgY29uZmxpY3QgYWZ0ZXIgYmVpbmcgc25ha2UgY2FzZWRcbiAqIEV4YW1wbGU6IG9jaV9jb3JlX2lwc2VjX2Nvbm5lY3Rpb25fdHVubmVsX21hbmFnZW1lbnQgKGhhc2hpY29ycC9vY2lAPTUuMjEuMCkgaGFzIGJncF9pcHY2X3N0YXRlIGFuZCBiZ3BfaXB2NnN0YXRlXG4gKiAod2hpY2ggYm90aCByZXN1bHQgaW4gXCJiZ3BJcHY2U3RhdGVcIiB3aGVuIGNhbWVsLWNhc2VkLCB3aXRoIHRoZSBzZWNvbmQgb25lIGJlaW5nIGRlcHJlY2F0ZWQ6IHRydWUpXG4gKiBBcyB3ZSBjdXJyZW50bHkgZG9uJ3QgaGFuZGxlIGFueSBkZXByZWNhdGVkIG9uZXMgYXQgYWxsLCB3ZSdsbCBqdXN0IGRlbGV0ZSBvbmUgb2YgdGhlIHR3byBhdHRyaWJ1dGVzIGZvciBub3dcbiAqIEBwYXJhbSBhdHRyaWJ1dGVzXG4gKi9cbmZ1bmN0aW9uIGRlZHVwbGljYXRlQXR0cmlidXRlc1dpdGhTYW1lTmFtZShcbiAgYXR0cmlidXRlczogQXR0cmlidXRlTW9kZWxbXSxcbik6IEF0dHJpYnV0ZU1vZGVsW10ge1xuICByZXR1cm4gYXR0cmlidXRlcy5maWx0ZXIoKGF0dHIsIGlkeCkgPT4ge1xuICAgIGNvbnN0IGhhc090aGVyV2l0aFNhbWVOYW1lID0gYXR0cmlidXRlc1xuICAgICAgLnNsaWNlKGlkeCArIDEpIC8vIG9ubHkgc2VhcmNoIGFmdGVyIHRoZSBpbmRleCBvZiB0aGUgY3VycmVudCBhdHRyaWJ1dGUgdG8gYXZvaWQgZGVsZXRpbmcgYm90aFxuICAgICAgLnNvbWUoKG90aGVyKSA9PiBvdGhlci5uYW1lID09PSBhdHRyLm5hbWUgJiYgb3RoZXIgIT09IGF0dHIpO1xuICAgIHJldHVybiAhaGFzT3RoZXJXaXRoU2FtZU5hbWU7XG4gIH0pO1xufVxuXG5jbGFzcyBQYXJzZXIge1xuICBwcml2YXRlIHN0cnVjdHMgPSBuZXcgQXJyYXk8U3RydWN0PigpO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgY2xhc3NOYW1lczogc3RyaW5nW10pIHt9XG5cbiAgcHJpdmF0ZSB1bmlxdWVDbGFzc05hbWUoY2xhc3NOYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGlmICh0aGlzLmNsYXNzTmFtZXMuaW5jbHVkZXMoY2xhc3NOYW1lKSkge1xuICAgICAgY2xhc3NOYW1lID0gYCR7Y2xhc3NOYW1lfUFgO1xuICAgIH1cbiAgICB0aGlzLmNsYXNzTmFtZXMucHVzaChjbGFzc05hbWUpO1xuICAgIHJldHVybiBjbGFzc05hbWU7XG4gIH1cblxuICBwdWJsaWMgcmVzb3VyY2VGcm9tKFxuICAgIGZxcG46IEZRUE4sXG4gICAgdHlwZTogc3RyaW5nLFxuICAgIHNjaGVtYTogU2NoZW1hLFxuICAgIHRlcnJhZm9ybVNjaGVtYVR5cGU6IHN0cmluZyxcbiAgICBjb25zdHJhaW50PzogQ29uc3RydWN0c01ha2VyVGFyZ2V0LFxuICApOiBSZXNvdXJjZU1vZGVsIHtcbiAgICBsZXQgYmFzZU5hbWUgPSB0eXBlO1xuXG4gICAgY29uc3QgcHJvdmlkZXJOYW1lRnJvbUNvbnN0cmFpbnQgPSBjb25zdHJhaW50XG4gICAgICA/IChjb25zdHJhaW50Lm5hbWUgYXMgUHJvdmlkZXJOYW1lKVxuICAgICAgOiB1bmRlZmluZWQ7XG4gICAgY29uc3QgcHJvdmlkZXJOYW1lRnJvbUZRUE4gPSBwYXJzZUZRUE4oZnFwbikubmFtZTtcblxuICAgIGlmIChiYXNlTmFtZS5zdGFydHNXaXRoKGAke3Byb3ZpZGVyTmFtZUZyb21GUVBOfV9gKSkge1xuICAgICAgYmFzZU5hbWUgPSBiYXNlTmFtZS5zdWJzdHIocHJvdmlkZXJOYW1lRnJvbUZRUE4ubGVuZ3RoICsgMSk7XG4gICAgfVxuXG4gICAgY29uc3QgcHJvdmlkZXJOYW1lID0gcHJvdmlkZXJOYW1lRnJvbUNvbnN0cmFpbnRcbiAgICAgID8gcHJvdmlkZXJOYW1lRnJvbUNvbnN0cmFpbnRcbiAgICAgIDogcHJvdmlkZXJOYW1lRnJvbUZRUE47XG5cbiAgICBjb25zdCBpc1Byb3ZpZGVyID0gdGVycmFmb3JtU2NoZW1hVHlwZSA9PT0gXCJwcm92aWRlclwiO1xuICAgIGlmIChpc1Byb3ZpZGVyKSB7XG4gICAgICBiYXNlTmFtZSA9IGAke3Byb3ZpZGVyTmFtZX1fJHtiYXNlTmFtZX1gO1xuICAgICAgaWYgKCEoXCJhdHRyaWJ1dGVzXCIgaW4gc2NoZW1hLmJsb2NrKSkge1xuICAgICAgICBzY2hlbWEuYmxvY2sgPSB7XG4gICAgICAgICAgYXR0cmlidXRlczoge30sXG4gICAgICAgICAgYmxvY2tfdHlwZXM6IChzY2hlbWEuYmxvY2sgYXMgQmxvY2spLmJsb2NrX3R5cGVzIHx8IHt9LFxuICAgICAgICB9O1xuICAgICAgfVxuICAgICAgLy8gc29tZWhvdyBtaXNzaW5nIGZyb20gcHJvdmlkZXIgc2NoZW1hXG4gICAgICBzY2hlbWEuYmxvY2suYXR0cmlidXRlc1tcImFsaWFzXCJdID0ge1xuICAgICAgICB0eXBlOiBcInN0cmluZ1wiLFxuICAgICAgICBkZXNjcmlwdGlvbjogXCJBbGlhcyBuYW1lXCIsXG4gICAgICAgIG9wdGlvbmFsOiB0cnVlLFxuICAgICAgICBjb21wdXRlZDogZmFsc2UsXG4gICAgICB9O1xuICAgIH1cblxuICAgIGJhc2VOYW1lID0gc2FuaXRpemVDbGFzc09yTmFtZXNwYWNlTmFtZShiYXNlTmFtZSwgaXNQcm92aWRlcik7XG5cbiAgICBjb25zdCBjbGFzc05hbWUgPSB0aGlzLnVuaXF1ZUNsYXNzTmFtZSh0b1Bhc2NhbENhc2UoYmFzZU5hbWUpKTtcbiAgICAvLyBhdm9pZCBuYW1pbmcgY29sbGlzaW9uIC0gc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9oYXNoaWNvcnAvdGVycmFmb3JtLWNkay9pc3N1ZXMvMjk5XG4gICAgY29uc3QgY29uZmlnU3RydWN0TmFtZSA9IHRoaXMudW5pcXVlQ2xhc3NOYW1lKGAke2NsYXNzTmFtZX1Db25maWdgKTtcbiAgICBjb25zdCBmaWxlTmFtZSA9IGdldEZpbGVOYW1lKHByb3ZpZGVyTmFtZSwgYmFzZU5hbWUpO1xuXG4gICAgY29uc3QgZmlsZVBhdGggPSBgcHJvdmlkZXJzLyR7dG9TbmFrZUNhc2UocHJvdmlkZXJOYW1lKX0vJHtmaWxlTmFtZX1gO1xuICAgIGxldCBhdHRyaWJ1dGVzID0gdGhpcy5yZW5kZXJBdHRyaWJ1dGVzRm9yQmxvY2soXG4gICAgICBuZXcgU2NvcGUoe1xuICAgICAgICBuYW1lOiBiYXNlTmFtZSxcbiAgICAgICAgaXNQcm92aWRlcixcbiAgICAgICAgcGFyZW50OiBpc1Byb3ZpZGVyXG4gICAgICAgICAgPyB1bmRlZmluZWRcbiAgICAgICAgICA6IG5ldyBTY29wZSh7IG5hbWU6IHByb3ZpZGVyTmFtZSwgaXNQcm92aWRlcjogdHJ1ZSB9KSxcbiAgICAgIH0pLFxuICAgICAgc2NoZW1hLmJsb2NrLFxuICAgICk7XG5cbiAgICBmdW5jdGlvbiBnZXRTdHJ1Y3RBdHRyaWJ1dGUoXG4gICAgICBhdHRyaWJ1dGVzOiBBdHRyaWJ1dGVNb2RlbFtdLFxuICAgICAgcGF0aDogc3RyaW5nLFxuICAgICk6IEF0dHJpYnV0ZU1vZGVsIHtcbiAgICAgIGNvbnN0IFtmaXJzdCwgLi4ucmVzdF0gPSBwYXRoLnNwbGl0KFwiLlwiKTtcbiAgICAgIGNvbnN0IGF0dHJpYnV0ZSA9IGF0dHJpYnV0ZXMuZmluZCgoYXR0KSA9PiB7XG4gICAgICAgIHJldHVybiBhdHQudGVycmFmb3JtTmFtZSA9PT0gZmlyc3Q7XG4gICAgICB9KTtcbiAgICAgIGlmICghYXR0cmlidXRlKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYEV4cGVjdGVkIHRvIGZpbmQgcmVjdXJzaXZlIGF0dHJpYnV0ZSBhdCBwYXRoOiAke3BhdGh9YCxcbiAgICAgICAgKTtcbiAgICAgIGlmICghYXR0cmlidXRlLnR5cGUuc3RydWN0KVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYEV4cGVjdGVkIHRvIGZpbmQgc3RydWN0IHR5cGUgYXR0cmlidXRlIGF0IHBhdGg6ICR7cGF0aH0gYnV0IGdvdCAke2F0dHJpYnV0ZS50eXBlLnN0b3JlZENsYXNzVHlwZX1gLFxuICAgICAgICApO1xuICAgICAgaWYgKHJlc3QubGVuZ3RoID09PSAwKSByZXR1cm4gYXR0cmlidXRlO1xuICAgICAgcmV0dXJuIGdldFN0cnVjdEF0dHJpYnV0ZShcbiAgICAgICAgYXR0cmlidXRlLnR5cGUuc3RydWN0LmF0dHJpYnV0ZXMsXG4gICAgICAgIHJlc3Quam9pbihcIi5cIiksXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIEludHJvZHVjZSByZWN1cnNpb24gZm9yIHNvbWUgYXR0cmlidXRlc1xuICAgIGNvbnN0IHJlY3Vyc2l2ZUF0dHJpYnV0ZVBhdGhzID0gZGV0ZWN0QXR0cmlidXRlTG9vcHMoYXR0cmlidXRlcyk7XG5cbiAgICBPYmplY3QuZW50cmllcyhyZWN1cnNpdmVBdHRyaWJ1dGVQYXRocykuZm9yRWFjaChcbiAgICAgIChbYXR0cmlidXRlUGF0aCwgc3RydWN0UGF0aF0pID0+IHtcbiAgICAgICAgLy8gVE9ETzogYnVpbGQgdGhpcyB0byBiZSBhIGJpdCBtb3JlIGRlZmVuc2l2ZSAoZS5nLiByZW1vdmUgISBvcGVyYXRvcilcbiAgICAgICAgY29uc3QgcmVjdXJzaW9uVGFyZ2V0U3RydWN0QXR0cmlidXRlID0gZ2V0U3RydWN0QXR0cmlidXRlKFxuICAgICAgICAgIGF0dHJpYnV0ZXMsXG4gICAgICAgICAgc3RydWN0UGF0aCxcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgcGFydHMgPSBhdHRyaWJ1dGVQYXRoLnNwbGl0KFwiLlwiKTtcbiAgICAgICAgY29uc3QgYXR0cmlidXRlTmFtZSA9IHBhcnRzLnBvcCgpO1xuICAgICAgICBjb25zdCBwYXJlbnRBdHRyaWJ1dGUgPSBnZXRTdHJ1Y3RBdHRyaWJ1dGUoYXR0cmlidXRlcywgcGFydHMuam9pbihcIi5cIikpO1xuICAgICAgICBjb25zdCBpbmRleFRvUmVwbGFjZSA9XG4gICAgICAgICAgcGFyZW50QXR0cmlidXRlLnR5cGUuc3RydWN0IS5hdHRyaWJ1dGVzLmZpbmRJbmRleChcbiAgICAgICAgICAgIChhdHQpID0+IGF0dC50ZXJyYWZvcm1OYW1lID09PSBhdHRyaWJ1dGVOYW1lLFxuICAgICAgICAgICk7XG4gICAgICAgIGlmIChpbmRleFRvUmVwbGFjZSA9PT0gLTEpXG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuJ3QgZmluZCBhdHRyaWJ1dGUgYXQgcGF0aCBcIiArIGF0dHJpYnV0ZVBhdGgpO1xuICAgICAgICBjb25zdCBwcmV2aW91c0F0dHJpYnV0ZSA9XG4gICAgICAgICAgcGFyZW50QXR0cmlidXRlLnR5cGUuc3RydWN0IS5hdHRyaWJ1dGVzW2luZGV4VG9SZXBsYWNlXTtcblxuICAgICAgICBwYXJlbnRBdHRyaWJ1dGUudHlwZS5zdHJ1Y3QhLmF0dHJpYnV0ZXNbaW5kZXhUb1JlcGxhY2VdID1cbiAgICAgICAgICByZWN1cnNpb25UYXJnZXRTdHJ1Y3RBdHRyaWJ1dGU7IC8vIGludHJvZHVjZSByZWN1cnNpb25cblxuICAgICAgICAvLyB1Z2x5LCBwbHMgY8y2Ycy2bMy2bMy2IHJlZmFjdG9yIG1lIG1heWJlXG4gICAgICAgIC8vIHdlIHN0b3JlIGFsbCBzdHJ1Y3RzIGluIHRoaXMuc3RydWN0cyDigJMgbm93IHdlIG5lZWQgdG8gZGlzcG9zZSBhbGwgc3RydWN0cyB0aGF0IGFyZSBwYXJ0IG9mIHByZXZpb3VzQXR0cmlidXRlXG4gICAgICAgIGNvbnN0IGRpc3Bvc2VTdHJ1Y3RzID0gKGF0dHI6IEF0dHJpYnV0ZU1vZGVsKSA9PiB7XG4gICAgICAgICAgaWYgKGF0dHIudHlwZS5zdHJ1Y3QpIHtcbiAgICAgICAgICAgIGF0dHIudHlwZS5zdHJ1Y3QuYXR0cmlidXRlcy5mb3JFYWNoKGRpc3Bvc2VTdHJ1Y3RzKTtcbiAgICAgICAgICAgIHRoaXMuc3RydWN0cyA9IHRoaXMuc3RydWN0cy5maWx0ZXIoKHMpID0+IHMgIT09IGF0dHIudHlwZS5zdHJ1Y3QpO1xuICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBkaXNwb3NlU3RydWN0cyhwcmV2aW91c0F0dHJpYnV0ZSk7XG4gICAgICB9LFxuICAgICk7XG5cbiAgICBhdHRyaWJ1dGVzID0gZGVkdXBsaWNhdGVBdHRyaWJ1dGVzV2l0aFNhbWVOYW1lKGF0dHJpYnV0ZXMpO1xuXG4gICAgY29uc3QgcmVzb3VyY2VNb2RlbCA9IG5ldyBSZXNvdXJjZU1vZGVsKHtcbiAgICAgIHRlcnJhZm9ybVR5cGU6IHR5cGUsXG4gICAgICBiYXNlTmFtZSxcbiAgICAgIGZpbGVOYW1lLFxuICAgICAgZmlsZVBhdGgsXG4gICAgICBjbGFzc05hbWUsXG4gICAgICBzY2hlbWEsXG4gICAgICBmcXBuLFxuICAgICAgYXR0cmlidXRlcyxcbiAgICAgIHRlcnJhZm9ybVNjaGVtYVR5cGUsXG4gICAgICBzdHJ1Y3RzOiB0aGlzLnN0cnVjdHMsXG4gICAgICBjb25maWdTdHJ1Y3ROYW1lLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHJlc291cmNlTW9kZWw7XG4gIH1cblxuICBwcml2YXRlIHJlbmRlckF0dHJpYnV0ZVR5cGUoXG4gICAgc2NvcGU6IFNjb3BlW10sXG4gICAgYXR0cmlidXRlVHlwZTogQXR0cmlidXRlVHlwZSB8IEF0dHJpYnV0ZU5lc3RlZFR5cGUsXG4gICAgcGFyZW50S2luZD86IHN0cmluZyxcbiAgKTogQXR0cmlidXRlVHlwZU1vZGVsIHtcbiAgICBjb25zdCBwYXJlbnQgPSBzY29wZVtzY29wZS5sZW5ndGggLSAxXTtcbiAgICBpZiAoc2hvdWxkU2tpcEF0dHJpYnV0ZShwYXJlbnQuYmFzZU5hbWUpKSB7XG4gICAgICByZXR1cm4gbmV3IE1hcEF0dHJpYnV0ZVR5cGVNb2RlbChuZXcgU2ltcGxlQXR0cmlidXRlVHlwZU1vZGVsKFwiYW55XCIpKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGF0dHJpYnV0ZVR5cGUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgIHN3aXRjaCAoYXR0cmlidXRlVHlwZSkge1xuICAgICAgICBjYXNlIFwiYm9vbFwiOlxuICAgICAgICAgIHJldHVybiBuZXcgU2ltcGxlQXR0cmlidXRlVHlwZU1vZGVsKFwiYm9vbGVhblwiKTtcbiAgICAgICAgY2FzZSBcInN0cmluZ1wiOlxuICAgICAgICAgIHJldHVybiBuZXcgU2ltcGxlQXR0cmlidXRlVHlwZU1vZGVsKFwic3RyaW5nXCIpO1xuICAgICAgICBjYXNlIFwibnVtYmVyXCI6XG4gICAgICAgICAgcmV0dXJuIG5ldyBTaW1wbGVBdHRyaWJ1dGVUeXBlTW9kZWwoXCJudW1iZXJcIik7XG4gICAgICAgIGNhc2UgXCJkeW5hbWljXCI6XG4gICAgICAgICAgcmV0dXJuIG5ldyBNYXBBdHRyaWJ1dGVUeXBlTW9kZWwobmV3IFNpbXBsZUF0dHJpYnV0ZVR5cGVNb2RlbChcImFueVwiKSk7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbnZhbGlkIHByaW1pdGl2ZSB0eXBlICR7YXR0cmlidXRlVHlwZX1gKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoQXJyYXkuaXNBcnJheShhdHRyaWJ1dGVUeXBlKSkge1xuICAgICAgaWYgKGF0dHJpYnV0ZVR5cGUubGVuZ3RoICE9PSAyKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgdW5leHBlY3RlZCBhcnJheWApO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBba2luZCwgdHlwZV0gPSBhdHRyaWJ1dGVUeXBlO1xuXG4gICAgICBpZiAoa2luZCA9PT0gXCJzZXRcIiB8fCBraW5kID09PSBcImxpc3RcIikge1xuICAgICAgICBjb25zdCBlbGVtZW50VHlwZSA9IHRoaXMucmVuZGVyQXR0cmlidXRlVHlwZShcbiAgICAgICAgICBzY29wZSxcbiAgICAgICAgICB0eXBlIGFzIEF0dHJpYnV0ZVR5cGUsXG4gICAgICAgICAgW2tpbmQsIHBhcmVudEtpbmRdLmpvaW4oXCJcIiksXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBraW5kID09PSBcImxpc3RcIlxuICAgICAgICAgID8gbmV3IExpc3RBdHRyaWJ1dGVUeXBlTW9kZWwoZWxlbWVudFR5cGUsIGZhbHNlLCBmYWxzZSlcbiAgICAgICAgICA6IG5ldyBTZXRBdHRyaWJ1dGVUeXBlTW9kZWwoZWxlbWVudFR5cGUsIGZhbHNlLCBmYWxzZSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChraW5kID09PSBcIm1hcFwiKSB7XG4gICAgICAgIGNvbnN0IHZhbHVlVHlwZSA9IHRoaXMucmVuZGVyQXR0cmlidXRlVHlwZShcbiAgICAgICAgICBzY29wZSxcbiAgICAgICAgICB0eXBlIGFzIEF0dHJpYnV0ZVR5cGUsXG4gICAgICAgICAgW2tpbmQsIHBhcmVudEtpbmRdLmpvaW4oXCJcIiksXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBuZXcgTWFwQXR0cmlidXRlVHlwZU1vZGVsKHZhbHVlVHlwZSk7XG4gICAgICB9XG5cbiAgICAgIGlmIChraW5kID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIGNvbnN0IG9iakF0dHJpYnV0ZXMgPSB0eXBlIGFzIHsgW25hbWU6IHN0cmluZ106IEF0dHJpYnV0ZVR5cGUgfTtcbiAgICAgICAgY29uc3QgYXR0cmlidXRlczogeyBbbmFtZTogc3RyaW5nXTogQXR0cmlidXRlIH0gPSB7fTtcbiAgICAgICAgZm9yIChjb25zdCBbbmFtZSwgdHlwZV0gb2YgT2JqZWN0LmVudHJpZXMob2JqQXR0cmlidXRlcykpIHtcbiAgICAgICAgICBhdHRyaWJ1dGVzW25hbWVdID0geyB0eXBlIH07XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgc3RydWN0ID0gdGhpcy5hZGRBbm9ueW1vdXNTdHJ1Y3QoXG4gICAgICAgICAgc2NvcGUsXG4gICAgICAgICAgYXR0cmlidXRlcyxcbiAgICAgICAgICBwYXJlbnRLaW5kID8/IGtpbmQsXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybiBuZXcgU3RydWN0QXR0cmlidXRlVHlwZU1vZGVsKHN0cnVjdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGlzQXR0cmlidXRlTmVzdGVkVHlwZShhdHRyaWJ1dGVUeXBlKSkge1xuICAgICAgbGV0IHN0cnVjdCA9IHVuZGVmaW5lZDtcbiAgICAgIGxldCB0eXBlTW9kZWwgPSB1bmRlZmluZWQ7XG4gICAgICBzd2l0Y2ggKGF0dHJpYnV0ZVR5cGUubmVzdGluZ19tb2RlKSB7XG4gICAgICAgIGNhc2UgXCJsaXN0XCI6XG4gICAgICAgICAgc3RydWN0ID0gdGhpcy5hZGRBbm9ueW1vdXNTdHJ1Y3QoXG4gICAgICAgICAgICBzY29wZSxcbiAgICAgICAgICAgIGF0dHJpYnV0ZVR5cGUuYXR0cmlidXRlcyxcbiAgICAgICAgICAgIGF0dHJpYnV0ZVR5cGUubmVzdGluZ19tb2RlLFxuICAgICAgICAgICk7XG4gICAgICAgICAgdHlwZU1vZGVsID0gbmV3IExpc3RBdHRyaWJ1dGVUeXBlTW9kZWwoXG4gICAgICAgICAgICBuZXcgU3RydWN0QXR0cmlidXRlVHlwZU1vZGVsKHN0cnVjdCksXG4gICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgXCJzZXRcIjpcbiAgICAgICAgICBzdHJ1Y3QgPSB0aGlzLmFkZEFub255bW91c1N0cnVjdChcbiAgICAgICAgICAgIHNjb3BlLFxuICAgICAgICAgICAgYXR0cmlidXRlVHlwZS5hdHRyaWJ1dGVzLFxuICAgICAgICAgICAgYXR0cmlidXRlVHlwZS5uZXN0aW5nX21vZGUsXG4gICAgICAgICAgKTtcbiAgICAgICAgICB0eXBlTW9kZWwgPSBuZXcgU2V0QXR0cmlidXRlVHlwZU1vZGVsKFxuICAgICAgICAgICAgbmV3IFN0cnVjdEF0dHJpYnV0ZVR5cGVNb2RlbChzdHJ1Y3QpLFxuICAgICAgICAgICAgZmFsc2UsXG4gICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICApO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFwibWFwXCI6XG4gICAgICAgICAgc3RydWN0ID0gdGhpcy5hZGRBbm9ueW1vdXNTdHJ1Y3QoXG4gICAgICAgICAgICBzY29wZSxcbiAgICAgICAgICAgIGF0dHJpYnV0ZVR5cGUuYXR0cmlidXRlcyxcbiAgICAgICAgICAgIGF0dHJpYnV0ZVR5cGUubmVzdGluZ19tb2RlLFxuICAgICAgICAgICk7XG4gICAgICAgICAgdHlwZU1vZGVsID0gbmV3IE1hcEF0dHJpYnV0ZVR5cGVNb2RlbChcbiAgICAgICAgICAgIG5ldyBTdHJ1Y3RBdHRyaWJ1dGVUeXBlTW9kZWwoc3RydWN0KSxcbiAgICAgICAgICApO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFwic2luZ2xlXCI6XG4gICAgICAgICAgc3RydWN0ID0gdGhpcy5hZGRBbm9ueW1vdXNTdHJ1Y3QoXG4gICAgICAgICAgICBzY29wZSxcbiAgICAgICAgICAgIGF0dHJpYnV0ZVR5cGUuYXR0cmlidXRlcyxcbiAgICAgICAgICAgIGF0dHJpYnV0ZVR5cGUubmVzdGluZ19tb2RlLFxuICAgICAgICAgICk7XG4gICAgICAgICAgdHlwZU1vZGVsID0gbmV3IFN0cnVjdEF0dHJpYnV0ZVR5cGVNb2RlbChzdHJ1Y3QpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OiB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYG5lc3RlZF90eXBlIHdpdGggbmVzdGluZ19tb2RlIFwiJHtcbiAgICAgICAgICAgICAgYXR0cmlidXRlVHlwZS5uZXN0aW5nX21vZGVcbiAgICAgICAgICAgIH1cIiBub3Qgc3VwcG9ydGVkIChhdHRyaWJ1dGUgc2NvcGU6ICR7c2NvcGVcbiAgICAgICAgICAgICAgLm1hcCgocykgPT4gcy5mdWxsTmFtZSlcbiAgICAgICAgICAgICAgLmpvaW4oXCIsXCIpfWAsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHR5cGVNb2RlbDtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoYHVua25vd24gdHlwZSAke0pTT04uc3RyaW5naWZ5KGF0dHJpYnV0ZVR5cGUpfWApO1xuICB9XG5cbiAgcHVibGljIHJlbmRlckF0dHJpYnV0ZXNGb3JCbG9jayhwYXJlbnRUeXBlOiBTY29wZSwgYmxvY2s6IEJsb2NrKSB7XG4gICAgY29uc3QgYXR0cmlidXRlcyA9IG5ldyBBcnJheTxBdHRyaWJ1dGVNb2RlbD4oKTtcblxuICAgIGZvciAoY29uc3QgW3RlcnJhZm9ybUF0dHJpYnV0ZU5hbWUsIGF0dF0gb2YgT2JqZWN0LmVudHJpZXMoXG4gICAgICBibG9jay5hdHRyaWJ1dGVzIHx8IHt9LFxuICAgICkpIHtcbiAgICAgIGxldCB0eXBlOiBBdHRyaWJ1dGVUeXBlTW9kZWw7XG4gICAgICBsZXQgZm9yY2VQbGFpbkdldHRlclR5cGUgPSBmYWxzZTtcbiAgICAgIGlmIChzaG91bGRTa2lwQXR0cmlidXRlKHBhcmVudFR5cGUuZnVsbE5hbWUodGVycmFmb3JtQXR0cmlidXRlTmFtZSkpKSB7XG4gICAgICAgIHR5cGUgPSBuZXcgU2tpcHBlZEF0dHJpYnV0ZVR5cGVNb2RlbCgpO1xuICAgICAgICBmb3JjZVBsYWluR2V0dGVyVHlwZSA9IHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0eXBlID0gdGhpcy5yZW5kZXJBdHRyaWJ1dGVUeXBlKFxuICAgICAgICAgIFtcbiAgICAgICAgICAgIHBhcmVudFR5cGUsXG4gICAgICAgICAgICBuZXcgU2NvcGUoe1xuICAgICAgICAgICAgICBuYW1lOiB0ZXJyYWZvcm1BdHRyaWJ1dGVOYW1lLFxuICAgICAgICAgICAgICBwYXJlbnQ6IHBhcmVudFR5cGUsXG4gICAgICAgICAgICAgIGlzUHJvdmlkZXI6IHBhcmVudFR5cGUuaXNQcm92aWRlcixcbiAgICAgICAgICAgICAgaXNDb21wdXRlZDogISFhdHQuY29tcHV0ZWQsXG4gICAgICAgICAgICAgIGlzT3B0aW9uYWw6ICEhYXR0Lm9wdGlvbmFsLFxuICAgICAgICAgICAgICBpc1JlcXVpcmVkOiAhIWF0dC5yZXF1aXJlZCxcbiAgICAgICAgICAgICAgaXNOZXN0ZWRUeXBlOiBpc05lc3RlZFR5cGVBdHRyaWJ1dGUoYXR0KSxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgIF0sXG4gICAgICAgICAgYXR0LnR5cGUgfHwgYXR0Lm5lc3RlZF90eXBlLFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBuYW1lID0gdG9DYW1lbENhc2UodGVycmFmb3JtQXR0cmlidXRlTmFtZSk7XG5cbiAgICAgIGF0dHJpYnV0ZXMucHVzaChcbiAgICAgICAgbmV3IEF0dHJpYnV0ZU1vZGVsKHtcbiAgICAgICAgICB0ZXJyYWZvcm1GdWxsTmFtZTogcGFyZW50VHlwZS5mdWxsTmFtZSh0ZXJyYWZvcm1BdHRyaWJ1dGVOYW1lKSxcbiAgICAgICAgICBkZXNjcmlwdGlvbjogYXR0LmRlc2NyaXB0aW9uLFxuICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgc3RvcmFnZU5hbWU6IGBfJHtuYW1lfWAsXG4gICAgICAgICAgY29tcHV0ZWQ6ICEhYXR0LmNvbXB1dGVkLFxuICAgICAgICAgIG9wdGlvbmFsOiAhIWF0dC5vcHRpb25hbCxcbiAgICAgICAgICB0ZXJyYWZvcm1OYW1lOiB0ZXJyYWZvcm1BdHRyaWJ1dGVOYW1lLFxuICAgICAgICAgIHR5cGUsXG4gICAgICAgICAgcHJvdmlkZXI6IHBhcmVudFR5cGUuaXNQcm92aWRlcixcbiAgICAgICAgICByZXF1aXJlZDogISFhdHQucmVxdWlyZWQsXG4gICAgICAgICAgZm9yY2VQbGFpbkdldHRlclR5cGUsXG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IFtibG9ja1R5cGVOYW1lLCBibG9ja1R5cGVdIG9mIE9iamVjdC5lbnRyaWVzKFxuICAgICAgYmxvY2suYmxvY2tfdHlwZXMgfHwge30sXG4gICAgKSkge1xuICAgICAgaWYgKHNob3VsZFNraXBBdHRyaWJ1dGUocGFyZW50VHlwZS5mdWxsTmFtZShibG9ja1R5cGVOYW1lKSkpIHtcbiAgICAgICAgY29uc3QgbmFtZSA9IHRvQ2FtZWxDYXNlKGJsb2NrVHlwZU5hbWUpO1xuICAgICAgICBjb25zdCBwYXJlbnQgPSBuZXcgU2NvcGUoe1xuICAgICAgICAgIG5hbWU6IGJsb2NrVHlwZU5hbWUsXG4gICAgICAgICAgcGFyZW50OiBwYXJlbnRUeXBlLFxuICAgICAgICAgIGlzUHJvdmlkZXI6IHBhcmVudFR5cGUuaXNQcm92aWRlcixcbiAgICAgICAgfSk7XG4gICAgICAgIGF0dHJpYnV0ZXMucHVzaChcbiAgICAgICAgICBuZXcgQXR0cmlidXRlTW9kZWwoe1xuICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgIHRlcnJhZm9ybU5hbWU6IGJsb2NrVHlwZU5hbWUsXG4gICAgICAgICAgICB0ZXJyYWZvcm1GdWxsTmFtZTogcGFyZW50LmZ1bGxOYW1lKGJsb2NrVHlwZU5hbWUpLFxuICAgICAgICAgICAgdHlwZTogbmV3IFNraXBwZWRBdHRyaWJ1dGVUeXBlTW9kZWwoKSxcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOiBgJHtibG9ja1R5cGVOYW1lfSBibG9ja2AsXG4gICAgICAgICAgICBzdG9yYWdlTmFtZTogYF8ke25hbWV9YCxcbiAgICAgICAgICAgIG9wdGlvbmFsOiB0cnVlLFxuICAgICAgICAgICAgY29tcHV0ZWQ6IGZhbHNlLFxuICAgICAgICAgICAgcHJvdmlkZXI6IHBhcmVudFR5cGUuaXNQcm92aWRlcixcbiAgICAgICAgICAgIHJlcXVpcmVkOiBmYWxzZSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICAvLyBjcmVhdGUgYSBzdHJ1Y3QgZm9yIHRoaXMgYmxvY2tcbiAgICAgIGxldCBibG9ja0F0dHJpYnV0ZXMgPSB0aGlzLnJlbmRlckF0dHJpYnV0ZXNGb3JCbG9jayhcbiAgICAgICAgbmV3IFNjb3BlKHtcbiAgICAgICAgICBuYW1lOiBgJHtwYXJlbnRUeXBlLm5hbWV9XyR7YmxvY2tUeXBlTmFtZX1gLFxuICAgICAgICAgIHBhcmVudDogcGFyZW50VHlwZSxcbiAgICAgICAgICBpc1Byb3ZpZGVyOiBwYXJlbnRUeXBlLmlzUHJvdmlkZXIsXG4gICAgICAgICAgaW5CbG9ja1R5cGU6IHRydWUsXG4gICAgICAgIH0pLFxuICAgICAgICBibG9ja1R5cGUuYmxvY2ssXG4gICAgICApO1xuXG4gICAgICBibG9ja0F0dHJpYnV0ZXMgPSBkZWR1cGxpY2F0ZUF0dHJpYnV0ZXNXaXRoU2FtZU5hbWUoYmxvY2tBdHRyaWJ1dGVzKTtcblxuICAgICAgY29uc3QgYmxvY2tTdHJ1Y3QgPSB0aGlzLmFkZFN0cnVjdChcbiAgICAgICAgW1xuICAgICAgICAgIHBhcmVudFR5cGUsXG4gICAgICAgICAgbmV3IFNjb3BlKHtcbiAgICAgICAgICAgIG5hbWU6IGJsb2NrVHlwZU5hbWUsXG4gICAgICAgICAgICBwYXJlbnQ6IHBhcmVudFR5cGUsXG4gICAgICAgICAgICBpc1Byb3ZpZGVyOiBwYXJlbnRUeXBlLmlzUHJvdmlkZXIsXG4gICAgICAgICAgfSksXG4gICAgICAgIF0sXG4gICAgICAgIGJsb2NrQXR0cmlidXRlcyxcbiAgICAgICAgYmxvY2tUeXBlLm5lc3RpbmdfbW9kZSxcbiAgICAgICAgKGJsb2NrVHlwZS5uZXN0aW5nX21vZGUgPT09IFwibGlzdFwiIHx8XG4gICAgICAgICAgYmxvY2tUeXBlLm5lc3RpbmdfbW9kZSA9PT0gXCJzZXRcIikgJiZcbiAgICAgICAgICBibG9ja1R5cGUubWF4X2l0ZW1zID09PSAxLFxuICAgICAgKTtcblxuICAgICAgLy8gZGVmaW5lIHRoZSBhdHRyaWJ1dGVcbiAgICAgIGF0dHJpYnV0ZXMucHVzaChcbiAgICAgICAgYXR0cmlidXRlRm9yQmxvY2tUeXBlKFxuICAgICAgICAgIGJsb2NrVHlwZU5hbWUsXG4gICAgICAgICAgYmxvY2tUeXBlLFxuICAgICAgICAgIGJsb2NrU3RydWN0LFxuICAgICAgICAgIHBhcmVudFR5cGUuaXNQcm92aWRlcixcbiAgICAgICAgICBwYXJlbnRUeXBlLFxuICAgICAgICApLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXR0cmlidXRlcztcblxuICAgIGZ1bmN0aW9uIGF0dHJpYnV0ZUZvckJsb2NrVHlwZShcbiAgICAgIHRlcnJhZm9ybU5hbWU6IHN0cmluZyxcbiAgICAgIGJsb2NrVHlwZTogQmxvY2tUeXBlLFxuICAgICAgc3RydWN0OiBTdHJ1Y3QsXG4gICAgICBpc1Byb3ZpZGVyOiBib29sZWFuLFxuICAgICAgcGFyZW50OiBTY29wZSxcbiAgICApOiBBdHRyaWJ1dGVNb2RlbCB7XG4gICAgICBjb25zdCBuYW1lID0gdG9DYW1lbENhc2UodGVycmFmb3JtTmFtZSk7XG4gICAgICBsZXQgb3B0aW9uYWw6IGJvb2xlYW47XG4gICAgICBsZXQgcmVxdWlyZWQ6IGJvb2xlYW47XG5cbiAgICAgIHN3aXRjaCAoYmxvY2tUeXBlLm5lc3RpbmdfbW9kZSkge1xuICAgICAgICBjYXNlIFwic2luZ2xlXCI6XG4gICAgICAgICAgb3B0aW9uYWwgPSAhc3RydWN0LmF0dHJpYnV0ZXMuc29tZSgoeCkgPT4gIXgub3B0aW9uYWwpO1xuICAgICAgICAgIHJlcXVpcmVkID0gIXN0cnVjdC5hdHRyaWJ1dGVzLnNvbWUoKHgpID0+ICF4LnJlcXVpcmVkKTtcblxuICAgICAgICAgIC8vIFRoaXMgaXMgZm9yIGJ1ZyAjMzU3MCBhcyBib3RoIG9wdGlvbmFsIGFuZCByZXF1aXJlZCBldmFsdWF0ZSB0byBmYWxzZSB1bmRlciBzb21lIGNpcmN1bXN0YW5jZXNcbiAgICAgICAgICAvLyAodGhpcyB0aGVuIGNhdXNlcyB0aGUgY29tcHV0ZWQgYmxvY2sgdG8gbm90IGJlIHBhcnQgb2YgYXNzaWduYWJsZUF0dHJpYnV0ZXMgYW5kIHRodXMgc2tpcHBlZCBpbiB0aGUgZ2VuZXJhdGVkIGNvZGUpXG4gICAgICAgICAgLy8gSGVuY2U6IElmIGJvdGggb3B0aW9uYWwgYW5kIHJlcXVpcmVkIGFyZSBmYWxzZSwgc2V0IG9wdGlvbmFsIHRvIHRydWUgSUYgYXQgbGVhc3Qgb25lXG4gICAgICAgICAgLy8gYXR0cmlidXRlIGluIHRoZSBibG9jayBoYXMgb3B0aW9uYWwgPSB0cnVlIG9yIHJlcXVpcmVkID0gdHJ1ZSwgYXMgdGhpcyB3b3VsZCBtZWFuIHRoYXQgYXQgbGVhc3Qgc29tZXRoaW5nIGNhbiBiZSBzZXRcbiAgICAgICAgICAvLyBhbmQgdGhlIGJsb2NrIGlzIG5vdCBhbGwgY29tcHV0ZWQuXG4gICAgICAgICAgaWYgKCFvcHRpb25hbCAmJiAhcmVxdWlyZWQpIHtcbiAgICAgICAgICAgIG9wdGlvbmFsID0gc3RydWN0LmF0dHJpYnV0ZXMuc29tZSgoeCkgPT4geC5vcHRpb25hbCB8fCB4LnJlcXVpcmVkKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gbmV3IEF0dHJpYnV0ZU1vZGVsKHtcbiAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICB0ZXJyYWZvcm1OYW1lLFxuICAgICAgICAgICAgdGVycmFmb3JtRnVsbE5hbWU6IHBhcmVudC5mdWxsTmFtZSh0ZXJyYWZvcm1OYW1lKSxcbiAgICAgICAgICAgIHR5cGU6IG5ldyBTdHJ1Y3RBdHRyaWJ1dGVUeXBlTW9kZWwoc3RydWN0KSxcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOiBgJHt0ZXJyYWZvcm1OYW1lfSBibG9ja2AsXG4gICAgICAgICAgICBzdG9yYWdlTmFtZTogYF8ke25hbWV9YCxcbiAgICAgICAgICAgIG9wdGlvbmFsLFxuICAgICAgICAgICAgY29tcHV0ZWQ6IGZhbHNlLFxuICAgICAgICAgICAgcHJvdmlkZXI6IGlzUHJvdmlkZXIsXG4gICAgICAgICAgICByZXF1aXJlZCxcbiAgICAgICAgICB9KTtcblxuICAgICAgICBjYXNlIFwibWFwXCI6XG4gICAgICAgICAgcmV0dXJuIG5ldyBBdHRyaWJ1dGVNb2RlbCh7XG4gICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgdGVycmFmb3JtTmFtZSxcbiAgICAgICAgICAgIHRlcnJhZm9ybUZ1bGxOYW1lOiBwYXJlbnQuZnVsbE5hbWUodGVycmFmb3JtTmFtZSksXG4gICAgICAgICAgICB0eXBlOiBuZXcgTWFwQXR0cmlidXRlVHlwZU1vZGVsKFxuICAgICAgICAgICAgICBuZXcgU3RydWN0QXR0cmlidXRlVHlwZU1vZGVsKHN0cnVjdCksXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IGAke3RlcnJhZm9ybU5hbWV9IGJsb2NrYCxcbiAgICAgICAgICAgIHN0b3JhZ2VOYW1lOiBgXyR7bmFtZX1gLFxuICAgICAgICAgICAgb3B0aW9uYWw6IGZhbHNlLFxuICAgICAgICAgICAgY29tcHV0ZWQ6IGZhbHNlLFxuICAgICAgICAgICAgcHJvdmlkZXI6IGlzUHJvdmlkZXIsXG4gICAgICAgICAgICByZXF1aXJlZDogZmFsc2UsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgY2FzZSBcImxpc3RcIjpcbiAgICAgICAgY2FzZSBcInNldFwiOlxuICAgICAgICAgIG9wdGlvbmFsID1cbiAgICAgICAgICAgIGJsb2NrVHlwZS5taW5faXRlbXMgPT09IHVuZGVmaW5lZCA/IHRydWUgOiBibG9ja1R5cGUubWluX2l0ZW1zIDwgMTtcbiAgICAgICAgICByZXF1aXJlZCA9XG4gICAgICAgICAgICBibG9ja1R5cGUubWluX2l0ZW1zID09PSB1bmRlZmluZWQgPyBmYWxzZSA6IGJsb2NrVHlwZS5taW5faXRlbXMgPiAwO1xuICAgICAgICAgIHJldHVybiBuZXcgQXR0cmlidXRlTW9kZWwoe1xuICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgIHRlcnJhZm9ybU5hbWU6IHRlcnJhZm9ybU5hbWUsXG4gICAgICAgICAgICB0ZXJyYWZvcm1GdWxsTmFtZTogcGFyZW50LmZ1bGxOYW1lKHRlcnJhZm9ybU5hbWUpLFxuICAgICAgICAgICAgdHlwZTpcbiAgICAgICAgICAgICAgYmxvY2tUeXBlLm5lc3RpbmdfbW9kZSA9PT0gXCJsaXN0XCJcbiAgICAgICAgICAgICAgICA/IG5ldyBMaXN0QXR0cmlidXRlVHlwZU1vZGVsKFxuICAgICAgICAgICAgICAgICAgICBuZXcgU3RydWN0QXR0cmlidXRlVHlwZU1vZGVsKHN0cnVjdCksXG4gICAgICAgICAgICAgICAgICAgIGJsb2NrVHlwZS5tYXhfaXRlbXMgPT09IDEsXG4gICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgOiBuZXcgU2V0QXR0cmlidXRlVHlwZU1vZGVsKFxuICAgICAgICAgICAgICAgICAgICBuZXcgU3RydWN0QXR0cmlidXRlVHlwZU1vZGVsKHN0cnVjdCksXG4gICAgICAgICAgICAgICAgICAgIGJsb2NrVHlwZS5tYXhfaXRlbXMgPT09IDEsXG4gICAgICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IGAke3RlcnJhZm9ybU5hbWV9IGJsb2NrYCxcbiAgICAgICAgICAgIHN0b3JhZ2VOYW1lOiBgXyR7bmFtZX1gLFxuICAgICAgICAgICAgb3B0aW9uYWwsXG4gICAgICAgICAgICBjb21wdXRlZDogZmFsc2UsXG4gICAgICAgICAgICBwcm92aWRlcjogaXNQcm92aWRlcixcbiAgICAgICAgICAgIHJlcXVpcmVkLFxuICAgICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICBwcml2YXRlIGFkZEFub255bW91c1N0cnVjdChcbiAgICBzY29wZTogU2NvcGVbXSxcbiAgICBhdHRyczogeyBbbmFtZTogc3RyaW5nXTogQXR0cmlidXRlIH0gfCB1bmRlZmluZWQsXG4gICAgbmVzdGluZ19tb2RlOiBzdHJpbmcsXG4gICkge1xuICAgIGxldCBhdHRyaWJ1dGVzID0gbmV3IEFycmF5PEF0dHJpYnV0ZU1vZGVsPigpO1xuICAgIGNvbnN0IHBhcmVudCA9IHNjb3BlW3Njb3BlLmxlbmd0aCAtIDFdO1xuICAgIGlmIChhdHRycykge1xuICAgICAgZm9yIChjb25zdCBbdGVycmFmb3JtTmFtZSwgYXR0XSBvZiBPYmplY3QuZW50cmllcyhhdHRycyB8fCB7fSkpIHtcbiAgICAgICAgLy8gbmVzdGVkIHR5cGVzIHN1cHBvcnQgY29tcHV0ZWQsIG9wdGlvbmFsIGFuZCByZXF1aXJlZCBvbiBhdHRyaWJ1dGUgbGV2ZWxcbiAgICAgICAgLy8gaWYgcGFyZW50IGlzIGNvbXB1dGVkLCBjaGlsZCBhbHdheXMgaXMgY29tcHV0ZWQgYXMgd2VsbFxuICAgICAgICBjb25zdCBjb21wdXRlZCA9XG4gICAgICAgICAgISFwYXJlbnQuaXNDb21wdXRlZCB8fCAocGFyZW50LmlzTmVzdGVkVHlwZSAmJiAhIWF0dC5jb21wdXRlZCk7XG4gICAgICAgIGNvbnN0IG9wdGlvbmFsID0gcGFyZW50LmlzTmVzdGVkVHlwZVxuICAgICAgICAgID8gISFhdHQub3B0aW9uYWxcbiAgICAgICAgICA6ICEhcGFyZW50LmlzT3B0aW9uYWw7XG4gICAgICAgIGNvbnN0IHJlcXVpcmVkID0gcGFyZW50LmlzTmVzdGVkVHlwZVxuICAgICAgICAgID8gISFhdHQucmVxdWlyZWRcbiAgICAgICAgICA6ICEhcGFyZW50LmlzUmVxdWlyZWQ7XG4gICAgICAgIGNvbnN0IG5hbWUgPSB0b0NhbWVsQ2FzZSh0ZXJyYWZvcm1OYW1lKTtcbiAgICAgICAgY29uc3QgdHlwZSA9IHRoaXMucmVuZGVyQXR0cmlidXRlVHlwZShcbiAgICAgICAgICBbXG4gICAgICAgICAgICAuLi5zY29wZSxcbiAgICAgICAgICAgIG5ldyBTY29wZSh7XG4gICAgICAgICAgICAgIG5hbWU6IHRlcnJhZm9ybU5hbWUsXG4gICAgICAgICAgICAgIHBhcmVudCxcbiAgICAgICAgICAgICAgaXNQcm92aWRlcjogcGFyZW50LmlzUHJvdmlkZXIsXG4gICAgICAgICAgICAgIGlzQ29tcHV0ZWQ6IGNvbXB1dGVkLFxuICAgICAgICAgICAgICBpc09wdGlvbmFsOiBvcHRpb25hbCxcbiAgICAgICAgICAgICAgaXNSZXF1aXJlZDogcmVxdWlyZWQsXG4gICAgICAgICAgICAgIGlzTmVzdGVkVHlwZTogcGFyZW50LmlzTmVzdGVkVHlwZSxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgIF0sXG4gICAgICAgICAgYXR0LnR5cGUgfHwgYXR0Lm5lc3RlZF90eXBlLFxuICAgICAgICApO1xuICAgICAgICBhdHRyaWJ1dGVzLnB1c2goXG4gICAgICAgICAgbmV3IEF0dHJpYnV0ZU1vZGVsKHtcbiAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICBzdG9yYWdlTmFtZTogYF8ke25hbWV9YCxcbiAgICAgICAgICAgIGNvbXB1dGVkOiBjb21wdXRlZCxcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOiBhdHQuZGVzY3JpcHRpb24sXG4gICAgICAgICAgICBvcHRpb25hbDogb3B0aW9uYWwsXG4gICAgICAgICAgICB0ZXJyYWZvcm1OYW1lLFxuICAgICAgICAgICAgdGVycmFmb3JtRnVsbE5hbWU6IHBhcmVudC5mdWxsTmFtZSh0ZXJyYWZvcm1OYW1lKSxcbiAgICAgICAgICAgIHR5cGUsXG4gICAgICAgICAgICBwcm92aWRlcjogcGFyZW50LmlzUHJvdmlkZXIsXG4gICAgICAgICAgICByZXF1aXJlZDogcmVxdWlyZWQsXG4gICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgYXR0cmlidXRlcyA9IGRlZHVwbGljYXRlQXR0cmlidXRlc1dpdGhTYW1lTmFtZShhdHRyaWJ1dGVzKTtcblxuICAgIHJldHVybiB0aGlzLmFkZFN0cnVjdChzY29wZSwgYXR0cmlidXRlcywgbmVzdGluZ19tb2RlKTtcbiAgfVxuXG4gIHByaXZhdGUgYWRkU3RydWN0KFxuICAgIHNjb3BlOiBTY29wZVtdLFxuICAgIGF0dHJpYnV0ZXM6IEF0dHJpYnV0ZU1vZGVsW10sXG4gICAgbmVzdGluZ19tb2RlOiBzdHJpbmcsXG4gICAgaXNTaW5nbGVJdGVtID0gZmFsc2UsXG4gICkge1xuICAgIGNvbnN0IHBvc3NpYmxlTmFtZSA9IHRvUGFzY2FsQ2FzZShcbiAgICAgIHNjb3BlLm1hcCgoeCkgPT4gdG9TbmFrZUNhc2UoeC5uYW1lKSkuam9pbihcIl9cIiksXG4gICAgKTtcbiAgICBjb25zdCBuYW1lID0gdGhpcy51bmlxdWVDbGFzc05hbWUoXG4gICAgICBpc1Jlc2VydmVkU3RydWN0Q2xhc3NOYW1lKHBvc3NpYmxlTmFtZSlcbiAgICAgICAgPyBgJHtwb3NzaWJsZU5hbWV9U3RydWN0YFxuICAgICAgICA6IHBvc3NpYmxlTmFtZSxcbiAgICApO1xuXG4gICAgY29uc3QgcGFyZW50ID0gc2NvcGVbc2NvcGUubGVuZ3RoIC0gMV07XG4gICAgLy8gYmxvY2tUeXBlLm5lc3RpbmdfbW9kZSA9PiBsaXN0L3NldCAmIGJsb2NrVHlwZS5tYXhfaXRlbXMgPT09IDEsXG4gICAgY29uc3QgaXNDbGFzcyA9IChwYXJlbnQuaXNDb21wdXRlZCAmJiAhcGFyZW50LmlzT3B0aW9uYWwpIHx8IGlzU2luZ2xlSXRlbTtcbiAgICBjb25zdCBpc0Fub255bW91cyA9IHRydWU7XG4gICAgY29uc3QgcyA9IG5ldyBTdHJ1Y3QoXG4gICAgICBuYW1lLFxuICAgICAgYXR0cmlidXRlcyxcbiAgICAgIGlzQ2xhc3MsXG4gICAgICBpc0Fub255bW91cyxcbiAgICAgIGlzU2luZ2xlSXRlbSxcbiAgICAgIG5lc3RpbmdfbW9kZSxcbiAgICApO1xuICAgIHRoaXMuc3RydWN0cy5wdXNoKHMpO1xuICAgIHJldHVybiBzO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBSZXNvdXJjZVBhcnNlciB7XG4gIHByaXZhdGUgdW5pcXVlQ2xhc3NuYW1lczogc3RyaW5nW10gPSBbXTtcbiAgcHJpdmF0ZSByZXNvdXJjZXM6IFJlY29yZDxzdHJpbmcsIFJlc291cmNlTW9kZWw+ID0ge307XG5cbiAgcHVibGljIHBhcnNlKFxuICAgIGZxcG46IEZRUE4sXG4gICAgdHlwZTogc3RyaW5nLFxuICAgIHNjaGVtYTogU2NoZW1hLFxuICAgIHRlcnJhZm9ybVR5cGU6IHN0cmluZyxcbiAgICBjb25zdHJhaW50PzogQ29uc3RydWN0c01ha2VyVGFyZ2V0LFxuICApOiBSZXNvdXJjZU1vZGVsIHtcbiAgICBpZiAodGhpcy5yZXNvdXJjZXNbdHlwZV0pIHtcbiAgICAgIHJldHVybiB0aGlzLnJlc291cmNlc1t0eXBlXTtcbiAgICB9XG5cbiAgICBjb25zdCBwYXJzZXIgPSBuZXcgUGFyc2VyKHRoaXMudW5pcXVlQ2xhc3NuYW1lcyk7XG4gICAgY29uc3QgcmVzb3VyY2UgPSBwYXJzZXIucmVzb3VyY2VGcm9tKFxuICAgICAgZnFwbixcbiAgICAgIHR5cGUsXG4gICAgICBzY2hlbWEsXG4gICAgICB0ZXJyYWZvcm1UeXBlLFxuICAgICAgY29uc3RyYWludCxcbiAgICApO1xuICAgIHRoaXMucmVzb3VyY2VzW3R5cGVdID0gcmVzb3VyY2U7XG4gICAgcmV0dXJuIHJlc291cmNlO1xuICB9XG5cbiAgLy8gVXNlZCBieSBjb252ZXJ0IHRvIGRldGVybWluZSB0aGUgcmlnaHQgbmFtZSBmb3IgYSBjbGFzc1xuICBwdWJsaWMgZ2V0Q2xhc3NOYW1lRm9yUmVzb3VyY2UodGVycmFmb3JtVHlwZTogc3RyaW5nKSB7XG4gICAgY29uc3QgcmVzb3VyY2UgPSB0aGlzLnJlc291cmNlc1t0ZXJyYWZvcm1UeXBlXTtcbiAgICByZXR1cm4gcmVzb3VyY2UgPyByZXNvdXJjZS5jbGFzc05hbWUgOiBcIlwiO1xuICB9XG5cbiAgLy8gVXNlZCBieSBjb252ZXJ0IHRvIGRldGVybWluZSB0aGUgcmlnaHQgbmFtZSBmb3IgYSBuYW1lc3BhY2VcbiAgcHVibGljIGdldE5hbWVzcGFjZU5hbWVGb3JSZXNvdXJjZSh0ZXJyYWZvcm1UeXBlOiBzdHJpbmcpIHtcbiAgICAvLyBTcGVjaWFsIGNhc2UgZXh0ZXJuYWwgcHJvdmlkZXIgc2luY2UgdGhlIG5hbWUgb2YgcmVzb3VyY2UgZG9lc24ndCBoYXZlIGEgcHJlZml4XG4gICAgaWYgKHRlcnJhZm9ybVR5cGUgPT09IFwiZGF0YV9leHRlcm5hbF9cIikge1xuICAgICAgdGVycmFmb3JtVHlwZSA9IFwiZGF0YV9leHRlcm5hbFwiO1xuICAgIH1cblxuICAgIGNvbnN0IHJlc291cmNlID0gdGhpcy5yZXNvdXJjZXNbdGVycmFmb3JtVHlwZV07XG4gICAgaWYgKCFyZXNvdXJjZSkge1xuICAgICAgcmV0dXJuIFwiXCI7XG4gICAgfVxuICAgIGNvbnN0IGZvbGRlciA9IGBwcm92aWRlcnMvJHtyZXNvdXJjZS5wcm92aWRlcn1gO1xuICAgIHJldHVybiByZXNvdXJjZS5maWxlUGF0aC5yZXBsYWNlKGAke2ZvbGRlcn0vYCwgXCJcIikucmVwbGFjZShcIi9pbmRleC50c1wiLCBcIlwiKTtcbiAgfVxufVxuIl19
|