@cdktn/provider-generator 0.24.0-pre.9 → 0.24.0-pre.91
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.spec.swcrc +22 -0
- package/LICENSE +355 -0
- package/README.md +1 -1
- package/build/__tests__/edge-provider-schema/builder.d.ts +9 -3
- package/build/__tests__/edge-provider-schema/builder.js +6 -3
- package/build/__tests__/edge-provider-schema/cli.js +8 -3
- package/build/__tests__/edge-provider-schema/index.js +119 -1
- package/build/__tests__/provider.test.js +4 -1
- package/build/get/__tests__/generator/ephemeral-resources.test.d.ts +2 -0
- package/build/get/__tests__/generator/ephemeral-resources.test.js +49 -0
- package/build/get/__tests__/generator/module-generator.test.js +12 -12
- package/build/get/__tests__/generator/provider-functions.test.d.ts +2 -0
- package/build/get/__tests__/generator/provider-functions.test.js +176 -0
- package/build/get/__tests__/generator/provider-source-matching.test.d.ts +2 -0
- package/build/get/__tests__/generator/provider-source-matching.test.js +45 -0
- package/build/get/__tests__/generator/provider.test.js +9 -1
- package/build/get/__tests__/generator/supported-stored-classes.test.d.ts +2 -0
- package/build/get/__tests__/generator/supported-stored-classes.test.js +137 -0
- package/build/get/__tests__/generator/types.test.js +44 -1
- package/build/get/__tests__/generator/write-only.test.d.ts +2 -0
- package/build/get/__tests__/generator/write-only.test.js +65 -0
- package/build/get/__tests__/target-versions.test.d.ts +2 -0
- package/build/get/__tests__/target-versions.test.js +171 -0
- package/build/get/constructs-maker.d.ts +8 -1
- package/build/get/constructs-maker.js +46 -10
- package/build/get/generator/emitter/attributes-emitter.d.ts +13 -2
- package/build/get/generator/emitter/attributes-emitter.js +71 -5
- package/build/get/generator/emitter/index.d.ts +1 -0
- package/build/get/generator/emitter/index.js +2 -1
- package/build/get/generator/emitter/provider-functions-emitter.d.ts +11 -0
- package/build/get/generator/emitter/provider-functions-emitter.js +94 -0
- package/build/get/generator/emitter/resource-emitter.d.ts +5 -1
- package/build/get/generator/emitter/resource-emitter.js +83 -7
- package/build/get/generator/emitter/struct-emitter.js +10 -10
- package/build/get/generator/models/attribute-model.d.ts +4 -0
- package/build/get/generator/models/attribute-model.js +50 -4
- package/build/get/generator/models/attribute-type-model.d.ts +24 -0
- package/build/get/generator/models/attribute-type-model.js +91 -5
- package/build/get/generator/models/index.d.ts +1 -0
- package/build/get/generator/models/index.js +2 -1
- package/build/get/generator/models/provider-function-model.d.ts +102 -0
- package/build/get/generator/models/provider-function-model.js +667 -0
- package/build/get/generator/models/resource-model.d.ts +3 -0
- package/build/get/generator/models/resource-model.js +13 -4
- package/build/get/generator/models/struct.d.ts +2 -0
- package/build/get/generator/models/struct.js +6 -2
- package/build/get/generator/models/supported-stored-classes.d.ts +5 -0
- package/build/get/generator/models/supported-stored-classes.js +86 -0
- package/build/get/generator/module-generator.js +3 -3
- package/build/get/generator/provider-generator.d.ts +2 -0
- package/build/get/generator/provider-generator.js +41 -6
- package/build/get/generator/resource-parser.js +3 -1
- package/jest.config.js +16 -9
- package/package.json +28 -27
- package/package.sh +1 -1
- package/src/__tests__/__snapshots__/edge-provider-schema.test.ts.snap +4 -0
- package/src/__tests__/__snapshots__/provider.test.ts.snap +2828 -2828
- package/src/__tests__/edge-provider-schema/builder.ts +201 -0
- package/src/__tests__/edge-provider-schema/cli.ts +51 -0
- package/src/__tests__/edge-provider-schema/index.ts +284 -0
- package/src/__tests__/edge-provider-schema.test.ts +24 -0
- package/src/__tests__/provider.test.ts +183 -0
- package/src/get/__tests__/constructs-maker.test.ts +118 -0
- package/src/get/__tests__/generator/__snapshots__/complex-computed-types.test.ts.snap +5 -5
- package/src/get/__tests__/generator/__snapshots__/ephemeral-resources.test.ts.snap +524 -0
- package/src/get/__tests__/generator/__snapshots__/export-sharding.test.ts.snap +3310 -3310
- package/src/get/__tests__/generator/__snapshots__/module-generator.test.ts.snap +355 -355
- package/src/get/__tests__/generator/__snapshots__/nested-types.test.ts.snap +8 -8
- package/src/get/__tests__/generator/__snapshots__/provider-functions.test.ts.snap +444 -0
- package/src/get/__tests__/generator/__snapshots__/provider.test.ts.snap +8 -8
- package/src/get/__tests__/generator/__snapshots__/resource-types.test.ts.snap +126 -126
- package/src/get/__tests__/generator/__snapshots__/skipped-attributes.test.ts.snap +17 -17
- package/src/get/__tests__/generator/__snapshots__/types.test.ts.snap +201 -52
- package/src/get/__tests__/generator/__snapshots__/write-only.test.ts.snap +262 -0
- package/src/get/__tests__/generator/complex-computed-types.test.ts +28 -0
- package/src/get/__tests__/generator/deep-nested-attributes.test.ts +56 -0
- package/src/get/__tests__/generator/description-escaping.test.ts +84 -0
- package/src/get/__tests__/generator/empty-provider-resources.test.ts +26 -0
- package/src/get/__tests__/generator/ephemeral-resources.test.ts +46 -0
- package/src/get/__tests__/generator/export-sharding.test.ts +169 -0
- package/src/get/__tests__/generator/fixtures/deeply-nested-collections.test.fixture.json +129 -0
- package/src/get/__tests__/generator/fixtures/ephemeral-resources.test.fixture.json +160 -0
- package/src/get/__tests__/generator/fixtures/provider-functions-collision.test.fixture.json +31 -0
- package/src/get/__tests__/generator/fixtures/provider-functions-synthetic.test.fixture.json +192 -0
- package/src/get/__tests__/generator/fixtures/provider-functions.test.fixture.json +170 -0
- package/src/get/__tests__/generator/fixtures/write-only.test.fixture.json +58 -0
- package/src/get/__tests__/generator/import-style.test.ts +129 -0
- package/src/get/__tests__/generator/module-generator.test.ts +528 -0
- package/src/get/__tests__/generator/nested-types.test.ts +54 -0
- package/src/get/__tests__/generator/provider-functions.test.ts +262 -0
- package/src/get/__tests__/generator/provider-source-matching.test.ts +84 -0
- package/src/get/__tests__/generator/provider.test.ts +59 -0
- package/src/get/__tests__/generator/resource-types.test.ts +118 -0
- package/src/get/__tests__/generator/skipped-attributes.test.ts +72 -0
- package/src/get/__tests__/generator/supported-stored-classes.test.ts +147 -0
- package/src/get/__tests__/generator/types.test.ts +686 -0
- package/src/get/__tests__/generator/versions-file.test.ts +72 -0
- package/src/get/__tests__/generator/write-only.test.ts +71 -0
- package/src/get/__tests__/target-versions.test.ts +206 -0
- package/src/get/__tests__/util.ts +75 -0
- package/src/get/constructs-maker.ts +885 -0
- package/src/get/generator/custom-defaults.ts +493 -0
- package/src/get/generator/emitter/attributes-emitter.ts +316 -0
- package/src/get/generator/emitter/index.ts +6 -0
- package/src/get/generator/emitter/provider-functions-emitter.ts +117 -0
- package/src/get/generator/emitter/resource-emitter.ts +330 -0
- package/src/get/generator/emitter/struct-emitter.ts +683 -0
- package/src/get/generator/loop-detection.ts +81 -0
- package/src/get/generator/models/attribute-model.ts +273 -0
- package/src/get/generator/models/attribute-type-model.ts +560 -0
- package/src/get/generator/models/index.ts +8 -0
- package/src/get/generator/models/provider-function-model.ts +872 -0
- package/src/get/generator/models/resource-model.ts +183 -0
- package/src/get/generator/models/scope.ts +54 -0
- package/src/get/generator/models/struct.ts +124 -0
- package/src/get/generator/models/supported-stored-classes.ts +88 -0
- package/src/get/generator/module-generator.ts +234 -0
- package/src/get/generator/provider-generator.ts +428 -0
- package/src/get/generator/resource-parser.ts +764 -0
- package/src/get/generator/sanitized-comments.ts +49 -0
- package/src/get/generator/skipped-attributes.ts +27 -0
- package/src/index.ts +40 -0
- package/src/util.ts +26 -0
- package/tsconfig.json +1 -2
|
@@ -0,0 +1,667 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildProviderFunctionsModel = exports.assertNoFunctionsGetterCollision = void 0;
|
|
4
|
+
// Copyright (c) HashiCorp, Inc
|
|
5
|
+
// SPDX-License-Identifier: MPL-2.0
|
|
6
|
+
const codemaker_1 = require("codemaker");
|
|
7
|
+
// Parameter names that collide with a reserved word/identifier in one of the
|
|
8
|
+
// jsii target languages. This is the sibling table for provider-defined
|
|
9
|
+
// functions: tools/generate-function-bindings/scripts/generate.ts holds the
|
|
10
|
+
// canonical (and separately maintained) table for built-in `Fn.*` functions.
|
|
11
|
+
// The two are intentionally not shared - that script lives outside the
|
|
12
|
+
// packages/ build and generates a different artifact - but any reserved name
|
|
13
|
+
// added there should be considered here too.
|
|
14
|
+
const RESERVED_PARAMETER_NAMES = {
|
|
15
|
+
default: "defaultValue", // reserved word in TypeScript
|
|
16
|
+
string: "str", // causes issues in Go
|
|
17
|
+
};
|
|
18
|
+
function sanitizeParameterName(name) {
|
|
19
|
+
var _a;
|
|
20
|
+
const camelCased = (0, codemaker_1.toCamelCase)(name);
|
|
21
|
+
return (_a = RESERVED_PARAMETER_NAMES[camelCased]) !== null && _a !== void 0 ? _a : camelCased;
|
|
22
|
+
}
|
|
23
|
+
function sanitizeMethodName(name) {
|
|
24
|
+
if (name === "length")
|
|
25
|
+
return "lengthOf"; // reserved on jsii-generated classes
|
|
26
|
+
return (0, codemaker_1.toCamelCase)(name);
|
|
27
|
+
}
|
|
28
|
+
// Members that `ProviderFunctionsEmitter` (see `emitter/provider-functions-emitter.ts`)
|
|
29
|
+
// itself puts on every generated `<Provider>ProviderFunctions` wrapper class,
|
|
30
|
+
// regardless of which functions a provider declares:
|
|
31
|
+
// - "constructor": the class's own constructor, which takes the provider's
|
|
32
|
+
// `providerLocalName`. A provider-defined function named "constructor"
|
|
33
|
+
// would sanitize to a *second* `constructor` member on the class, which
|
|
34
|
+
// is invalid TypeScript.
|
|
35
|
+
// - "providerLocalName": the `private readonly providerLocalName: string`
|
|
36
|
+
// field the constructor assigns (see the emitter's `emitClassHeader`/
|
|
37
|
+
// constructor emission). A provider-defined function sanitizing to this
|
|
38
|
+
// name would collide with that field.
|
|
39
|
+
// If `ProviderFunctionsEmitter` ever grows more members on the wrapper class,
|
|
40
|
+
// add them here too.
|
|
41
|
+
const RESERVED_WRAPPER_MEMBER_NAMES = new Set([
|
|
42
|
+
"constructor",
|
|
43
|
+
"providerLocalName",
|
|
44
|
+
]);
|
|
45
|
+
/**
|
|
46
|
+
* The bracket-composable ("T[]", no top-level union) TypeScript/docstring
|
|
47
|
+
* type for an element that can nest inside an array without ITSELF needing
|
|
48
|
+
* the whole-collection token union at that level: `string`, `number`, or a
|
|
49
|
+
* list/set of one of those, recursively (e.g. `list(list(string))` bottoms
|
|
50
|
+
* out at `string`). Returns `undefined` for anything else (`bool`, `map`,
|
|
51
|
+
* `object`, `dynamic`, or a nested collection that doesn't itself qualify),
|
|
52
|
+
* so the caller falls back to widening the whole parameter to
|
|
53
|
+
* `any[] | cdktn.IResolvable` instead.
|
|
54
|
+
*/
|
|
55
|
+
function plainArrayElementType(type) {
|
|
56
|
+
if (type === "string")
|
|
57
|
+
return { tsType: "string", docstringType: "string" };
|
|
58
|
+
if (type === "number")
|
|
59
|
+
return { tsType: "number", docstringType: "number" };
|
|
60
|
+
if (Array.isArray(type) && (type[0] === "list" || type[0] === "set")) {
|
|
61
|
+
const inner = plainArrayElementType(type[1]);
|
|
62
|
+
if (!inner)
|
|
63
|
+
return undefined;
|
|
64
|
+
return {
|
|
65
|
+
tsType: `${inner.tsType}[]`,
|
|
66
|
+
docstringType: `${type[0] === "set" ? "Set" : "Array"}<${inner.docstringType}>`,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Maps a `list`/`set` parameter to its jsii-safe shape - mirrors
|
|
73
|
+
* `ListAttributeTypeModel`/`SetAttributeTypeModel.inputTypeDefinition`
|
|
74
|
+
* (both identical) branch for branch, since jsii parameters, like resource
|
|
75
|
+
* inputs, are allowed to union in a whole-collection `cdktn.IResolvable`
|
|
76
|
+
* token. `kind` only affects the documentation: the docstring notation
|
|
77
|
+
* (`Array<...>` for a Terraform list, `Set<...>` for a Terraform set,
|
|
78
|
+
* recursively via `plainArrayElementType`/`mapParameterType`) plus, for
|
|
79
|
+
* sets, a prose note - the jsii type is an array either way, so the note
|
|
80
|
+
* keeps a reader from literally passing a JS `Set` and flags the
|
|
81
|
+
* ordering/duplicate-element semantics difference. The type-level handling
|
|
82
|
+
* is identical for both.
|
|
83
|
+
*/
|
|
84
|
+
function mapListOrSetParameterType(kind, element) {
|
|
85
|
+
const wrapper = kind === "set" ? "Set" : "Array";
|
|
86
|
+
const docstringNote = kind === "set"
|
|
87
|
+
? "Terraform set; ordering is not guaranteed and duplicate values are removed."
|
|
88
|
+
: undefined;
|
|
89
|
+
if (element === "string") {
|
|
90
|
+
// Mirrors the final `else` branch: encoded list tokens already satisfy
|
|
91
|
+
// `string[]`, so no union is needed.
|
|
92
|
+
return {
|
|
93
|
+
tsType: "string[]",
|
|
94
|
+
docstringType: `${wrapper}<string>`,
|
|
95
|
+
docstringNote,
|
|
96
|
+
acceptsResolvableAlready: false,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
if (element === "number") {
|
|
100
|
+
// Same reasoning as `string` above.
|
|
101
|
+
return {
|
|
102
|
+
tsType: "number[]",
|
|
103
|
+
docstringType: `${wrapper}<number>`,
|
|
104
|
+
docstringNote,
|
|
105
|
+
acceptsResolvableAlready: false,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
if (element === "bool") {
|
|
109
|
+
// Mirrors the `elementType.storedClassType === "boolean"` branch: bool
|
|
110
|
+
// has no lossless per-element token, but the WHOLE collection is still
|
|
111
|
+
// tokenizable, so the union is on the outside.
|
|
112
|
+
return {
|
|
113
|
+
tsType: "Array<boolean | cdktn.IResolvable> | cdktn.IResolvable",
|
|
114
|
+
docstringType: `${wrapper}<boolean | IResolvable>`,
|
|
115
|
+
docstringNote,
|
|
116
|
+
acceptsResolvableAlready: true,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
const plainElement = plainArrayElementType(element);
|
|
120
|
+
if (plainElement) {
|
|
121
|
+
// Mirrors the `elementType.typeModelType !== "simple"` branch: a nested
|
|
122
|
+
// list/set that itself bottoms out at string/number composes into a
|
|
123
|
+
// proper nested array type (e.g. `list(list(string))` -> `string[][]`),
|
|
124
|
+
// with the whole-collection token additionally accepted alongside it.
|
|
125
|
+
return {
|
|
126
|
+
tsType: `${plainElement.tsType}[] | cdktn.IResolvable`,
|
|
127
|
+
docstringType: `${wrapper}<${plainElement.docstringType}>`,
|
|
128
|
+
docstringNote,
|
|
129
|
+
acceptsResolvableAlready: true,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
// map/object/dynamic element, or a nested collection that doesn't itself
|
|
133
|
+
// reduce to string/number: no jsii-safe array-of-X type exists - widen
|
|
134
|
+
// the whole parameter to `any[]`. Unlike a bare `any` parameter, plain
|
|
135
|
+
// `any[]` does NOT structurally accept a whole-collection
|
|
136
|
+
// `cdktn.IResolvable` token, so the union is required here (this is
|
|
137
|
+
// stricter than `MapAttributeTypeModel`/`ListAttributeTypeModel` have to
|
|
138
|
+
// be, since those only ever fall back to `any[] | cdktn.IResolvable` via
|
|
139
|
+
// the same "not simple" branch above, which already grants it). Keep the
|
|
140
|
+
// docstring honest about the real element shape rather than just saying
|
|
141
|
+
// `any`.
|
|
142
|
+
const elementDescription = mapParameterType(element).docstringType;
|
|
143
|
+
return {
|
|
144
|
+
tsType: "any[] | cdktn.IResolvable",
|
|
145
|
+
docstringType: `${wrapper}<${elementDescription}>`,
|
|
146
|
+
docstringNote,
|
|
147
|
+
acceptsResolvableAlready: true,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Maps a `map` parameter to its jsii-safe shape - mirrors
|
|
152
|
+
* `MapAttributeTypeModel.inputTypeDefinition`. Only the `bool`-element case
|
|
153
|
+
* is reachable from real provider schemas today (`string`/`number` element
|
|
154
|
+
* maps stay a plain, non-union record; nested/complex map elements aren't
|
|
155
|
+
* emitted for provider functions - see the `object` fallback in
|
|
156
|
+
* `mapParameterType`), but the shape is kept branch-for-branch aligned with
|
|
157
|
+
* the model it mirrors rather than collapsed.
|
|
158
|
+
*/
|
|
159
|
+
function mapMapParameterType(element) {
|
|
160
|
+
if (element === "string") {
|
|
161
|
+
return {
|
|
162
|
+
tsType: "{ [key: string]: string }",
|
|
163
|
+
docstringType: "{ [key: string]: string }",
|
|
164
|
+
acceptsResolvableAlready: false,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
if (element === "number") {
|
|
168
|
+
return {
|
|
169
|
+
tsType: "{ [key: string]: number }",
|
|
170
|
+
docstringType: "{ [key: string]: number }",
|
|
171
|
+
acceptsResolvableAlready: false,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
if (element === "bool") {
|
|
175
|
+
// Mirrors the `elementType.storedClassType === "boolean"` branch: map
|
|
176
|
+
// of booleans has PER-ENTRY token support, but the whole map itself is
|
|
177
|
+
// not additionally unioned with `cdktn.IResolvable` (unlike the list/set
|
|
178
|
+
// case) - matching `MapAttributeTypeModel.inputTypeDefinition` exactly.
|
|
179
|
+
return {
|
|
180
|
+
tsType: "{ [key: string]: (boolean | cdktn.IResolvable) }",
|
|
181
|
+
docstringType: "{ [key: string]: (boolean | IResolvable) }",
|
|
182
|
+
acceptsResolvableAlready: false,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
// map/object/dynamic element: no structural input helper exists here -
|
|
186
|
+
// stays `any`, which (being `any`) already accepts a whole-map
|
|
187
|
+
// `cdktn.IResolvable` token too.
|
|
188
|
+
return {
|
|
189
|
+
tsType: "any",
|
|
190
|
+
docstringType: "any",
|
|
191
|
+
acceptsResolvableAlready: true,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Maps a provider function parameter's declared Terraform type to a
|
|
196
|
+
* jsii-safe TypeScript parameter type, recursively for collection types.
|
|
197
|
+
*
|
|
198
|
+
* Unlike return types, jsii allows unions in *parameter* position, so
|
|
199
|
+
* `bool` is typed `boolean | cdktn.IResolvable` (mirroring
|
|
200
|
+
* `SimpleAttributeTypeModel.inputTypeDefinition`'s input-side convention) -
|
|
201
|
+
* this both accepts a real boolean and still accepts a token in place of
|
|
202
|
+
* one. `dynamic` has no structural typing and stays `any` (which already
|
|
203
|
+
* accepts anything, including a token); `object` (structural input helpers
|
|
204
|
+
* are deferred to a follow-up issue) stays `any` too.
|
|
205
|
+
*
|
|
206
|
+
* `list`/`set` and `map` delegate to `mapListOrSetParameterType`/
|
|
207
|
+
* `mapMapParameterType`, which mirror `ListAttributeTypeModel`/
|
|
208
|
+
* `SetAttributeTypeModel`/`MapAttributeTypeModel.inputTypeDefinition`
|
|
209
|
+
* branch for branch (see `attribute-type-model.ts`) - the same
|
|
210
|
+
* whole-collection-token conventions already used for resource inputs.
|
|
211
|
+
*/
|
|
212
|
+
function mapParameterType(type) {
|
|
213
|
+
if (type === "string") {
|
|
214
|
+
return {
|
|
215
|
+
tsType: "string",
|
|
216
|
+
docstringType: "string",
|
|
217
|
+
acceptsResolvableAlready: false,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
if (type === "number") {
|
|
221
|
+
return {
|
|
222
|
+
tsType: "number",
|
|
223
|
+
docstringType: "number",
|
|
224
|
+
acceptsResolvableAlready: false,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
if (type === "bool") {
|
|
228
|
+
return {
|
|
229
|
+
tsType: "boolean | cdktn.IResolvable",
|
|
230
|
+
docstringType: "boolean | IResolvable",
|
|
231
|
+
acceptsResolvableAlready: true,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
if (type === "dynamic") {
|
|
235
|
+
return {
|
|
236
|
+
tsType: "any",
|
|
237
|
+
docstringType: "any",
|
|
238
|
+
acceptsResolvableAlready: true,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
if (Array.isArray(type) && (type[0] === "list" || type[0] === "set")) {
|
|
242
|
+
return mapListOrSetParameterType(type[0], type[1]);
|
|
243
|
+
}
|
|
244
|
+
if (Array.isArray(type) && type[0] === "map") {
|
|
245
|
+
return mapMapParameterType(type[1]);
|
|
246
|
+
}
|
|
247
|
+
// object: structural input helpers are deferred to a follow-up issue.
|
|
248
|
+
return {
|
|
249
|
+
tsType: "any",
|
|
250
|
+
docstringType: "object",
|
|
251
|
+
acceptsResolvableAlready: true,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
function buildParameterModel(parameter, fallbackName) {
|
|
255
|
+
var _a;
|
|
256
|
+
const terraformName = (_a = parameter.name) !== null && _a !== void 0 ? _a : fallbackName;
|
|
257
|
+
const { tsType, docstringType, docstringNote, acceptsResolvableAlready } = mapParameterType(parameter.type);
|
|
258
|
+
return {
|
|
259
|
+
terraformName,
|
|
260
|
+
name: sanitizeParameterName(terraformName),
|
|
261
|
+
tsType,
|
|
262
|
+
docstringType,
|
|
263
|
+
docstringNote,
|
|
264
|
+
description: parameter.description,
|
|
265
|
+
acceptsResolvableAlready,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Widens a mapped type's `tsType`/`docstringType` to also accept an
|
|
270
|
+
* explicit `cdktn.Token.nullValue()` in this position - unless
|
|
271
|
+
* `acceptsResolvableAlready` says it already does (e.g. a `bool` parameter
|
|
272
|
+
* is already `boolean | cdktn.IResolvable`, so nullability adds nothing to
|
|
273
|
+
* the type itself, only to the docstring note appended by the caller).
|
|
274
|
+
*/
|
|
275
|
+
function withNullableResolvableUnion(model) {
|
|
276
|
+
if (model.acceptsResolvableAlready) {
|
|
277
|
+
return { tsType: model.tsType, docstringType: model.docstringType };
|
|
278
|
+
}
|
|
279
|
+
return {
|
|
280
|
+
tsType: `${model.tsType} | cdktn.IResolvable`,
|
|
281
|
+
docstringType: `${model.docstringType} | IResolvable`,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Applies `is_nullable` trailing-compatibility rules across a function's
|
|
286
|
+
* fixed (non-variadic) parameter list. This needs the whole list in view
|
|
287
|
+
* (see `buildFunctionModel`), since whether a nullable parameter can become
|
|
288
|
+
* jsii-optional depends on every parameter *after* it too:
|
|
289
|
+
*
|
|
290
|
+
* - A nullable parameter where it and every later fixed parameter are also
|
|
291
|
+
* nullable becomes jsii-optional (`name?: T`): omitting it in TypeScript
|
|
292
|
+
* leaves `undefined` in the invoke args array, which `FunctionCall`
|
|
293
|
+
* already renders as the Terraform `null` keyword. It additionally gains
|
|
294
|
+
* the `| cdktn.IResolvable` union (see `withNullableResolvableUnion`), so
|
|
295
|
+
* a caller who does supply the argument can pass
|
|
296
|
+
* `cdktn.Token.nullValue()` for an explicit Terraform `null` without
|
|
297
|
+
* omitting the parameter.
|
|
298
|
+
* - A nullable parameter followed by a required one keeps its position
|
|
299
|
+
* (jsii can't express "optional but not trailing"), and instead gains the
|
|
300
|
+
* same `| cdktn.IResolvable` union so a caller can still pass an explicit
|
|
301
|
+
* `cdktn.Token.nullValue()` (an `IResolvable` resolving to `null` - see
|
|
302
|
+
* `Token.nullValue()`/`Token.asAny()`) in that fixed position - keeping
|
|
303
|
+
* the parameter's real type rather than giving up all type safety by
|
|
304
|
+
* widening it to `any`.
|
|
305
|
+
*
|
|
306
|
+
* Both cases document the real mechanism in the docstring note rather than
|
|
307
|
+
* implying the plain TypeScript `null` literal is accepted: the trailing
|
|
308
|
+
* case can also just be omitted, the mid-position case can't be omitted at
|
|
309
|
+
* all (jsii can't express "optional but not trailing").
|
|
310
|
+
*/
|
|
311
|
+
function applyNullability(parameters, models) {
|
|
312
|
+
const trailingCompatible = new Array(parameters.length).fill(false);
|
|
313
|
+
let allNullableSoFar = true;
|
|
314
|
+
for (let i = parameters.length - 1; i >= 0; i--) {
|
|
315
|
+
allNullableSoFar = allNullableSoFar && parameters[i].is_nullable === true;
|
|
316
|
+
trailingCompatible[i] = allNullableSoFar;
|
|
317
|
+
}
|
|
318
|
+
return models.map((model, index) => {
|
|
319
|
+
const parameter = parameters[index];
|
|
320
|
+
if (!parameter.is_nullable)
|
|
321
|
+
return model;
|
|
322
|
+
const { tsType, docstringType } = withNullableResolvableUnion(model);
|
|
323
|
+
const nullabilityNote = trailingCompatible[index]
|
|
324
|
+
? "Omit or pass cdktn.Token.nullValue() to render the Terraform null keyword."
|
|
325
|
+
: "Pass cdktn.Token.nullValue() for an explicit Terraform null.";
|
|
326
|
+
return {
|
|
327
|
+
...model,
|
|
328
|
+
...(trailingCompatible[index] ? { optional: true } : {}),
|
|
329
|
+
tsType,
|
|
330
|
+
docstringType,
|
|
331
|
+
docstringNote: [model.docstringNote, nullabilityNote]
|
|
332
|
+
.filter(Boolean)
|
|
333
|
+
.join(" "),
|
|
334
|
+
};
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Maps a provider function's declared return type to the jsii-safe
|
|
339
|
+
* TypeScript return type, the `@returns` JSDoc type, and the expression
|
|
340
|
+
* that unwraps the `TerraformProviderFunction.invoke(...)` `IResolvable`
|
|
341
|
+
* into it.
|
|
342
|
+
*
|
|
343
|
+
* jsii return positions can't use the `T | cdktn.IResolvable` union that
|
|
344
|
+
* parameters can (see `mapParameterType`), so every shape that can't be
|
|
345
|
+
* losslessly unwrapped through an `asXxx` Token helper falls back to the
|
|
346
|
+
* plain `cdktn.IResolvable` produced by `invoke()` itself, unwrapped.
|
|
347
|
+
* Provider functions frequently return objects (e.g. every function in the
|
|
348
|
+
* `time` provider), so - unlike built-in `Fn.*` functions - the object case
|
|
349
|
+
* is a primary path, not an error: it is treated the same as
|
|
350
|
+
* `dynamic`/a `list`/`set` of anything other than `string`/`number` (no
|
|
351
|
+
* `asAnyList` Token helper exists), and returned as the RAW `invoke()`
|
|
352
|
+
* result. `map` returns, unlike those, DO have a full set of typed Token
|
|
353
|
+
* helpers (`asStringMap`/`asNumberMap`/`asBooleanMap`/`asAnyMap`), so every
|
|
354
|
+
* `map` shape gets an actual typed record return instead of falling back to
|
|
355
|
+
* `cdktn.IResolvable`.
|
|
356
|
+
*
|
|
357
|
+
* Whenever the declared return type IS `cdktn.IResolvable` (not `any`):
|
|
358
|
+
* unlike `helpers.ts` `asAny`, this must NOT go through
|
|
359
|
+
* `cdktn.Token.asString(...)` - `Token.asString()` produces an encoded
|
|
360
|
+
* string token that `Tokenization.isResolvable()` does not recognize, so
|
|
361
|
+
* generated struct setters (e.g. an `OutputReference` `internalValue`) treat
|
|
362
|
+
* it as a plain object with no known keys and the attribute silently
|
|
363
|
+
* vanishes from synth output. The raw `IResolvable` from `invoke()` IS
|
|
364
|
+
* recognized by `Tokenization.isResolvable()` and resolves correctly.
|
|
365
|
+
* Declaring it as `cdktn.IResolvable` instead of `any` also gives callers
|
|
366
|
+
* real type safety: `any` let a caller write `result.hours` on a token with
|
|
367
|
+
* no compile-time feedback, silently producing `undefined` at runtime;
|
|
368
|
+
* `IResolvable` has no such property and forces the caller through
|
|
369
|
+
* `cdktn.Token`/the provider's struct types instead. `invoke()` already
|
|
370
|
+
* returns `IResolvable`, so no cast is needed to return it as
|
|
371
|
+
* `cdktn.IResolvable`.
|
|
372
|
+
*/
|
|
373
|
+
function mapReturnType(returnType) {
|
|
374
|
+
if (returnType === "string") {
|
|
375
|
+
return {
|
|
376
|
+
tsType: "string",
|
|
377
|
+
docstringType: "string",
|
|
378
|
+
wrapReturn: (expr) => `cdktn.Token.asString(${expr})`,
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
if (returnType === "number") {
|
|
382
|
+
return {
|
|
383
|
+
tsType: "number",
|
|
384
|
+
docstringType: "number",
|
|
385
|
+
wrapReturn: (expr) => `cdktn.Token.asNumber(${expr})`,
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
if (returnType === "bool") {
|
|
389
|
+
// Booleans can't be represented as tokens (see helpers.ts asBoolean):
|
|
390
|
+
// return the IResolvable produced by invoke() unwrapped. The docstring
|
|
391
|
+
// still documents the real conceptual shape.
|
|
392
|
+
return {
|
|
393
|
+
tsType: "cdktn.IResolvable",
|
|
394
|
+
docstringType: "boolean | IResolvable",
|
|
395
|
+
wrapReturn: (expr) => expr,
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
if (returnType === "dynamic") {
|
|
399
|
+
return {
|
|
400
|
+
tsType: "cdktn.IResolvable",
|
|
401
|
+
docstringType: "any",
|
|
402
|
+
wrapReturn: (expr) => expr,
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
if (Array.isArray(returnType) &&
|
|
406
|
+
(returnType[0] === "list" || returnType[0] === "set")) {
|
|
407
|
+
// Same documentation conventions as `mapListOrSetParameterType`: the
|
|
408
|
+
// notation (`Array<...>`/`Set<...>`) carries the Terraform collection
|
|
409
|
+
// structure recursively, and only sets get a prose note.
|
|
410
|
+
const wrapper = returnType[0] === "set" ? "Set" : "Array";
|
|
411
|
+
const docstringNote = returnType[0] === "set"
|
|
412
|
+
? "Terraform set; ordering is not guaranteed and duplicate values are removed."
|
|
413
|
+
: undefined;
|
|
414
|
+
const element = returnType[1];
|
|
415
|
+
if (element === "string") {
|
|
416
|
+
return {
|
|
417
|
+
tsType: "string[]",
|
|
418
|
+
docstringType: `${wrapper}<string>`,
|
|
419
|
+
docstringNote,
|
|
420
|
+
wrapReturn: (expr) => `cdktn.Token.asList(${expr})`,
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
if (element === "number") {
|
|
424
|
+
return {
|
|
425
|
+
tsType: "number[]",
|
|
426
|
+
docstringType: `${wrapper}<number>`,
|
|
427
|
+
docstringNote,
|
|
428
|
+
wrapReturn: (expr) => `cdktn.Token.asNumberList(${expr})`,
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
// list/set of anything else: there is no `asAnyList` Token helper -
|
|
432
|
+
// fall back to the raw IResolvable, same reasoning as dynamic/object
|
|
433
|
+
// below, but keep the docstring honest about the real element shape
|
|
434
|
+
// (reusing mapParameterType purely for its descriptive docstringType -
|
|
435
|
+
// its tsType/acceptsResolvableAlready are irrelevant here).
|
|
436
|
+
return {
|
|
437
|
+
tsType: "cdktn.IResolvable",
|
|
438
|
+
docstringType: `${wrapper}<${mapParameterType(element).docstringType}>`,
|
|
439
|
+
docstringNote,
|
|
440
|
+
wrapReturn: (expr) => expr,
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
if (Array.isArray(returnType) && returnType[0] === "map") {
|
|
444
|
+
// Unlike list/set and object/dynamic, every `map` shape has a matching
|
|
445
|
+
// typed Token helper (see token.ts), so it gets a real typed record
|
|
446
|
+
// return instead of falling back to the raw IResolvable.
|
|
447
|
+
const element = returnType[1];
|
|
448
|
+
if (element === "string") {
|
|
449
|
+
return {
|
|
450
|
+
tsType: "{ [key: string]: string }",
|
|
451
|
+
docstringType: "{ [key: string]: string }",
|
|
452
|
+
wrapReturn: (expr) => `cdktn.Token.asStringMap(${expr})`,
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
if (element === "number") {
|
|
456
|
+
return {
|
|
457
|
+
tsType: "{ [key: string]: number }",
|
|
458
|
+
docstringType: "{ [key: string]: number }",
|
|
459
|
+
wrapReturn: (expr) => `cdktn.Token.asNumberMap(${expr})`,
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
if (element === "bool") {
|
|
463
|
+
// Token.asBooleanMap's declared return type is `{ [key: string]:
|
|
464
|
+
// boolean }` (see token.ts) - used verbatim, not unioned with
|
|
465
|
+
// IResolvable: the map's individual entries are plain booleans once
|
|
466
|
+
// unwrapped by the helper.
|
|
467
|
+
return {
|
|
468
|
+
tsType: "{ [key: string]: boolean }",
|
|
469
|
+
docstringType: "{ [key: string]: boolean }",
|
|
470
|
+
wrapReturn: (expr) => `cdktn.Token.asBooleanMap(${expr})`,
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
// map of anything else (object/dynamic/nested collection): asAnyMap
|
|
474
|
+
// still gives a typed (if loosely-typed) record rather than falling
|
|
475
|
+
// back to the raw IResolvable.
|
|
476
|
+
return {
|
|
477
|
+
tsType: "{ [key: string]: any }",
|
|
478
|
+
docstringType: "{ [key: string]: any }",
|
|
479
|
+
wrapReturn: (expr) => `cdktn.Token.asAnyMap(${expr})`,
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
// object: no structural typing for arbitrary provider function results -
|
|
483
|
+
// declared as `cdktn.IResolvable`, and returned as the raw `IResolvable`
|
|
484
|
+
// from invoke() (NOT wrapped in `cdktn.Token.asString(...)`, which would
|
|
485
|
+
// make the result unrecognizable to `Tokenization.isResolvable()`
|
|
486
|
+
// downstream - see the mapReturnType docstring above).
|
|
487
|
+
return {
|
|
488
|
+
tsType: "cdktn.IResolvable",
|
|
489
|
+
docstringType: "object",
|
|
490
|
+
wrapReturn: (expr) => expr,
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
function buildFunctionModel(terraformName, signature) {
|
|
494
|
+
var _a;
|
|
495
|
+
const { tsType: returnTsType, docstringType: returnDocstringType, docstringNote: returnDocstringNote, wrapReturn, } = mapReturnType(signature.return_type);
|
|
496
|
+
const rawParameters = (_a = signature.parameters) !== null && _a !== void 0 ? _a : [];
|
|
497
|
+
const parameters = applyNullability(rawParameters, rawParameters.map((parameter, index) => buildParameterModel(parameter, `arg${index}`)));
|
|
498
|
+
let variadicParameter;
|
|
499
|
+
if (signature.variadic_parameter) {
|
|
500
|
+
const elementModel = buildParameterModel(signature.variadic_parameter, "values");
|
|
501
|
+
if (signature.variadic_parameter.is_nullable) {
|
|
502
|
+
// A nullable variadic parameter: jsii can't express "each individual
|
|
503
|
+
// argument may independently be null" on the generated `values:
|
|
504
|
+
// Array<T>` array parameter (it's an ordinary array parameter, not a
|
|
505
|
+
// true rest/spread parameter - only the invoke() call site spreads
|
|
506
|
+
// it), so every element's type instead widens to also accept an
|
|
507
|
+
// explicit `cdktn.Token.nullValue()`, the same way a fixed nullable
|
|
508
|
+
// parameter does (see `withNullableResolvableUnion`); the docstring
|
|
509
|
+
// keeps the honest per-element type plus that guidance in its note.
|
|
510
|
+
const { tsType, docstringType } = withNullableResolvableUnion(elementModel);
|
|
511
|
+
variadicParameter = {
|
|
512
|
+
...elementModel,
|
|
513
|
+
tsType,
|
|
514
|
+
docstringType: `Array<${docstringType}>`,
|
|
515
|
+
docstringNote: [
|
|
516
|
+
elementModel.docstringNote,
|
|
517
|
+
"Pass cdktn.Token.nullValue() for an explicit Terraform null.",
|
|
518
|
+
]
|
|
519
|
+
.filter(Boolean)
|
|
520
|
+
.join(" "),
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
else {
|
|
524
|
+
// Non-nullable: the docstring wraps the element's docstring type in
|
|
525
|
+
// `Array<...>` here (rather than in the emitter), so every parameter
|
|
526
|
+
// - fixed or variadic - can share one `@param {docstringType}`
|
|
527
|
+
// emission path.
|
|
528
|
+
variadicParameter = {
|
|
529
|
+
...elementModel,
|
|
530
|
+
docstringType: `Array<${elementModel.docstringType}>`,
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
return {
|
|
535
|
+
terraformName,
|
|
536
|
+
methodName: sanitizeMethodName(terraformName),
|
|
537
|
+
description: signature.description,
|
|
538
|
+
summary: signature.summary,
|
|
539
|
+
deprecationMessage: signature.deprecation_message,
|
|
540
|
+
returnTsType,
|
|
541
|
+
returnDocstringType,
|
|
542
|
+
returnDocstringNote,
|
|
543
|
+
wrapReturn,
|
|
544
|
+
parameters,
|
|
545
|
+
variadicParameter,
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* Throws if two functions in the same provider sanitize to the same
|
|
550
|
+
* generated method name. Terraform function names are unique, but
|
|
551
|
+
* `sanitizeMethodName` (camelCasing, `length` -> `lengthOf`) is not
|
|
552
|
+
* necessarily injective, so a real - if unlikely - provider schema could
|
|
553
|
+
* still produce a duplicate method. Generation is aborted rather than
|
|
554
|
+
* silently emitting one method that shadows the other.
|
|
555
|
+
*/
|
|
556
|
+
function assertNoMethodNameCollisions(providerName, functions) {
|
|
557
|
+
const seenBy = new Map(); // methodName -> terraformName
|
|
558
|
+
for (const fn of functions) {
|
|
559
|
+
const existingTerraformName = seenBy.get(fn.methodName);
|
|
560
|
+
if (existingTerraformName !== undefined) {
|
|
561
|
+
throw new Error(`Provider "${providerName}" declares two provider-defined functions, ` +
|
|
562
|
+
`"${existingTerraformName}" and "${fn.terraformName}", that both ` +
|
|
563
|
+
`sanitize to the generated method name "${fn.methodName}". ` +
|
|
564
|
+
`Generation aborted to avoid silently overwriting one method with ` +
|
|
565
|
+
`the other - please report this as an issue.`);
|
|
566
|
+
}
|
|
567
|
+
seenBy.set(fn.methodName, fn.terraformName);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Throws if a function's sanitized `methodName` lands on a member name
|
|
572
|
+
* `ProviderFunctionsEmitter` already puts on every wrapper class (see
|
|
573
|
+
* `RESERVED_WRAPPER_MEMBER_NAMES`). Unlike `assertNoMethodNameCollisions`,
|
|
574
|
+
* which only catches two *functions* colliding with each other, this catches
|
|
575
|
+
* a single function colliding with the wrapper class itself - e.g. a
|
|
576
|
+
* Terraform function literally named "constructor", or "provider_local_name"
|
|
577
|
+
* camelCasing to "providerLocalName".
|
|
578
|
+
*
|
|
579
|
+
* This intentionally does NOT also check sanitized *parameter* names against
|
|
580
|
+
* "providerLocalName": parameters are declared in the generated method's own
|
|
581
|
+
* scope, not the class's, so a parameter named `providerLocalName` shadows
|
|
582
|
+
* the class field within that method body without colliding with it (valid,
|
|
583
|
+
* if confusing, TypeScript) - there is nothing to abort generation over.
|
|
584
|
+
*/
|
|
585
|
+
function assertNoReservedWrapperMemberCollisions(providerName, functions) {
|
|
586
|
+
for (const fn of functions) {
|
|
587
|
+
if (RESERVED_WRAPPER_MEMBER_NAMES.has(fn.methodName)) {
|
|
588
|
+
throw new Error(`Provider "${providerName}" declares a provider-defined function ` +
|
|
589
|
+
`"${fn.terraformName}" that sanitizes to the generated method name ` +
|
|
590
|
+
`"${fn.methodName}", which collides with a member that ` +
|
|
591
|
+
`ProviderFunctionsEmitter already puts on every ` +
|
|
592
|
+
`"<Provider>ProviderFunctions" wrapper class (the class ` +
|
|
593
|
+
`constructor, or its "providerLocalName" field). Generation ` +
|
|
594
|
+
`aborted to avoid emitting invalid TypeScript or silently ` +
|
|
595
|
+
`shadowing that member - please report this as an issue.`);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* Throws if two parameters of the same function (including the variadic
|
|
601
|
+
* parameter) sanitize to the same generated parameter name, for the same
|
|
602
|
+
* reason as `assertNoMethodNameCollisions` above but at the parameter level.
|
|
603
|
+
*/
|
|
604
|
+
function assertNoParameterNameCollisions(providerName, fn) {
|
|
605
|
+
const seenBy = new Map(); // sanitized name -> terraformName
|
|
606
|
+
const allParameters = fn.variadicParameter
|
|
607
|
+
? [...fn.parameters, fn.variadicParameter]
|
|
608
|
+
: fn.parameters;
|
|
609
|
+
for (const param of allParameters) {
|
|
610
|
+
const existingTerraformName = seenBy.get(param.name);
|
|
611
|
+
if (existingTerraformName !== undefined) {
|
|
612
|
+
throw new Error(`Provider "${providerName}" function "${fn.terraformName}" declares ` +
|
|
613
|
+
`two parameters, "${existingTerraformName}" and ` +
|
|
614
|
+
`"${param.terraformName}", that both sanitize to the generated ` +
|
|
615
|
+
`parameter name "${param.name}". Generation aborted to avoid ` +
|
|
616
|
+
`silently dropping one parameter - please report this as an issue.`);
|
|
617
|
+
}
|
|
618
|
+
seenBy.set(param.name, param.terraformName);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
/**
|
|
622
|
+
* Throws if the provider's own config schema declares an attribute whose
|
|
623
|
+
* generated property name (see `AttributeModel.name` /
|
|
624
|
+
* `escapeAttributeName`) is exactly "functions", while the provider also
|
|
625
|
+
* declares provider-defined functions. That combination would collide with
|
|
626
|
+
* the memoized `functions` getter `ResourceEmitter` emits on the provider
|
|
627
|
+
* class (see `resource-emitter.ts`'s `emitFunctionsGetter`) - one would
|
|
628
|
+
* silently shadow the other. Same loud-failure convention as
|
|
629
|
+
* `assertNoMethodNameCollisions`/`assertNoParameterNameCollisions` above:
|
|
630
|
+
* generation is aborted rather than silently picking a winner.
|
|
631
|
+
*/
|
|
632
|
+
function assertNoFunctionsGetterCollision(providerName, attributeNames) {
|
|
633
|
+
if (attributeNames.includes("functions")) {
|
|
634
|
+
throw new Error(`Provider "${providerName}" declares provider-defined functions and its ` +
|
|
635
|
+
`own config schema also has an attribute that generates the property ` +
|
|
636
|
+
`name "functions" on the provider class. This collides with the ` +
|
|
637
|
+
`generated "functions" getter used to invoke provider-defined ` +
|
|
638
|
+
`functions. Generation aborted to avoid silently shadowing one with ` +
|
|
639
|
+
`the other - please report this as an issue.`);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
exports.assertNoFunctionsGetterCollision = assertNoFunctionsGetterCollision;
|
|
643
|
+
/**
|
|
644
|
+
* Builds the model for a provider's `provider-functions/index.ts` file from
|
|
645
|
+
* its provider schema `functions` map. Returns `undefined` when the provider
|
|
646
|
+
* declares no functions - callers should skip emitting the file entirely.
|
|
647
|
+
*/
|
|
648
|
+
function buildProviderFunctionsModel(providerName, functions) {
|
|
649
|
+
const entries = Object.entries(functions !== null && functions !== void 0 ? functions : {});
|
|
650
|
+
if (entries.length === 0)
|
|
651
|
+
return undefined;
|
|
652
|
+
const mappedFunctions = entries
|
|
653
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
654
|
+
.map(([name, signature]) => buildFunctionModel(name, signature));
|
|
655
|
+
assertNoMethodNameCollisions(providerName, mappedFunctions);
|
|
656
|
+
assertNoReservedWrapperMemberCollisions(providerName, mappedFunctions);
|
|
657
|
+
for (const fn of mappedFunctions) {
|
|
658
|
+
assertNoParameterNameCollisions(providerName, fn);
|
|
659
|
+
}
|
|
660
|
+
return {
|
|
661
|
+
providerName,
|
|
662
|
+
className: `${(0, codemaker_1.toPascalCase)(providerName)}ProviderFunctions`,
|
|
663
|
+
functions: mappedFunctions,
|
|
664
|
+
};
|
|
665
|
+
}
|
|
666
|
+
exports.buildProviderFunctionsModel = buildProviderFunctionsModel;
|
|
667
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmlkZXItZnVuY3Rpb24tbW9kZWwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvZ2V0L2dlbmVyYXRvci9tb2RlbHMvcHJvdmlkZXItZnVuY3Rpb24tbW9kZWwudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsK0JBQStCO0FBQy9CLG1DQUFtQztBQUNuQyx5Q0FBc0Q7QUF5R3RELDZFQUE2RTtBQUM3RSx3RUFBd0U7QUFDeEUsNEVBQTRFO0FBQzVFLDZFQUE2RTtBQUM3RSx1RUFBdUU7QUFDdkUsNkVBQTZFO0FBQzdFLDZDQUE2QztBQUM3QyxNQUFNLHdCQUF3QixHQUErQjtJQUMzRCxPQUFPLEVBQUUsY0FBYyxFQUFFLDhCQUE4QjtJQUN2RCxNQUFNLEVBQUUsS0FBSyxFQUFFLHNCQUFzQjtDQUN0QyxDQUFDO0FBRUYsU0FBUyxxQkFBcUIsQ0FBQyxJQUFZOztJQUN6QyxNQUFNLFVBQVUsR0FBRyxJQUFBLHVCQUFXLEVBQUMsSUFBSSxDQUFDLENBQUM7SUFDckMsT0FBTyxNQUFBLHdCQUF3QixDQUFDLFVBQVUsQ0FBQyxtQ0FBSSxVQUFVLENBQUM7QUFDNUQsQ0FBQztBQUVELFNBQVMsa0JBQWtCLENBQUMsSUFBWTtJQUN0QyxJQUFJLElBQUksS0FBSyxRQUFRO1FBQUUsT0FBTyxVQUFVLENBQUMsQ0FBQyxxQ0FBcUM7SUFDL0UsT0FBTyxJQUFBLHVCQUFXLEVBQUMsSUFBSSxDQUFDLENBQUM7QUFDM0IsQ0FBQztBQUVELHdGQUF3RjtBQUN4Riw4RUFBOEU7QUFDOUUscURBQXFEO0FBQ3JELDZFQUE2RTtBQUM3RSwyRUFBMkU7QUFDM0UsNEVBQTRFO0FBQzVFLDZCQUE2QjtBQUM3Qiw0RUFBNEU7QUFDNUUsMEVBQTBFO0FBQzFFLDRFQUE0RTtBQUM1RSwwQ0FBMEM7QUFDMUMsOEVBQThFO0FBQzlFLHFCQUFxQjtBQUNyQixNQUFNLDZCQUE2QixHQUFHLElBQUksR0FBRyxDQUFDO0lBQzVDLGFBQWE7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QUFDLE1BQU0sS0FBSyxDQUFDO1FBQUUsT0FBTyxTQUFTLENBQUM7SUFFM0MsTUFBTSxlQUFlLEdBQUcsT0FBTztTQUM1QixJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDdEMsR0FBRyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsU0FBUyxDQUFDLEVBQUUsRUFBRSxDQUFDLGtCQUFrQixDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDO0lBRW5FLDRCQUE0QixDQUFDLFlBQVksRUFBRSxlQUFlLENBQUMsQ0FBQztJQUM1RCx1Q0FBdUMsQ0FBQyxZQUFZLEVBQUUsZUFBZSxDQUFDLENBQUM7SUFDdkUsS0FBSyxNQUFNLEVBQUUsSUFBSSxlQUFlLEVBQUUsQ0FBQztRQUNqQywrQkFBK0IsQ0FBQyxZQUFZLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDcEQsQ0FBQztJQUVELE9BQU87UUFDTCxZQUFZO1FBQ1osU0FBUyxFQUFFLEdBQUcsSUFBQSx3QkFBWSxFQUFDLFlBQVksQ0FBQyxtQkFBbUI7UUFDM0QsU0FBUyxFQUFFLGVBQWU7S0FDM0IsQ0FBQztBQUNKLENBQUM7QUF0QkQsa0VBc0JDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IChjKSBIYXNoaUNvcnAsIEluY1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IE1QTC0yLjBcbmltcG9ydCB7IHRvQ2FtZWxDYXNlLCB0b1Bhc2NhbENhc2UgfSBmcm9tIFwiY29kZW1ha2VyXCI7XG5pbXBvcnQge1xuICBBdHRyaWJ1dGVUeXBlLFxuICBGdW5jdGlvblBhcmFtZXRlcixcbiAgRnVuY3Rpb25TaWduYXR1cmUsXG59IGZyb20gXCJAY2RrdG4vY29tbW9uc1wiO1xuXG4vKipcbiAqIEEgcHJvdmlkZXItZGVmaW5lZCBmdW5jdGlvbiBwYXJhbWV0ZXIgKHBvc2l0aW9uYWwgb3IgdGhlIHRyYWlsaW5nXG4gKiB2YXJpYWRpYyBvbmUpLCBtYXBwZWQgdG8gdGhlIGpzaWktc2FmZSBUeXBlU2NyaXB0IHR5cGUgdXNlZCBpbiB0aGVcbiAqIGdlbmVyYXRlZCBtZXRob2Qgc2lnbmF0dXJlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFByb3ZpZGVyRnVuY3Rpb25QYXJhbWV0ZXJNb2RlbCB7XG4gIHJlYWRvbmx5IHRlcnJhZm9ybU5hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgbmFtZTogc3RyaW5nO1xuICByZWFkb25seSB0c1R5cGU6IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBKU0RvYyB0eXBlIGV4cHJlc3Npb24gZW1pdHRlZCBpbnNpZGUgdGhlIGBAcGFyYW0gey4uLn1gIGJyYWNlcy5cbiAgICogQSBwdXJlIHR5cGUgZXhwcmVzc2lvbiBvbmx5IC0gcHJvc2UgKFRlcnJhZm9ybSBsaXN0L3NldCBzZW1hbnRpY3MsXG4gICAqIGBjZGt0bi5Ub2tlbi5udWxsVmFsdWUoKWAgZ3VpZGFuY2UpIGJlbG9uZ3MgaW4gYGRvY3N0cmluZ05vdGVgLlxuICAgKi9cbiAgcmVhZG9ubHkgZG9jc3RyaW5nVHlwZTogc3RyaW5nO1xuICAvKipcbiAgICogUHJvc2UgYXBwZW5kZWQgYWZ0ZXIgdGhlIHBhcmFtZXRlciBuYW1lIChhbmQgYGRlc2NyaXB0aW9uYCwgaWYgYW55KSBpblxuICAgKiB0aGUgZW1pdHRlZCBgQHBhcmFtYCBsaW5lIC0gZS5nLiBzZXQtb3JkZXJpbmcgc2VtYW50aWNzIG9yIGhvdyB0byBwYXNzXG4gICAqIGFuIGV4cGxpY2l0IFRlcnJhZm9ybSBgbnVsbGAuIE9mZmljaWFsIEpTRG9jIHBsYWNlcyBvbmx5IHRoZSB0eXBlXG4gICAqIGV4cHJlc3Npb24gaW5zaWRlIHRoZSBicmFjZXMsIHNvIHRoaXMgbXVzdCBuZXZlciBiZSBmb2xkZWQgaW50b1xuICAgKiBgZG9jc3RyaW5nVHlwZWAuXG4gICAqL1xuICByZWFkb25seSBkb2NzdHJpbmdOb3RlPzogc3RyaW5nO1xuICByZWFkb25seSBkZXNjcmlwdGlvbj86IHN0cmluZztcbiAgLyoqXG4gICAqIFRydWUgd2hlbiB0aGlzIChmaXhlZCwgbm9uLXZhcmlhZGljKSBwYXJhbWV0ZXIgaXMgZW1pdHRlZCBhcyBhXG4gICAqIGpzaWktb3B0aW9uYWwgVHlwZVNjcmlwdCBwYXJhbWV0ZXIgKGBuYW1lPzogVGApIC0gc2VlIHRoZVxuICAgKiBpc19udWxsYWJsZS90cmFpbGluZy1jb21wYXRpYmlsaXR5IGhhbmRsaW5nIGluIGBhcHBseU51bGxhYmlsaXR5YC5cbiAgICogTmV2ZXIgc2V0IG9uIHRoZSB2YXJpYWRpYyBwYXJhbWV0ZXI6IGFuIGFycmF5IHBhcmFtZXRlciBjYW4ndCBiZSBgP2AuXG4gICAqL1xuICByZWFkb25seSBvcHRpb25hbD86IGJvb2xlYW47XG59XG5cbi8qKlxuICogYFByb3ZpZGVyRnVuY3Rpb25QYXJhbWV0ZXJNb2RlbGAgcGx1cyB0aGUgb25lIGJpdCBvZiBpbmZvcm1hdGlvbiB0aGF0J3NcbiAqIG9ubHkgbmVlZGVkIHdoaWxlIGJ1aWxkaW5nIHRoZSBtb2RlbCAoc2VlIGBtYXBQYXJhbWV0ZXJUeXBlYC9cbiAqIGBhcHBseU51bGxhYmlsaXR5YCksIG5ldmVyIGJ5IHRoZSBlbWl0dGVyOiB3aGV0aGVyIGB0c1R5cGVgIGFscmVhZHlcbiAqIGFjY2VwdHMgYW4gYXJiaXRyYXJ5IGBjZGt0bi5JUmVzb2x2YWJsZWAgaW4gdGhpcyBwb3NpdGlvbiAoYSBiYXJlXG4gKiBib29sZWFuL2NvbGxlY3Rpb24tb2YtYm9vbGVhbiB0b2tlbiwgYGFueWAsIG9yIGFuIGV4cGxpY2l0XG4gKiBgfCBjZGt0bi5JUmVzb2x2YWJsZWAgdW5pb24gYWxyZWFkeSBwcmVzZW50KS4gTnVsbGFiaWxpdHkgaGFuZGxpbmcgdXNlc1xuICogdGhpcyB0byBkZWNpZGUgd2hldGhlciBpdCBuZWVkcyB0byBhcHBlbmQgYW5vdGhlciBgfCBjZGt0bi5JUmVzb2x2YWJsZWBcbiAqIHNvIGEgY2FsbGVyIGNhbiBwYXNzIGBjZGt0bi5Ub2tlbi5udWxsVmFsdWUoKWAgLSB3aXRob3V0IHJlc29ydGluZyB0b1xuICogcmUtZGVyaXZpbmcgdGhhdCBhbnN3ZXIgd2l0aCBhIHN0cmluZyBzZWFyY2ggb3ZlciBgdHNUeXBlYC5cbiAqL1xuaW50ZXJmYWNlIEludGVybmFsUGFyYW1ldGVyTW9kZWwgZXh0ZW5kcyBQcm92aWRlckZ1bmN0aW9uUGFyYW1ldGVyTW9kZWwge1xuICByZWFkb25seSBhY2NlcHRzUmVzb2x2YWJsZUFscmVhZHk6IGJvb2xlYW47XG59XG5cbi8qKlxuICogQSBzaW5nbGUgcHJvdmlkZXItZGVmaW5lZCBmdW5jdGlvbiwgbWFwcGVkIHRvIGEgc3RhdGljIG1ldGhvZCBvbiB0aGVcbiAqIGdlbmVyYXRlZCBgPFByb3ZpZGVyPlByb3ZpZGVyRnVuY3Rpb25zYCBjbGFzcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQcm92aWRlckZ1bmN0aW9uTW9kZWwge1xuICByZWFkb25seSB0ZXJyYWZvcm1OYW1lOiBzdHJpbmc7XG4gIHJlYWRvbmx5IG1ldGhvZE5hbWU6IHN0cmluZztcbiAgcmVhZG9ubHkgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHN1bW1hcnk/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUZXJyYWZvcm0gKD49MS44KSBkZXByZWNhdGlvbiBtZXNzYWdlIGZvciB0aGUgZnVuY3Rpb24sIHN1cmZhY2VkIGFzIGFuXG4gICAqIGBAZGVwcmVjYXRlZGAgSlNEb2MgdGFnLiBPcGVuVG9mdSBuZXZlciBlbWl0cyB0aGlzIGZpZWxkIC0gc2VlXG4gICAqIGBGdW5jdGlvblNpZ25hdHVyZS5kZXByZWNhdGlvbl9tZXNzYWdlYC5cbiAgICovXG4gIHJlYWRvbmx5IGRlcHJlY2F0aW9uTWVzc2FnZT86IHN0cmluZztcbiAgcmVhZG9ubHkgcmV0dXJuVHNUeXBlOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgYEByZXR1cm5zIHsuLi59YCBKU0RvYyB0eXBlLCBkZXNjcmliaW5nIHRoZSBjb25jZXB0dWFsL1RlcnJhZm9ybVxuICAgKiBzaGFwZSBvZiB0aGUgcmV0dXJuIHZhbHVlIC0gc2VlIGBtYXBSZXR1cm5UeXBlYC4gVGhpcyBkZWxpYmVyYXRlbHkgY2FuXG4gICAqIGRpZmZlciBmcm9tIGByZXR1cm5Uc1R5cGVgIChlLmcuIGEgYGJvb2xgIHJldHVybiBpcyBkZWNsYXJlZFxuICAgKiBgY2RrdG4uSVJlc29sdmFibGVgIGJ1dCBkb2N1bWVudGVkIGFzIGBib29sZWFuIHwgSVJlc29sdmFibGVgKSwgdGhlIHNhbWVcbiAgICogd2F5IGEgcGFyYW1ldGVyJ3MgYGRvY3N0cmluZ1R5cGVgIGNhbiBkaWZmZXIgZnJvbSBpdHMgYHRzVHlwZWAuXG4gICAqL1xuICByZWFkb25seSByZXR1cm5Eb2NzdHJpbmdUeXBlOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBQcm9zZSBhcHBlbmRlZCBhZnRlciB0aGUgYEByZXR1cm5zIHsuLi59YCBicmFjZXMgKGUuZy4gVGVycmFmb3JtXG4gICAqIGxpc3Qvc2V0IHNlbWFudGljcykgLSB0aGUgcmV0dXJuLXNpZGUgY291bnRlcnBhcnQgb2YgYSBwYXJhbWV0ZXInc1xuICAgKiBgZG9jc3RyaW5nTm90ZWAuXG4gICAqL1xuICByZWFkb25seSByZXR1cm5Eb2NzdHJpbmdOb3RlPzogc3RyaW5nO1xuICAvKipcbiAgICogV3JhcHMgdGhlIGBjZGt0bi5UZXJyYWZvcm1Qcm92aWRlckZ1bmN0aW9uLmludm9rZSguLi4pYCBjYWxsIGV4cHJlc3Npb25cbiAgICogaW50byB0aGUgbWV0aG9kJ3MgYHJldHVybmAgc3RhdGVtZW50IChlLmcuIHdyYXBwaW5nIGl0IGluXG4gICAqIGBjZGt0bi5Ub2tlbi5hc1N0cmluZyguLi4pYCwgb3IgcmV0dXJuaW5nIGl0IHVud3JhcHBlZCBmb3IgYGJvb2xgKS5cbiAgICovXG4gIHJlYWRvbmx5IHdyYXBSZXR1cm46IChpbnZva2VFeHByZXNzaW9uOiBzdHJpbmcpID0+IHN0cmluZztcbiAgcmVhZG9ubHkgcGFyYW1ldGVyczogUHJvdmlkZXJGdW5jdGlvblBhcmFtZXRlck1vZGVsW107XG4gIHJlYWRvbmx5IHZhcmlhZGljUGFyYW1ldGVyPzogUHJvdmlkZXJGdW5jdGlvblBhcmFtZXRlck1vZGVsO1xufVxuXG4vKipcbiAqIEFsbCBwcm92aWRlci1kZWZpbmVkIGZ1bmN0aW9ucyBvZiBhIHNpbmdsZSBwcm92aWRlciwgbWFwcGVkIHRvIGEgc2luZ2xlXG4gKiBnZW5lcmF0ZWQgYHByb3ZpZGVycy88cHJvdmlkZXI+L3Byb3ZpZGVyLWZ1bmN0aW9ucy9pbmRleC50c2AgZmlsZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQcm92aWRlckZ1bmN0aW9uc01vZGVsIHtcbiAgcmVhZG9ubHkgcHJvdmlkZXJOYW1lOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGNsYXNzTmFtZTogc3RyaW5nO1xuICByZWFkb25seSBmdW5jdGlvbnM6IFByb3ZpZGVyRnVuY3Rpb25Nb2RlbFtdO1xufVxuXG4vLyBQYXJhbWV0ZXIgbmFtZXMgdGhhdCBjb2xsaWRlIHdpdGggYSByZXNlcnZlZCB3b3JkL2lkZW50aWZpZXIgaW4gb25lIG9mIHRoZVxuLy8ganNpaSB0YXJnZXQgbGFuZ3VhZ2VzLiBUaGlzIGlzIHRoZSBzaWJsaW5nIHRhYmxlIGZvciBwcm92aWRlci1kZWZpbmVkXG4vLyBmdW5jdGlvbnM6IHRvb2xzL2dlbmVyYXRlLWZ1bmN0aW9uLWJpbmRpbmdzL3NjcmlwdHMvZ2VuZXJhdGUudHMgaG9sZHMgdGhlXG4vLyBjYW5vbmljYWwgKGFuZCBzZXBhcmF0ZWx5IG1haW50YWluZWQpIHRhYmxlIGZvciBidWlsdC1pbiBgRm4uKmAgZnVuY3Rpb25zLlxuLy8gVGhlIHR3byBhcmUgaW50ZW50aW9uYWxseSBub3Qgc2hhcmVkIC0gdGhhdCBzY3JpcHQgbGl2ZXMgb3V0c2lkZSB0aGVcbi8vIHBhY2thZ2VzLyBidWlsZCBhbmQgZ2VuZXJhdGVzIGEgZGlmZmVyZW50IGFydGlmYWN0IC0gYnV0IGFueSByZXNlcnZlZCBuYW1lXG4vLyBhZGRlZCB0aGVyZSBzaG91bGQgYmUgY29uc2lkZXJlZCBoZXJlIHRvby5cbmNvbnN0IFJFU0VSVkVEX1BBUkFNRVRFUl9OQU1FUzogeyBbbmFtZTogc3RyaW5nXTogc3RyaW5nIH0gPSB7XG4gIGRlZmF1bHQ6IFwiZGVmYXVsdFZhbHVlXCIsIC8vIHJlc2VydmVkIHdvcmQgaW4gVHlwZVNjcmlwdFxuICBzdHJpbmc6IFwic3RyXCIsIC8vIGNhdXNlcyBpc3N1ZXMgaW4gR29cbn07XG5cbmZ1bmN0aW9uIHNhbml0aXplUGFyYW1ldGVyTmFtZShuYW1lOiBzdHJpbmcpOiBzdHJpbmcge1xuICBjb25zdCBjYW1lbENhc2VkID0gdG9DYW1lbENhc2UobmFtZSk7XG4gIHJldHVybiBSRVNFUlZFRF9QQVJBTUVURVJfTkFNRVNbY2FtZWxDYXNlZF0gPz8gY2FtZWxDYXNlZDtcbn1cblxuZnVuY3Rpb24gc2FuaXRpemVNZXRob2ROYW1lKG5hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIGlmIChuYW1lID09PSBcImxlbmd0aFwiKSByZXR1cm4gXCJsZW5ndGhPZlwiOyAvLyByZXNlcnZlZCBvbiBqc2lpLWdlbmVyYXRlZCBjbGFzc2VzXG4gIHJldHVybiB0b0NhbWVsQ2FzZShuYW1lKTtcbn1cblxuLy8gTWVtYmVycyB0aGF0IGBQcm92aWRlckZ1bmN0aW9uc0VtaXR0ZXJgIChzZWUgYGVtaXR0ZXIvcHJvdmlkZXItZnVuY3Rpb25zLWVtaXR0ZXIudHNgKVxuLy8gaXRzZWxmIHB1dHMgb24gZXZlcnkgZ2VuZXJhdGVkIGA8UHJvdmlkZXI+UHJvdmlkZXJGdW5jdGlvbnNgIHdyYXBwZXIgY2xhc3MsXG4vLyByZWdhcmRsZXNzIG9mIHdoaWNoIGZ1bmN0aW9ucyBhIHByb3ZpZGVyIGRlY2xhcmVzOlxuLy8gICAtIFwiY29uc3RydWN0b3JcIjogdGhlIGNsYXNzJ3Mgb3duIGNvbnN0cnVjdG9yLCB3aGljaCB0YWtlcyB0aGUgcHJvdmlkZXInc1xuLy8gICAgIGBwcm92aWRlckxvY2FsTmFtZWAuIEEgcHJvdmlkZXItZGVmaW5lZCBmdW5jdGlvbiBuYW1lZCBcImNvbnN0cnVjdG9yXCJcbi8vICAgICB3b3VsZCBzYW5pdGl6ZSB0byBhICpzZWNvbmQqIGBjb25zdHJ1Y3RvcmAgbWVtYmVyIG9uIHRoZSBjbGFzcywgd2hpY2hcbi8vICAgICBpcyBpbnZhbGlkIFR5cGVTY3JpcHQuXG4vLyAgIC0gXCJwcm92aWRlckxvY2FsTmFtZVwiOiB0aGUgYHByaXZhdGUgcmVhZG9ubHkgcHJvdmlkZXJMb2NhbE5hbWU6IHN0cmluZ2Bcbi8vICAgICBmaWVsZCB0aGUgY29uc3RydWN0b3IgYXNzaWducyAoc2VlIHRoZSBlbWl0dGVyJ3MgYGVtaXRDbGFzc0hlYWRlcmAvXG4vLyAgICAgY29uc3RydWN0b3IgZW1pc3Npb24pLiBBIHByb3ZpZGVyLWRlZmluZWQgZnVuY3Rpb24gc2FuaXRpemluZyB0byB0aGlzXG4vLyAgICAgbmFtZSB3b3VsZCBjb2xsaWRlIHdpdGggdGhhdCBmaWVsZC5cbi8vIElmIGBQcm92aWRlckZ1bmN0aW9uc0VtaXR0ZXJgIGV2ZXIgZ3Jvd3MgbW9yZSBtZW1iZXJzIG9uIHRoZSB3cmFwcGVyIGNsYXNzLFxuLy8gYWRkIHRoZW0gaGVyZSB0b28uXG5jb25zdCBSRVNFUlZFRF9XUkFQUEVSX01FTUJFUl9OQU1FUyA9IG5ldyBTZXQoW1xuICBcImNvbnN0cnVjdG9yXCIsXG4gIFwicHJvdmlkZXJMb2NhbE5hbWVcIixcbl0pO1xuXG4vKipcbiAqIFJlc3VsdCBvZiBtYXBwaW5nIGEgc2luZ2xlIFRlcnJhZm9ybSBhdHRyaWJ1dGUgdHlwZSBpbnRvIGEganNpaS1zYWZlXG4gKiBwYXJhbWV0ZXIgc2hhcGUgKHNlZSBgbWFwUGFyYW1ldGVyVHlwZWApLlxuICovXG5pbnRlcmZhY2UgTWFwcGVkUGFyYW1ldGVyVHlwZSB7XG4gIHJlYWRvbmx5IHRzVHlwZTogc3RyaW5nO1xuICByZWFkb25seSBkb2NzdHJpbmdUeXBlOiBzdHJpbmc7XG4gIC8qKiBTZWUgYFByb3ZpZGVyRnVuY3Rpb25QYXJhbWV0ZXJNb2RlbC5kb2NzdHJpbmdOb3RlYC4gKi9cbiAgcmVhZG9ubHkgZG9jc3RyaW5nTm90ZT86IHN0cmluZztcbiAgLyoqXG4gICAqIFRydWUgd2hlbiBgdHNUeXBlYCBhbHJlYWR5IGFjY2VwdHMgYW4gYXJiaXRyYXJ5IGBjZGt0bi5JUmVzb2x2YWJsZWAgaW5cbiAgICogdGhpcyBwb3NpdGlvbiB3aXRob3V0IG5lZWRpbmcgYW4gZXh0cmEgYHwgY2RrdG4uSVJlc29sdmFibGVgIHVuaW9uIC1cbiAgICogc2VlIGBJbnRlcm5hbFBhcmFtZXRlck1vZGVsYC5cbiAgICovXG4gIHJlYWRvbmx5IGFjY2VwdHNSZXNvbHZhYmxlQWxyZWFkeTogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBUaGUgYnJhY2tldC1jb21wb3NhYmxlIChcIlRbXVwiLCBubyB0b3AtbGV2ZWwgdW5pb24pIFR5cGVTY3JpcHQvZG9jc3RyaW5nXG4gKiB0eXBlIGZvciBhbiBlbGVtZW50IHRoYXQgY2FuIG5lc3QgaW5zaWRlIGFuIGFycmF5IHdpdGhvdXQgSVRTRUxGIG5lZWRpbmdcbiAqIHRoZSB3aG9sZS1jb2xsZWN0aW9uIHRva2VuIHVuaW9uIGF0IHRoYXQgbGV2ZWw6IGBzdHJpbmdgLCBgbnVtYmVyYCwgb3IgYVxuICogbGlzdC9zZXQgb2Ygb25lIG9mIHRob3NlLCByZWN1cnNpdmVseSAoZS5nLiBgbGlzdChsaXN0KHN0cmluZykpYCBib3R0b21zXG4gKiBvdXQgYXQgYHN0cmluZ2ApLiBSZXR1cm5zIGB1bmRlZmluZWRgIGZvciBhbnl0aGluZyBlbHNlIChgYm9vbGAsIGBtYXBgLFxuICogYG9iamVjdGAsIGBkeW5hbWljYCwgb3IgYSBuZXN0ZWQgY29sbGVjdGlvbiB0aGF0IGRvZXNuJ3QgaXRzZWxmIHF1YWxpZnkpLFxuICogc28gdGhlIGNhbGxlciBmYWxscyBiYWNrIHRvIHdpZGVuaW5nIHRoZSB3aG9sZSBwYXJhbWV0ZXIgdG9cbiAqIGBhbnlbXSB8IGNka3RuLklSZXNvbHZhYmxlYCBpbnN0ZWFkLlxuICovXG5mdW5jdGlvbiBwbGFpbkFycmF5RWxlbWVudFR5cGUoXG4gIHR5cGU6IEF0dHJpYnV0ZVR5cGUsXG4pOiB7IHRzVHlwZTogc3RyaW5nOyBkb2NzdHJpbmdUeXBlOiBzdHJpbmcgfSB8IHVuZGVmaW5lZCB7XG4gIGlmICh0eXBlID09PSBcInN0cmluZ1wiKSByZXR1cm4geyB0c1R5cGU6IFwic3RyaW5nXCIsIGRvY3N0cmluZ1R5cGU6IFwic3RyaW5nXCIgfTtcbiAgaWYgKHR5cGUgPT09IFwibnVtYmVyXCIpIHJldHVybiB7IHRzVHlwZTogXCJudW1iZXJcIiwgZG9jc3RyaW5nVHlwZTogXCJudW1iZXJcIiB9O1xuICBpZiAoQXJyYXkuaXNBcnJheSh0eXBlKSAmJiAodHlwZVswXSA9PT0gXCJsaXN0XCIgfHwgdHlwZVswXSA9PT0gXCJzZXRcIikpIHtcbiAgICBjb25zdCBpbm5lciA9IHBsYWluQXJyYXlFbGVtZW50VHlwZSh0eXBlWzFdKTtcbiAgICBpZiAoIWlubmVyKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHJldHVybiB7XG4gICAgICB0c1R5cGU6IGAke2lubmVyLnRzVHlwZX1bXWAsXG4gICAgICBkb2NzdHJpbmdUeXBlOiBgJHt0eXBlWzBdID09PSBcInNldFwiID8gXCJTZXRcIiA6IFwiQXJyYXlcIn08JHtpbm5lci5kb2NzdHJpbmdUeXBlfT5gLFxuICAgIH07XG4gIH1cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBNYXBzIGEgYGxpc3RgL2BzZXRgIHBhcmFtZXRlciB0byBpdHMganNpaS1zYWZlIHNoYXBlIC0gbWlycm9yc1xuICogYExpc3RBdHRyaWJ1dGVUeXBlTW9kZWxgL2BTZXRBdHRyaWJ1dGVUeXBlTW9kZWwuaW5wdXRUeXBlRGVmaW5pdGlvbmBcbiAqIChib3RoIGlkZW50aWNhbCkgYnJhbmNoIGZvciBicmFuY2gsIHNpbmNlIGpzaWkgcGFyYW1ldGVycywgbGlrZSByZXNvdXJjZVxuICogaW5wdXRzLCBhcmUgYWxsb3dlZCB0byB1bmlvbiBpbiBhIHdob2xlLWNvbGxlY3Rpb24gYGNka3RuLklSZXNvbHZhYmxlYFxuICogdG9rZW4uIGBraW5kYCBvbmx5IGFmZmVjdHMgdGhlIGRvY3VtZW50YXRpb246IHRoZSBkb2NzdHJpbmcgbm90YXRpb25cbiAqIChgQXJyYXk8Li4uPmAgZm9yIGEgVGVycmFmb3JtIGxpc3QsIGBTZXQ8Li4uPmAgZm9yIGEgVGVycmFmb3JtIHNldCxcbiAqIHJlY3Vyc2l2ZWx5IHZpYSBgcGxhaW5BcnJheUVsZW1lbnRUeXBlYC9gbWFwUGFyYW1ldGVyVHlwZWApIHBsdXMsIGZvclxuICogc2V0cywgYSBwcm9zZSBub3RlIC0gdGhlIGpzaWkgdHlwZSBpcyBhbiBhcnJheSBlaXRoZXIgd2F5LCBzbyB0aGUgbm90ZVxuICoga2VlcHMgYSByZWFkZXIgZnJvbSBsaXRlcmFsbHkgcGFzc2luZyBhIEpTIGBTZXRgIGFuZCBmbGFncyB0aGVcbiAqIG9yZGVyaW5nL2R1cGxpY2F0ZS1lbGVtZW50IHNlbWFudGljcyBkaWZmZXJlbmNlLiBUaGUgdHlwZS1sZXZlbCBoYW5kbGluZ1xuICogaXMgaWRlbnRpY2FsIGZvciBib3RoLlxuICovXG5mdW5jdGlvbiBtYXBMaXN0T3JTZXRQYXJhbWV0ZXJUeXBlKFxuICBraW5kOiBcImxpc3RcIiB8IFwic2V0XCIsXG4gIGVsZW1lbnQ6IEF0dHJpYnV0ZVR5cGUsXG4pOiBNYXBwZWRQYXJhbWV0ZXJUeXBlIHtcbiAgY29uc3Qgd3JhcHBlciA9IGtpbmQgPT09IFwic2V0XCIgPyBcIlNldFwiIDogXCJBcnJheVwiO1xuICBjb25zdCBkb2NzdHJpbmdOb3RlID1cbiAgICBraW5kID09PSBcInNldFwiXG4gICAgICA/IFwiVGVycmFmb3JtIHNldDsgb3JkZXJpbmcgaXMgbm90IGd1YXJhbnRlZWQgYW5kIGR1cGxpY2F0ZSB2YWx1ZXMgYXJlIHJlbW92ZWQuXCJcbiAgICAgIDogdW5kZWZpbmVkO1xuXG4gIGlmIChlbGVtZW50ID09PSBcInN0cmluZ1wiKSB7XG4gICAgLy8gTWlycm9ycyB0aGUgZmluYWwgYGVsc2VgIGJyYW5jaDogZW5jb2RlZCBsaXN0IHRva2VucyBhbHJlYWR5IHNhdGlzZnlcbiAgICAvLyBgc3RyaW5nW11gLCBzbyBubyB1bmlvbiBpcyBuZWVkZWQuXG4gICAgcmV0dXJuIHtcbiAgICAgIHRzVHlwZTogXCJzdHJpbmdbXVwiLFxuICAgICAgZG9jc3RyaW5nVHlwZTogYCR7d3JhcHBlcn08c3RyaW5nPmAsXG4gICAgICBkb2NzdHJpbmdOb3RlLFxuICAgICAgYWNjZXB0c1Jlc29sdmFibGVBbHJlYWR5OiBmYWxzZSxcbiAgICB9O1xuICB9XG4gIGlmIChlbGVtZW50ID09PSBcIm51bWJlclwiKSB7XG4gICAgLy8gU2FtZSByZWFzb25pbmcgYXMgYHN0cmluZ2AgYWJvdmUuXG4gICAgcmV0dXJuIHtcbiAgICAgIHRzVHlwZTogXCJudW1iZXJbXVwiLFxuICAgICAgZG9jc3RyaW5nVHlwZTogYCR7d3JhcHBlcn08bnVtYmVyPmAsXG4gICAgICBkb2NzdHJpbmdOb3RlLFxuICAgICAgYWNjZXB0c1Jlc29sdmFibGVBbHJlYWR5OiBmYWxzZSxcbiAgICB9O1xuICB9XG4gIGlmIChlbGVtZW50ID09PSBcImJvb2xcIikge1xuICAgIC8vIE1pcnJvcnMgdGhlIGBlbGVtZW50VHlwZS5zdG9yZWRDbGFzc1R5cGUgPT09IFwiYm9vbGVhblwiYCBicmFuY2g6IGJvb2xcbiAgICAvLyBoYXMgbm8gbG9zc2xlc3MgcGVyLWVsZW1lbnQgdG9rZW4sIGJ1dCB0aGUgV0hPTEUgY29sbGVjdGlvbiBpcyBzdGlsbFxuICAgIC8vIHRva2VuaXphYmxlLCBzbyB0aGUgdW5pb24gaXMgb24gdGhlIG91dHNpZGUuXG4gICAgcmV0dXJuIHtcbiAgICAgIHRzVHlwZTogXCJBcnJheTxib29sZWFuIHwgY2RrdG4uSVJlc29sdmFibGU+IHwgY2RrdG4uSVJlc29sdmFibGVcIixcbiAgICAgIGRvY3N0cmluZ1R5cGU6IGAke3dyYXBwZXJ9PGJvb2xlYW4gfCBJUmVzb2x2YWJsZT5gLFxuICAgICAgZG9jc3RyaW5nTm90ZSxcbiAgICAgIGFjY2VwdHNSZXNvbHZhYmxlQWxyZWFkeTogdHJ1ZSxcbiAgICB9O1xuICB9XG5cbiAgY29uc3QgcGxhaW5FbGVtZW50ID0gcGxhaW5BcnJheUVsZW1lbnRUeXBlKGVsZW1lbnQpO1xuICBpZiAocGxhaW5FbGVtZW50KSB7XG4gICAgLy8gTWlycm9ycyB0aGUgYGVsZW1lbnRUeXBlLnR5cGVNb2RlbFR5cGUgIT09IFwic2ltcGxlXCJgIGJyYW5jaDogYSBuZXN0ZWRcbiAgICAvLyBsaXN0L3NldCB0aGF0IGl0c2VsZiBib3R0b21zIG91dCBhdCBzdHJpbmcvbnVtYmVyIGNvbXBvc2VzIGludG8gYVxuICAgIC8vIHByb3BlciBuZXN0ZWQgYXJyYXkgdHlwZSAoZS5nLiBgbGlzdChsaXN0KHN0cmluZykpYCAtPiBgc3RyaW5nW11bXWApLFxuICAgIC8vIHdpdGggdGhlIHdob2xlLWNvbGxlY3Rpb24gdG9rZW4gYWRkaXRpb25hbGx5IGFjY2VwdGVkIGFsb25nc2lkZSBpdC5cbiAgICByZXR1cm4ge1xuICAgICAgdHNUeXBlOiBgJHtwbGFpbkVsZW1lbnQudHNUeXBlfVtdIHwgY2RrdG4uSVJlc29sdmFibGVgLFxuICAgICAgZG9jc3RyaW5nVHlwZTogYCR7d3JhcHBlcn08JHtwbGFpbkVsZW1lbnQuZG9jc3RyaW5nVHlwZX0+YCxcbiAgICAgIGRvY3N0cmluZ05vdGUsXG4gICAgICBhY2NlcHRzUmVzb2x2YWJsZUFscmVhZHk6IHRydWUsXG4gICAgfTtcbiAgfVxuXG4gIC8vIG1hcC9vYmplY3QvZHluYW1pYyBlbGVtZW50LCBvciBhIG5lc3RlZCBjb2xsZWN0aW9uIHRoYXQgZG9lc24ndCBpdHNlbGZcbiAgLy8gcmVkdWNlIHRvIHN0cmluZy9udW1iZXI6IG5vIGpzaWktc2FmZSBhcnJheS1vZi1YIHR5cGUgZXhpc3RzIC0gd2lkZW5cbiAgLy8gdGhlIHdob2xlIHBhcmFtZXRlciB0byBgYW55W11gLiBVbmxpa2UgYSBiYXJlIGBhbnlgIHBhcmFtZXRlciwgcGxhaW5cbiAgLy8gYGFueVtdYCBkb2VzIE5PVCBzdHJ1Y3R1cmFsbHkgYWNjZXB0IGEgd2hvbGUtY29sbGVjdGlvblxuICAvLyBgY2RrdG4uSVJlc29sdmFibGVgIHRva2VuLCBzbyB0aGUgdW5pb24gaXMgcmVxdWlyZWQgaGVyZSAodGhpcyBpc1xuICAvLyBzdHJpY3RlciB0aGFuIGBNYXBBdHRyaWJ1dGVUeXBlTW9kZWxgL2BMaXN0QXR0cmlidXRlVHlwZU1vZGVsYCBoYXZlIHRvXG4gIC8vIGJlLCBzaW5jZSB0aG9zZSBvbmx5IGV2ZXIgZmFsbCBiYWNrIHRvIGBhbnlbXSB8IGNka3RuLklSZXNvbHZhYmxlYCB2aWFcbiAgLy8gdGhlIHNhbWUgXCJub3Qgc2ltcGxlXCIgYnJhbmNoIGFib3ZlLCB3aGljaCBhbHJlYWR5IGdyYW50cyBpdCkuIEtlZXAgdGhlXG4gIC8vIGRvY3N0cmluZyBob25lc3QgYWJvdXQgdGhlIHJlYWwgZWxlbWVudCBzaGFwZSByYXRoZXIgdGhhbiBqdXN0IHNheWluZ1xuICAvLyBgYW55YC5cbiAgY29uc3QgZWxlbWVudERlc2NyaXB0aW9uID0gbWFwUGFyYW1ldGVyVHlwZShlbGVtZW50KS5kb2NzdHJpbmdUeXBlO1xuICByZXR1cm4ge1xuICAgIHRzVHlwZTogXCJhbnlbXSB8IGNka3RuLklSZXNvbHZhYmxlXCIsXG4gICAgZG9jc3RyaW5nVHlwZTogYCR7d3JhcHBlcn08JHtlbGVtZW50RGVzY3JpcHRpb259PmAsXG4gICAgZG9jc3RyaW5nTm90ZSxcbiAgICBhY2NlcHRzUmVzb2x2YWJsZUFscmVhZHk6IHRydWUsXG4gIH07XG59XG5cbi8qKlxuICogTWFwcyBhIGBtYXBgIHBhcmFtZXRlciB0byBpdHMganNpaS1zYWZlIHNoYXBlIC0gbWlycm9yc1xuICogYE1hcEF0dHJpYnV0ZVR5cGVNb2RlbC5pbnB1dFR5cGVEZWZpbml0aW9uYC4gT25seSB0aGUgYGJvb2xgLWVsZW1lbnQgY2FzZVxuICogaXMgcmVhY2hhYmxlIGZyb20gcmVhbCBwcm92aWRlciBzY2hlbWFzIHRvZGF5IChgc3RyaW5nYC9gbnVtYmVyYCBlbGVtZW50XG4gKiBtYXBzIHN0YXkgYSBwbGFpbiwgbm9uLXVuaW9uIHJlY29yZDsgbmVzdGVkL2NvbXBsZXggbWFwIGVsZW1lbnRzIGFyZW4ndFxuICogZW1pdHRlZCBmb3IgcHJvdmlkZXIgZnVuY3Rpb25zIC0gc2VlIHRoZSBgb2JqZWN0YCBmYWxsYmFjayBpblxuICogYG1hcFBhcmFtZXRlclR5cGVgKSwgYnV0IHRoZSBzaGFwZSBpcyBrZXB0IGJyYW5jaC1mb3ItYnJhbmNoIGFsaWduZWQgd2l0aFxuICogdGhlIG1vZGVsIGl0IG1pcnJvcnMgcmF0aGVyIHRoYW4gY29sbGFwc2VkLlxuICovXG5mdW5jdGlvbiBtYXBNYXBQYXJhbWV0ZXJUeXBlKGVsZW1lbnQ6IEF0dHJpYnV0ZVR5cGUpOiBNYXBwZWRQYXJhbWV0ZXJUeXBlIHtcbiAgaWYgKGVsZW1lbnQgPT09IFwic3RyaW5nXCIpIHtcbiAgICByZXR1cm4ge1xuICAgICAgdHNUeXBlOiBcInsgW2tleTogc3RyaW5nXTogc3RyaW5nIH1cIixcbiAgICAgIGRvY3N0cmluZ1R5cGU6IFwieyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfVwiLFxuICAgICAgYWNjZXB0c1Jlc29sdmFibGVBbHJlYWR5OiBmYWxzZSxcbiAgICB9O1xuICB9XG4gIGlmIChlbGVtZW50ID09PSBcIm51bWJlclwiKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHRzVHlwZTogXCJ7IFtrZXk6IHN0cmluZ106IG51bWJlciB9XCIsXG4gICAgICBkb2NzdHJpbmdUeXBlOiBcInsgW2tleTogc3RyaW5nXTogbnVtYmVyIH1cIixcbiAgICAgIGFjY2VwdHNSZXNvbHZhYmxlQWxyZWFkeTogZmFsc2UsXG4gICAgfTtcbiAgfVxuICBpZiAoZWxlbWVudCA9PT0gXCJib29sXCIpIHtcbiAgICAvLyBNaXJyb3JzIHRoZSBgZWxlbWVudFR5cGUuc3RvcmVkQ2xhc3NUeXBlID09PSBcImJvb2xlYW5cImAgYnJhbmNoOiBtYXBcbiAgICAvLyBvZiBib29sZWFucyBoYXMgUEVSLUVOVFJZIHRva2VuIHN1cHBvcnQsIGJ1dCB0aGUgd2hvbGUgbWFwIGl0c2VsZiBpc1xuICAgIC8vIG5vdCBhZGRpdGlvbmFsbHkgdW5pb25lZCB3aXRoIGBjZGt0bi5JUmVzb2x2YWJsZWAgKHVubGlrZSB0aGUgbGlzdC9zZXRcbiAgICAvLyBjYXNlKSAtIG1hdGNoaW5nIGBNYXBBdHRyaWJ1dGVUeXBlTW9kZWwuaW5wdXRUeXBlRGVmaW5pdGlvbmAgZXhhY3RseS5cbiAgICByZXR1cm4ge1xuICAgICAgdHNUeXBlOiBcInsgW2tleTogc3RyaW5nXTogKGJvb2xlYW4gfCBjZGt0bi5JUmVzb2x2YWJsZSkgfVwiLFxuICAgICAgZG9jc3RyaW5nVHlwZTogXCJ7IFtrZXk6IHN0cmluZ106IChib29sZWFuIHwgSVJlc29sdmFibGUpIH1cIixcbiAgICAgIGFjY2VwdHNSZXNvbHZhYmxlQWxyZWFkeTogZmFsc2UsXG4gICAgfTtcbiAgfVxuICAvLyBtYXAvb2JqZWN0L2R5bmFtaWMgZWxlbWVudDogbm8gc3RydWN0dXJhbCBpbnB1dCBoZWxwZXIgZXhpc3RzIGhlcmUgLVxuICAvLyBzdGF5cyBgYW55YCwgd2hpY2ggKGJlaW5nIGBhbnlgKSBhbHJlYWR5IGFjY2VwdHMgYSB3aG9sZS1tYXBcbiAgLy8gYGNka3RuLklSZXNvbHZhYmxlYCB0b2tlbiB0b28uXG4gIHJldHVybiB7XG4gICAgdHNUeXBlOiBcImFueVwiLFxuICAgIGRvY3N0cmluZ1R5cGU6IFwiYW55XCIsXG4gICAgYWNjZXB0c1Jlc29sdmFibGVBbHJlYWR5OiB0cnVlLFxuICB9O1xufVxuXG4vKipcbiAqIE1hcHMgYSBwcm92aWRlciBmdW5jdGlvbiBwYXJhbWV0ZXIncyBkZWNsYXJlZCBUZXJyYWZvcm0gdHlwZSB0byBhXG4gKiBqc2lpLXNhZmUgVHlwZVNjcmlwdCBwYXJhbWV0ZXIgdHlwZSwgcmVjdXJzaXZlbHkgZm9yIGNvbGxlY3Rpb24gdHlwZXMuXG4gKlxuICogVW5saWtlIHJldHVybiB0eXBlcywganNpaSBhbGxvd3MgdW5pb25zIGluICpwYXJhbWV0ZXIqIHBvc2l0aW9uLCBzb1xuICogYGJvb2xgIGlzIHR5cGVkIGBib29sZWFuIHwgY2RrdG4uSVJlc29sdmFibGVgIChtaXJyb3JpbmdcbiAqIGBTaW1wbGVBdHRyaWJ1dGVUeXBlTW9kZWwuaW5wdXRUeXBlRGVmaW5pdGlvbmAncyBpbnB1dC1zaWRlIGNvbnZlbnRpb24pIC1cbiAqIHRoaXMgYm90aCBhY2NlcHRzIGEgcmVhbCBib29sZWFuIGFuZCBzdGlsbCBhY2NlcHRzIGEgdG9rZW4gaW4gcGxhY2Ugb2ZcbiAqIG9uZS4gYGR5bmFtaWNgIGhhcyBubyBzdHJ1Y3R1cmFsIHR5cGluZyBhbmQgc3RheXMgYGFueWAgKHdoaWNoIGFscmVhZHlcbiAqIGFjY2VwdHMgYW55dGhpbmcsIGluY2x1ZGluZyBhIHRva2VuKTsgYG9iamVjdGAgKHN0cnVjdHVyYWwgaW5wdXQgaGVscGVyc1xuICogYXJlIGRlZmVycmVkIHRvIGEgZm9sbG93LXVwIGlzc3VlKSBzdGF5cyBgYW55YCB0b28uXG4gKlxuICogYGxpc3RgL2BzZXRgIGFuZCBgbWFwYCBkZWxlZ2F0ZSB0byBgbWFwTGlzdE9yU2V0UGFyYW1ldGVyVHlwZWAvXG4gKiBgbWFwTWFwUGFyYW1ldGVyVHlwZWAsIHdoaWNoIG1pcnJvciBgTGlzdEF0dHJpYnV0ZVR5cGVNb2RlbGAvXG4gKiBgU2V0QXR0cmlidXRlVHlwZU1vZGVsYC9gTWFwQXR0cmlidXRlVHlwZU1vZGVsLmlucHV0VHlwZURlZmluaXRpb25gXG4gKiBicmFuY2ggZm9yIGJyYW5jaCAoc2VlIGBhdHRyaWJ1dGUtdHlwZS1tb2RlbC50c2ApIC0gdGhlIHNhbWVcbiAqIHdob2xlLWNvbGxlY3Rpb24tdG9rZW4gY29udmVudGlvbnMgYWxyZWFkeSB1c2VkIGZvciByZXNvdXJjZSBpbnB1dHMuXG4gKi9cbmZ1bmN0aW9uIG1hcFBhcmFtZXRlclR5cGUodHlwZTogQXR0cmlidXRlVHlwZSk6IE1hcHBlZFBhcmFtZXRlclR5cGUge1xuICBpZiAodHlwZSA9PT0gXCJzdHJpbmdcIikge1xuICAgIHJldHVybiB7XG4gICAgICB0c1R5cGU6IFwic3RyaW5nXCIsXG4gICAgICBkb2NzdHJpbmdUeXBlOiBcInN0cmluZ1wiLFxuICAgICAgYWNjZXB0c1Jlc29sdmFibGVBbHJlYWR5OiBmYWxzZSxcbiAgICB9O1xuICB9XG4gIGlmICh0eXBlID09PSBcIm51bWJlclwiKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHRzVHlwZTogXCJudW1iZXJcIixcbiAgICAgIGRvY3N0cmluZ1R5cGU6IFwibnVtYmVyXCIsXG4gICAgICBhY2NlcHRzUmVzb2x2YWJsZUFscmVhZHk6IGZhbHNlLFxuICAgIH07XG4gIH1cbiAgaWYgKHR5cGUgPT09IFwiYm9vbFwiKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHRzVHlwZTogXCJib29sZWFuIHwgY2RrdG4uSVJlc29sdmFibGVcIixcbiAgICAgIGRvY3N0cmluZ1R5cGU6IFwiYm9vbGVhbiB8IElSZXNvbHZhYmxlXCIsXG4gICAgICBhY2NlcHRzUmVzb2x2YWJsZUFscmVhZHk6IHRydWUsXG4gICAgfTtcbiAgfVxuICBpZiAodHlwZSA9PT0gXCJkeW5hbWljXCIpIHtcbiAgICByZXR1cm4ge1xuICAgICAgdHNUeXBlOiBcImFueVwiLFxuICAgICAgZG9jc3RyaW5nVHlwZTogXCJhbnlcIixcbiAgICAgIGFjY2VwdHNSZXNvbHZhYmxlQWxyZWFkeTogdHJ1ZSxcbiAgICB9O1xuICB9XG5cbiAgaWYgKEFycmF5LmlzQXJyYXkodHlwZSkgJiYgKHR5cGVbMF0gPT09IFwibGlzdFwiIHx8IHR5cGVbMF0gPT09IFwic2V0XCIpKSB7XG4gICAgcmV0dXJuIG1hcExpc3RPclNldFBhcmFtZXRlclR5cGUodHlwZVswXSwgdHlwZVsxXSk7XG4gIH1cblxuICBpZiAoQXJyYXkuaXNBcnJheSh0eXBlKSAmJiB0eXBlWzBdID09PSBcIm1hcFwiKSB7XG4gICAgcmV0dXJuIG1hcE1hcFBhcmFtZXRlclR5cGUodHlwZVsxXSk7XG4gIH1cblxuICAvLyBvYmplY3Q6IHN0cnVjdHVyYWwgaW5wdXQgaGVscGVycyBhcmUgZGVmZXJyZWQgdG8gYSBmb2xsb3ctdXAgaXNzdWUuXG4gIHJldHVybiB7XG4gICAgdHNUeXBlOiBcImFueVwiLFxuICAgIGRvY3N0cmluZ1R5cGU6IFwib2JqZWN0XCIsXG4gICAgYWNjZXB0c1Jlc29sdmFibGVBbHJlYWR5OiB0cnVlLFxuICB9O1xufVxuXG5mdW5jdGlvbiBidWlsZFBhcmFtZXRlck1vZGVsKFxuICBwYXJhbWV0ZXI6IEZ1bmN0aW9uUGFyYW1ldGVyLFxuICBmYWxsYmFja05hbWU6IHN0cmluZyxcbik6IEludGVybmFsUGFyYW1ldGVyTW9kZWwge1xuICBjb25zdCB0ZXJyYWZvcm1OYW1lID0gcGFyYW1ldGVyLm5hbWUgPz8gZmFsbGJhY2tOYW1lO1xuICBjb25zdCB7IHRzVHlwZSwgZG9jc3RyaW5nVHlwZSwgZG9jc3RyaW5nTm90ZSwgYWNjZXB0c1Jlc29sdmFibGVBbHJlYWR5IH0gPVxuICAgIG1hcFBhcmFtZXRlclR5cGUocGFyYW1ldGVyLnR5cGUpO1xuICByZXR1cm4ge1xuICAgIHRlcnJhZm9ybU5hbWUsXG4gICAgbmFtZTogc2FuaXRpemVQYXJhbWV0ZXJOYW1lKHRlcnJhZm9ybU5hbWUpLFxuICAgIHRzVHlwZSxcbiAgICBkb2NzdHJpbmdUeXBlLFxuICAgIGRvY3N0cmluZ05vdGUsXG4gICAgZGVzY3JpcHRpb246IHBhcmFtZXRlci5kZXNjcmlwdGlvbixcbiAgICBhY2NlcHRzUmVzb2x2YWJsZUFscmVhZHksXG4gIH07XG59XG5cbi8qKlxuICogV2lkZW5zIGEgbWFwcGVkIHR5cGUncyBgdHNUeXBlYC9gZG9jc3RyaW5nVHlwZWAgdG8gYWxzbyBhY2NlcHQgYW5cbiAqIGV4cGxpY2l0IGBjZGt0bi5Ub2tlbi5udWxsVmFsdWUoKWAgaW4gdGhpcyBwb3NpdGlvbiAtIHVubGVzc1xuICogYGFjY2VwdHNSZXNvbHZhYmxlQWxyZWFkeWAgc2F5cyBpdCBhbHJlYWR5IGRvZXMgKGUuZy4gYSBgYm9vbGAgcGFyYW1ldGVyXG4gKiBpcyBhbHJlYWR5IGBib29sZWFuIHwgY2RrdG4uSVJlc29sdmFibGVgLCBzbyBudWxsYWJpbGl0eSBhZGRzIG5vdGhpbmcgdG9cbiAqIHRoZSB0eXBlIGl0c2VsZiwgb25seSB0byB0aGUgZG9jc3RyaW5nIG5vdGUgYXBwZW5kZWQgYnkgdGhlIGNhbGxlcikuXG4gKi9cbmZ1bmN0aW9uIHdpdGhOdWxsYWJsZVJlc29sdmFibGVVbmlvbihcbiAgbW9kZWw6IFBpY2s8XG4gICAgSW50ZXJuYWxQYXJhbWV0ZXJNb2RlbCxcbiAgICBcInRzVHlwZVwiIHwgXCJkb2NzdHJpbmdUeXBlXCIgfCBcImFjY2VwdHNSZXNvbHZhYmxlQWxyZWFkeVwiXG4gID4sXG4pOiB7IHRzVHlwZTogc3RyaW5nOyBkb2NzdHJpbmdUeXBlOiBzdHJpbmcgfSB7XG4gIGlmIChtb2RlbC5hY2NlcHRzUmVzb2x2YWJsZUFscmVhZHkpIHtcbiAgICByZXR1cm4geyB0c1R5cGU6IG1vZGVsLnRzVHlwZSwgZG9jc3RyaW5nVHlwZTogbW9kZWwuZG9jc3RyaW5nVHlwZSB9O1xuICB9XG4gIHJldHVybiB7XG4gICAgdHNUeXBlOiBgJHttb2RlbC50c1R5cGV9IHwgY2RrdG4uSVJlc29sdmFibGVgLFxuICAgIGRvY3N0cmluZ1R5cGU6IGAke21vZGVsLmRvY3N0cmluZ1R5cGV9IHwgSVJlc29sdmFibGVgLFxuICB9O1xufVxuXG4vKipcbiAqIEFwcGxpZXMgYGlzX251bGxhYmxlYCB0cmFpbGluZy1jb21wYXRpYmlsaXR5IHJ1bGVzIGFjcm9zcyBhIGZ1bmN0aW9uJ3NcbiAqIGZpeGVkIChub24tdmFyaWFkaWMpIHBhcmFtZXRlciBsaXN0LiBUaGlzIG5lZWRzIHRoZSB3aG9sZSBsaXN0IGluIHZpZXdcbiAqIChzZWUgYGJ1aWxkRnVuY3Rpb25Nb2RlbGApLCBzaW5jZSB3aGV0aGVyIGEgbnVsbGFibGUgcGFyYW1ldGVyIGNhbiBiZWNvbWVcbiAqIGpzaWktb3B0aW9uYWwgZGVwZW5kcyBvbiBldmVyeSBwYXJhbWV0ZXIgKmFmdGVyKiBpdCB0b286XG4gKlxuICogLSBBIG51bGxhYmxlIHBhcmFtZXRlciB3aGVyZSBpdCBhbmQgZXZlcnkgbGF0ZXIgZml4ZWQgcGFyYW1ldGVyIGFyZSBhbHNvXG4gKiAgIG51bGxhYmxlIGJlY29tZXMganNpaS1vcHRpb25hbCAoYG5hbWU/OiBUYCk6IG9taXR0aW5nIGl0IGluIFR5cGVTY3JpcHRcbiAqICAgbGVhdmVzIGB1bmRlZmluZWRgIGluIHRoZSBpbnZva2UgYXJncyBhcnJheSwgd2hpY2ggYEZ1bmN0aW9uQ2FsbGBcbiAqICAgYWxyZWFkeSByZW5kZXJzIGFzIHRoZSBUZXJyYWZvcm0gYG51bGxgIGtleXdvcmQuIEl0IGFkZGl0aW9uYWxseSBnYWluc1xuICogICB0aGUgYHwgY2RrdG4uSVJlc29sdmFibGVgIHVuaW9uIChzZWUgYHdpdGhOdWxsYWJsZVJlc29sdmFibGVVbmlvbmApLCBzb1xuICogICBhIGNhbGxlciB3aG8gZG9lcyBzdXBwbHkgdGhlIGFyZ3VtZW50IGNhbiBwYXNzXG4gKiAgIGBjZGt0bi5Ub2tlbi5udWxsVmFsdWUoKWAgZm9yIGFuIGV4cGxpY2l0IFRlcnJhZm9ybSBgbnVsbGAgd2l0aG91dFxuICogICBvbWl0dGluZyB0aGUgcGFyYW1ldGVyLlxuICogLSBBIG51bGxhYmxlIHBhcmFtZXRlciBmb2xsb3dlZCBieSBhIHJlcXVpcmVkIG9uZSBrZWVwcyBpdHMgcG9zaXRpb25cbiAqICAgKGpzaWkgY2FuJ3QgZXhwcmVzcyBcIm9wdGlvbmFsIGJ1dCBub3QgdHJhaWxpbmdcIiksIGFuZCBpbnN0ZWFkIGdhaW5zIHRoZVxuICogICBzYW1lIGB8IGNka3RuLklSZXNvbHZhYmxlYCB1bmlvbiBzbyBhIGNhbGxlciBjYW4gc3RpbGwgcGFzcyBhbiBleHBsaWNpdFxuICogICBgY2RrdG4uVG9rZW4ubnVsbFZhbHVlKClgIChhbiBgSVJlc29sdmFibGVgIHJlc29sdmluZyB0byBgbnVsbGAgLSBzZWVcbiAqICAgYFRva2VuLm51bGxWYWx1ZSgpYC9gVG9rZW4uYXNBbnkoKWApIGluIHRoYXQgZml4ZWQgcG9zaXRpb24gLSBrZWVwaW5nXG4gKiAgIHRoZSBwYXJhbWV0ZXIncyByZWFsIHR5cGUgcmF0aGVyIHRoYW4gZ2l2aW5nIHVwIGFsbCB0eXBlIHNhZmV0eSBieVxuICogICB3aWRlbmluZyBpdCB0byBgYW55YC5cbiAqXG4gKiBCb3RoIGNhc2VzIGRvY3VtZW50IHRoZSByZWFsIG1lY2hhbmlzbSBpbiB0aGUgZG9jc3RyaW5nIG5vdGUgcmF0aGVyIHRoYW5cbiAqIGltcGx5aW5nIHRoZSBwbGFpbiBUeXBlU2NyaXB0IGBudWxsYCBsaXRlcmFsIGlzIGFjY2VwdGVkOiB0aGUgdHJhaWxpbmdcbiAqIGNhc2UgY2FuIGFsc28ganVzdCBiZSBvbWl0dGVkLCB0aGUgbWlkLXBvc2l0aW9uIGNhc2UgY2FuJ3QgYmUgb21pdHRlZCBhdFxuICogYWxsIChqc2lpIGNhbid0IGV4cHJlc3MgXCJvcHRpb25hbCBidXQgbm90IHRyYWlsaW5nXCIpLlxuICovXG5mdW5jdGlvbiBhcHBseU51bGxhYmlsaXR5KFxuICBwYXJhbWV0ZXJzOiBGdW5jdGlvblBhcmFtZXRlcltdLFxuICBtb2RlbHM6IEludGVybmFsUGFyYW1ldGVyTW9kZWxbXSxcbik6IEludGVybmFsUGFyYW1ldGVyTW9kZWxbXSB7XG4gIGNvbnN0IHRyYWlsaW5nQ29tcGF0aWJsZSA9IG5ldyBBcnJheShwYXJhbWV0ZXJzLmxlbmd0aCkuZmlsbChmYWxzZSk7XG4gIGxldCBhbGxOdWxsYWJsZVNvRmFyID0gdHJ1ZTtcbiAgZm9yIChsZXQgaSA9IHBhcmFtZXRlcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBhbGxOdWxsYWJsZVNvRmFyID0gYWxsTnVsbGFibGVTb0ZhciAmJiBwYXJhbWV0ZXJzW2ldLmlzX251bGxhYmxlID09PSB0cnVlO1xuICAgIHRyYWlsaW5nQ29tcGF0aWJsZVtpXSA9IGFsbE51bGxhYmxlU29GYXI7XG4gIH1cblxuICByZXR1cm4gbW9kZWxzLm1hcCgobW9kZWwsIGluZGV4KSA9PiB7XG4gICAgY29uc3QgcGFyYW1ldGVyID0gcGFyYW1ldGVyc1tpbmRleF07XG4gICAgaWYgKCFwYXJhbWV0ZXIuaXNfbnVsbGFibGUpIHJldHVybiBtb2RlbDtcblxuICAgIGNvbnN0IHsgdHNUeXBlLCBkb2NzdHJpbmdUeXBlIH0gPSB3aXRoTnVsbGFibGVSZXNvbHZhYmxlVW5pb24obW9kZWwpO1xuICAgIGNvbnN0IG51bGxhYmlsaXR5Tm90ZSA9IHRyYWlsaW5nQ29tcGF0aWJsZVtpbmRleF1cbiAgICAgID8gXCJPbWl0IG9yIHBhc3MgY2RrdG4uVG9rZW4ubnVsbFZhbHVlKCkgdG8gcmVuZGVyIHRoZSBUZXJyYWZvcm0gbnVsbCBrZXl3b3JkLlwiXG4gICAgICA6IFwiUGFzcyBjZGt0bi5Ub2tlbi5udWxsVmFsdWUoKSBmb3IgYW4gZXhwbGljaXQgVGVycmFmb3JtIG51bGwuXCI7XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4ubW9kZWwsXG4gICAgICAuLi4odHJhaWxpbmdDb21wYXRpYmxlW2luZGV4XSA/IHsgb3B0aW9uYWw6IHRydWUgfSA6IHt9KSxcbiAgICAgIHRzVHlwZSxcbiAgICAgIGRvY3N0cmluZ1R5cGUsXG4gICAgICBkb2NzdHJpbmdOb3RlOiBbbW9kZWwuZG9jc3RyaW5nTm90ZSwgbnVsbGFiaWxpdHlOb3RlXVxuICAgICAgICAuZmlsdGVyKEJvb2xlYW4pXG4gICAgICAgIC5qb2luKFwiIFwiKSxcbiAgICB9O1xuICB9KTtcbn1cblxuLyoqXG4gKiBNYXBzIGEgcHJvdmlkZXIgZnVuY3Rpb24ncyBkZWNsYXJlZCByZXR1cm4gdHlwZSB0byB0aGUganNpaS1zYWZlXG4gKiBUeXBlU2NyaXB0IHJldHVybiB0eXBlLCB0aGUgYEByZXR1cm5zYCBKU0RvYyB0eXBlLCBhbmQgdGhlIGV4cHJlc3Npb25cbiAqIHRoYXQgdW53cmFwcyB0aGUgYFRlcnJhZm9ybVByb3ZpZGVyRnVuY3Rpb24uaW52b2tlKC4uLilgIGBJUmVzb2x2YWJsZWBcbiAqIGludG8gaXQuXG4gKlxuICoganNpaSByZXR1cm4gcG9zaXRpb25zIGNhbid0IHVzZSB0aGUgYFQgfCBjZGt0bi5JUmVzb2x2YWJsZWAgdW5pb24gdGhhdFxuICogcGFyYW1ldGVycyBjYW4gKHNlZSBgbWFwUGFyYW1ldGVyVHlwZWApLCBzbyBldmVyeSBzaGFwZSB0aGF0IGNhbid0IGJlXG4gKiBsb3NzbGVzc2x5IHVud3JhcHBlZCB0aHJvdWdoIGFuIGBhc1h4eGAgVG9rZW4gaGVscGVyIGZhbGxzIGJhY2sgdG8gdGhlXG4gKiBwbGFpbiBgY2RrdG4uSVJlc29sdmFibGVgIHByb2R1Y2VkIGJ5IGBpbnZva2UoKWAgaXRzZWxmLCB1bndyYXBwZWQuXG4gKiBQcm92aWRlciBmdW5jdGlvbnMgZnJlcXVlbnRseSByZXR1cm4gb2JqZWN0cyAoZS5nLiBldmVyeSBmdW5jdGlvbiBpbiB0aGVcbiAqIGB0aW1lYCBwcm92aWRlciksIHNvIC0gdW5saWtlIGJ1aWx0LWluIGBGbi4qYCBmdW5jdGlvbnMgLSB0aGUgb2JqZWN0IGNhc2VcbiAqIGlzIGEgcHJpbWFyeSBwYXRoLCBub3QgYW4gZXJyb3I6IGl0IGlzIHRyZWF0ZWQgdGhlIHNhbWUgYXNcbiAqIGBkeW5hbWljYC9hIGBsaXN0YC9gc2V0YCBvZiBhbnl0aGluZyBvdGhlciB0aGFuIGBzdHJpbmdgL2BudW1iZXJgIChub1xuICogYGFzQW55TGlzdGAgVG9rZW4gaGVscGVyIGV4aXN0cyksIGFuZCByZXR1cm5lZCBhcyB0aGUgUkFXIGBpbnZva2UoKWBcbiAqIHJlc3VsdC4gYG1hcGAgcmV0dXJucywgdW5saWtlIHRob3NlLCBETyBoYXZlIGEgZnVsbCBzZXQgb2YgdHlwZWQgVG9rZW5cbiAqIGhlbHBlcnMgKGBhc1N0cmluZ01hcGAvYGFzTnVtYmVyTWFwYC9gYXNCb29sZWFuTWFwYC9gYXNBbnlNYXBgKSwgc28gZXZlcnlcbiAqIGBtYXBgIHNoYXBlIGdldHMgYW4gYWN0dWFsIHR5cGVkIHJlY29yZCByZXR1cm4gaW5zdGVhZCBvZiBmYWxsaW5nIGJhY2sgdG9cbiAqIGBjZGt0bi5JUmVzb2x2YWJsZWAuXG4gKlxuICogV2hlbmV2ZXIgdGhlIGRlY2xhcmVkIHJldHVybiB0eXBlIElTIGBjZGt0bi5JUmVzb2x2YWJsZWAgKG5vdCBgYW55YCk6XG4gKiB1bmxpa2UgYGhlbHBlcnMudHNgIGBhc0FueWAsIHRoaXMgbXVzdCBOT1QgZ28gdGhyb3VnaFxuICogYGNka3RuLlRva2VuLmFzU3RyaW5nKC4uLilgIC0gYFRva2VuLmFzU3RyaW5nKClgIHByb2R1Y2VzIGFuIGVuY29kZWRcbiAqIHN0cmluZyB0b2tlbiB0aGF0IGBUb2tlbml6YXRpb24uaXNSZXNvbHZhYmxlKClgIGRvZXMgbm90IHJlY29nbml6ZSwgc29cbiAqIGdlbmVyYXRlZCBzdHJ1Y3Qgc2V0dGVycyAoZS5nLiBhbiBgT3V0cHV0UmVmZXJlbmNlYCBgaW50ZXJuYWxWYWx1ZWApIHRyZWF0XG4gKiBpdCBhcyBhIHBsYWluIG9iamVjdCB3aXRoIG5vIGtub3duIGtleXMgYW5kIHRoZSBhdHRyaWJ1dGUgc2lsZW50bHlcbiAqIHZhbmlzaGVzIGZyb20gc3ludGggb3V0cHV0LiBUaGUgcmF3IGBJUmVzb2x2YWJsZWAgZnJvbSBgaW52b2tlKClgIElTXG4gKiByZWNvZ25pemVkIGJ5IGBUb2tlbml6YXRpb24uaXNSZXNvbHZhYmxlKClgIGFuZCByZXNvbHZlcyBjb3JyZWN0bHkuXG4gKiBEZWNsYXJpbmcgaXQgYXMgYGNka3RuLklSZXNvbHZhYmxlYCBpbnN0ZWFkIG9mIGBhbnlgIGFsc28gZ2l2ZXMgY2FsbGVyc1xuICogcmVhbCB0eXBlIHNhZmV0eTogYGFueWAgbGV0IGEgY2FsbGVyIHdyaXRlIGByZXN1bHQuaG91cnNgIG9uIGEgdG9rZW4gd2l0aFxuICogbm8gY29tcGlsZS10aW1lIGZlZWRiYWNrLCBzaWxlbnRseSBwcm9kdWNpbmcgYHVuZGVmaW5lZGAgYXQgcnVudGltZTtcbiAqIGBJUmVzb2x2YWJsZWAgaGFzIG5vIHN1Y2ggcHJvcGVydHkgYW5kIGZvcmNlcyB0aGUgY2FsbGVyIHRocm91Z2hcbiAqIGBjZGt0bi5Ub2tlbmAvdGhlIHByb3ZpZGVyJ3Mgc3RydWN0IHR5cGVzIGluc3RlYWQuIGBpbnZva2UoKWAgYWxyZWFkeVxuICogcmV0dXJucyBgSVJlc29sdmFibGVgLCBzbyBubyBjYXN0IGlzIG5lZWRlZCB0byByZXR1cm4gaXQgYXNcbiAqIGBjZGt0bi5JUmVzb2x2YWJsZWAuXG4gKi9cbmZ1bmN0aW9uIG1hcFJldHVyblR5cGUocmV0dXJuVHlwZTogQXR0cmlidXRlVHlwZSk6IHtcbiAgdHNUeXBlOiBzdHJpbmc7XG4gIGRvY3N0cmluZ1R5cGU6IHN0cmluZztcbiAgZG9jc3RyaW5nTm90ZT86IHN0cmluZztcbiAgd3JhcFJldHVybjogKGludm9rZUV4cHJlc3Npb246IHN0cmluZykgPT4gc3RyaW5nO1xufSB7XG4gIGlmIChyZXR1cm5UeXBlID09PSBcInN0cmluZ1wiKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHRzVHlwZTogXCJzdHJpbmdcIixcbiAgICAgIGRvY3N0cmluZ1R5cGU6IFwic3RyaW5nXCIsXG4gICAgICB3cmFwUmV0dXJuOiAoZXhwcikgPT4gYGNka3RuLlRva2VuLmFzU3RyaW5nKCR7ZXhwcn0pYCxcbiAgICB9O1xuICB9XG4gIGlmIChyZXR1cm5UeXBlID09PSBcIm51bWJlclwiKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHRzVHlwZTogXCJudW1iZXJcIixcbiAgICAgIGRvY3N0cmluZ1R5cGU6IFwibnVtYmVyXCIsXG4gICAgICB3cmFwUmV0dXJuOiAoZXhwcikgPT4gYGNka3RuLlRva2VuLmFzTnVtYmVyKCR7ZXhwcn0pYCxcbiAgICB9O1xuICB9XG4gIGlmIChyZXR1cm5UeXBlID09PSBcImJvb2xcIikge1xuICAgIC8vIEJvb2xlYW5zIGNhbid0IGJlIHJlcHJlc2VudGVkIGFzIHRva2VucyAoc2VlIGhlbHBlcnMudHMgYXNCb29sZWFuKTpcbiAgICAvLyByZXR1cm4gdGhlIElSZXNvbHZhYmxlIHByb2R1Y2VkIGJ5IGludm9rZSgpIHVud3JhcHBlZC4gVGhlIGRvY3N0cmluZ1xuICAgIC8vIHN0aWxsIGRvY3VtZW50cyB0aGUgcmVhbCBjb25jZXB0dWFsIHNoYXBlLlxuICAgIHJldHVybiB7XG4gICAgICB0c1R5cGU6IFwiY2RrdG4uSVJlc29sdmFibGVcIixcbiAgICAgIGRvY3N0cmluZ1R5cGU6IFwiYm9vbGVhbiB8IElSZXNvbHZhYmxlXCIsXG4gICAgICB3cmFwUmV0dXJuOiAoZXhwcikgPT4gZXhwcixcbiAgICB9O1xuICB9XG4gIGlmIChyZXR1cm5UeXBlID09PSBcImR5bmFtaWNcIikge1xuICAgIHJldHVybiB7XG4gICAgICB0c1R5cGU6IFwiY2RrdG4uSVJlc29sdmFibGVcIixcbiAgICAgIGRvY3N0cmluZ1R5cGU6IFwiYW55XCIsXG4gICAgICB3cmFwUmV0dXJuOiAoZXhwcikgPT4gZXhwcixcbiAgICB9O1xuICB9XG4gIGlmIChcbiAgICBBcnJheS5pc0FycmF5KHJldHVyblR5cGUpICYmXG4gICAgKHJldHVyblR5cGVbMF0gPT09IFwibGlzdFwiIHx8IHJldHVyblR5cGVbMF0gPT09IFwic2V0XCIpXG4gICkge1xuICAgIC8vIFNhbWUgZG9jdW1lbnRhdGlvbiBjb252ZW50aW9ucyBhcyBgbWFwTGlzdE9yU2V0UGFyYW1ldGVyVHlwZWA6IHRoZVxuICAgIC8vIG5vdGF0aW9uIChgQXJyYXk8Li4uPmAvYFNldDwuLi4+YCkgY2FycmllcyB0aGUgVGVycmFmb3JtIGNvbGxlY3Rpb25cbiAgICAvLyBzdHJ1Y3R1cmUgcmVjdXJzaXZlbHksIGFuZCBvbmx5IHNldHMgZ2V0IGEgcHJvc2Ugbm90ZS5cbiAgICBjb25zdCB3cmFwcGVyID0gcmV0dXJuVHlwZVswXSA9PT0gXCJzZXRcIiA/IFwiU2V0XCIgOiBcIkFycmF5XCI7XG4gICAgY29uc3QgZG9jc3RyaW5nTm90ZSA9XG4gICAgICByZXR1cm5UeXBlWzBdID09PSBcInNldFwiXG4gICAgICAgID8gXCJUZXJyYWZvcm0gc2V0OyBvcmRlcmluZyBpcyBub3QgZ3VhcmFudGVlZCBhbmQgZHVwbGljYXRlIHZhbHVlcyBhcmUgcmVtb3ZlZC5cIlxuICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICBjb25zdCBlbGVtZW50ID0gcmV0dXJuVHlwZVsxXTtcbiAgICBpZiAoZWxlbWVudCA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHNUeXBlOiBcInN0cmluZ1tdXCIsXG4gICAgICAgIGRvY3N0cmluZ1R5cGU6IGAke3dyYXBwZXJ9PHN0cmluZz5gLFxuICAgICAgICBkb2NzdHJpbmdOb3RlLFxuICAgICAgICB3cmFwUmV0dXJuOiAoZXhwcikgPT4gYGNka3RuLlRva2VuLmFzTGlzdCgke2V4cHJ9KWAsXG4gICAgICB9O1xuICAgIH1cbiAgICBpZiAoZWxlbWVudCA9PT0gXCJudW1iZXJcIikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHNUeXBlOiBcIm51bWJlcltdXCIsXG4gICAgICAgIGRvY3N0cmluZ1R5cGU6IGAke3dyYXBwZXJ9PG51bWJlcj5gLFxuICAgICAgICBkb2NzdHJpbmdOb3RlLFxuICAgICAgICB3cmFwUmV0dXJuOiAoZXhwcikgPT4gYGNka3RuLlRva2VuLmFzTnVtYmVyTGlzdCgke2V4cHJ9KWAsXG4gICAgICB9O1xuICAgIH1cbiAgICAvLyBsaXN0L3NldCBvZiBhbnl0aGluZyBlbHNlOiB0aGVyZSBpcyBubyBgYXNBbnlMaXN0YCBUb2tlbiBoZWxwZXIgLVxuICAgIC8vIGZhbGwgYmFjayB0byB0aGUgcmF3IElSZXNvbHZhYmxlLCBzYW1lIHJlYXNvbmluZyBhcyBkeW5hbWljL29iamVjdFxuICAgIC8vIGJlbG93LCBidXQga2VlcCB0aGUgZG9jc3RyaW5nIGhvbmVzdCBhYm91dCB0aGUgcmVhbCBlbGVtZW50IHNoYXBlXG4gICAgLy8gKHJldXNpbmcgbWFwUGFyYW1ldGVyVHlwZSBwdXJlbHkgZm9yIGl0cyBkZXNjcmlwdGl2ZSBkb2NzdHJpbmdUeXBlIC1cbiAgICAvLyBpdHMgdHNUeXBlL2FjY2VwdHNSZXNvbHZhYmxlQWxyZWFkeSBhcmUgaXJyZWxldmFudCBoZXJlKS5cbiAgICByZXR1cm4ge1xuICAgICAgdHNUeXBlOiBcImNka3RuLklSZXNvbHZhYmxlXCIsXG4gICAgICBkb2NzdHJpbmdUeXBlOiBgJHt3cmFwcGVyfTwke21hcFBhcmFtZXRlclR5cGUoZWxlbWVudCkuZG9jc3RyaW5nVHlwZX0+YCxcbiAgICAgIGRvY3N0cmluZ05vdGUsXG4gICAgICB3cmFwUmV0dXJuOiAoZXhwcikgPT4gZXhwcixcbiAgICB9O1xuICB9XG4gIGlmIChBcnJheS5pc0FycmF5KHJldHVyblR5cGUpICYmIHJldHVyblR5cGVbMF0gPT09IFwibWFwXCIpIHtcbiAgICAvLyBVbmxpa2UgbGlzdC9zZXQgYW5kIG9iamVjdC9keW5hbWljLCBldmVyeSBgbWFwYCBzaGFwZSBoYXMgYSBtYXRjaGluZ1xuICAgIC8vIHR5cGVkIFRva2VuIGhlbHBlciAoc2VlIHRva2VuLnRzKSwgc28gaXQgZ2V0cyBhIHJlYWwgdHlwZWQgcmVjb3JkXG4gICAgLy8gcmV0dXJuIGluc3RlYWQgb2YgZmFsbGluZyBiYWNrIHRvIHRoZSByYXcgSVJlc29sdmFibGUuXG4gICAgY29uc3QgZWxlbWVudCA9IHJldHVyblR5cGVbMV07XG4gICAgaWYgKGVsZW1lbnQgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHRzVHlwZTogXCJ7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9XCIsXG4gICAgICAgIGRvY3N0cmluZ1R5cGU6IFwieyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfVwiLFxuICAgICAgICB3cmFwUmV0dXJuOiAoZXhwcikgPT4gYGNka3RuLlRva2VuLmFzU3RyaW5nTWFwKCR7ZXhwcn0pYCxcbiAgICAgIH07XG4gICAgfVxuICAgIGlmIChlbGVtZW50ID09PSBcIm51bWJlclwiKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB0c1R5cGU6IFwieyBba2V5OiBzdHJpbmddOiBudW1iZXIgfVwiLFxuICAgICAgICBkb2NzdHJpbmdUeXBlOiBcInsgW2tleTogc3RyaW5nXTogbnVtYmVyIH1cIixcbiAgICAgICAgd3JhcFJldHVybjogKGV4cHIpID0+IGBjZGt0bi5Ub2tlbi5hc051bWJlck1hcCgke2V4cHJ9KWAsXG4gICAgICB9O1xuICAgIH1cbiAgICBpZiAoZWxlbWVudCA9PT0gXCJib29sXCIpIHtcbiAgICAgIC8vIFRva2VuLmFzQm9vbGVhbk1hcCdzIGRlY2xhcmVkIHJldHVybiB0eXBlIGlzIGB7IFtrZXk6IHN0cmluZ106XG4gICAgICAvLyBib29sZWFuIH1gIChzZWUgdG9rZW4udHMpIC0gdXNlZCB2ZXJiYXRpbSwgbm90IHVuaW9uZWQgd2l0aFxuICAgICAgLy8gSVJlc29sdmFibGU6IHRoZSBtYXAncyBpbmRpdmlkdWFsIGVudHJpZXMgYXJlIHBsYWluIGJvb2xlYW5zIG9uY2VcbiAgICAgIC8vIHVud3JhcHBlZCBieSB0aGUgaGVscGVyLlxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHNUeXBlOiBcInsgW2tleTogc3RyaW5nXTogYm9vbGVhbiB9XCIsXG4gICAgICAgIGRvY3N0cmluZ1R5cGU6IFwieyBba2V5OiBzdHJpbmddOiBib29sZWFuIH1cIixcbiAgICAgICAgd3JhcFJldHVybjogKGV4cHIpID0+IGBjZGt0bi5Ub2tlbi5hc0Jvb2xlYW5NYXAoJHtleHByfSlgLFxuICAgICAgfTtcbiAgICB9XG4gICAgLy8gbWFwIG9mIGFueXRoaW5nIGVsc2UgKG9iamVjdC9keW5hbWljL25lc3RlZCBjb2xsZWN0aW9uKTogYXNBbnlNYXBcbiAgICAvLyBzdGlsbCBnaXZlcyBhIHR5cGVkIChpZiBsb29zZWx5LXR5cGVkKSByZWNvcmQgcmF0aGVyIHRoYW4gZmFsbGluZ1xuICAgIC8vIGJhY2sgdG8gdGhlIHJhdyBJUmVzb2x2YWJsZS5cbiAgICByZXR1cm4ge1xuICAgICAgdHNUeXBlOiBcInsgW2tleTogc3RyaW5nXTogYW55IH1cIixcbiAgICAgIGRvY3N0cmluZ1R5cGU6IFwieyBba2V5OiBzdHJpbmddOiBhbnkgfVwiLFxuICAgICAgd3JhcFJldHVybjogKGV4cHIpID0+IGBjZGt0bi5Ub2tlbi5hc0FueU1hcCgke2V4cHJ9KWAsXG4gICAgfTtcbiAgfVxuICAvLyBvYmplY3Q6IG5vIHN0cnVjdHVyYWwgdHlwaW5nIGZvciBhcmJpdHJhcnkgcHJvdmlkZXIgZnVuY3Rpb24gcmVzdWx0cyAtXG4gIC8vIGRlY2xhcmVkIGFzIGBjZGt0bi5JUmVzb2x2YWJsZWAsIGFuZCByZXR1cm5lZCBhcyB0aGUgcmF3IGBJUmVzb2x2YWJsZWBcbiAgLy8gZnJvbSBpbnZva2UoKSAoTk9UIHdyYXBwZWQgaW4gYGNka3RuLlRva2VuLmFzU3RyaW5nKC4uLilgLCB3aGljaCB3b3VsZFxuICAvLyBtYWtlIHRoZSByZXN1bHQgdW5yZWNvZ25pemFibGUgdG8gYFRva2VuaXphdGlvbi5pc1Jlc29sdmFibGUoKWBcbiAgLy8gZG93bnN0cmVhbSAtIHNlZSB0aGUgbWFwUmV0dXJuVHlwZSBkb2NzdHJpbmcgYWJvdmUpLlxuICByZXR1cm4ge1xuICAgIHRzVHlwZTogXCJjZGt0bi5JUmVzb2x2YWJsZVwiLFxuICAgIGRvY3N0cmluZ1R5cGU6IFwib2JqZWN0XCIsXG4gICAgd3JhcFJldHVybjogKGV4cHIpID0+IGV4cHIsXG4gIH07XG59XG5cbmZ1bmN0aW9uIGJ1aWxkRnVuY3Rpb25Nb2RlbChcbiAgdGVycmFmb3JtTmFtZTogc3RyaW5nLFxuICBzaWduYXR1cmU6IEZ1bmN0aW9uU2lnbmF0dXJlLFxuKTogUHJvdmlkZXJGdW5jdGlvbk1vZGVsIHtcbiAgY29uc3Qge1xuICAgIHRzVHlwZTogcmV0dXJuVHNUeXBlLFxuICAgIGRvY3N0cmluZ1R5cGU6IHJldHVybkRvY3N0cmluZ1R5cGUsXG4gICAgZG9jc3RyaW5nTm90ZTogcmV0dXJuRG9jc3RyaW5nTm90ZSxcbiAgICB3cmFwUmV0dXJuLFxuICB9ID0gbWFwUmV0dXJuVHlwZShzaWduYXR1cmUucmV0dXJuX3R5cGUpO1xuXG4gIGNvbnN0IHJhd1BhcmFtZXRlcnMgPSBzaWduYXR1cmUucGFyYW1ldGVycyA/PyBbXTtcbiAgY29uc3QgcGFyYW1ldGVycyA9IGFwcGx5TnVsbGFiaWxpdHkoXG4gICAgcmF3UGFyYW1ldGVycyxcbiAgICByYXdQYXJhbWV0ZXJzLm1hcCgocGFyYW1ldGVyLCBpbmRleCkgPT5cbiAgICAgIGJ1aWxkUGFyYW1ldGVyTW9kZWwocGFyYW1ldGVyLCBgYXJnJHtpbmRleH1gKSxcbiAgICApLFxuICApO1xuXG4gIGxldCB2YXJpYWRpY1BhcmFtZXRlcjogSW50ZXJuYWxQYXJhbWV0ZXJNb2RlbCB8IHVuZGVmaW5lZDtcbiAgaWYgKHNpZ25hdHVyZS52YXJpYWRpY19wYXJhbWV0ZXIpIHtcbiAgICBjb25zdCBlbGVtZW50TW9kZWwgPSBidWlsZFBhcmFtZXRlck1vZGVsKFxuICAgICAgc2lnbmF0dXJlLnZhcmlhZGljX3BhcmFtZXRlcixcbiAgICAgIFwidmFsdWVzXCIsXG4gICAgKTtcbiAgICBpZiAoc2lnbmF0dXJlLnZhcmlhZGljX3BhcmFtZXRlci5pc19udWxsYWJsZSkge1xuICAgICAgLy8gQSBudWxsYWJsZSB2YXJpYWRpYyBwYXJhbWV0ZXI6IGpzaWkgY2FuJ3QgZXhwcmVzcyBcImVhY2ggaW5kaXZpZHVhbFxuICAgICAgLy8gYXJndW1lbnQgbWF5IGluZGVwZW5kZW50bHkgYmUgbnVsbFwiIG9uIHRoZSBnZW5lcmF0ZWQgYHZhbHVlczpcbiAgICAgIC8vIEFycmF5PFQ+YCBhcnJheSBwYXJhbWV0ZXIgKGl0J3MgYW4gb3JkaW5hcnkgYXJyYXkgcGFyYW1ldGVyLCBub3QgYVxuICAgICAgLy8gdHJ1ZSByZXN0L3NwcmVhZCBwYXJhbWV0ZXIgLSBvbmx5IHRoZSBpbnZva2UoKSBjYWxsIHNpdGUgc3ByZWFkc1xuICAgICAgLy8gaXQpLCBzbyBldmVyeSBlbGVtZW50J3MgdHlwZSBpbnN0ZWFkIHdpZGVucyB0byBhbHNvIGFjY2VwdCBhblxuICAgICAgLy8gZXhwbGljaXQgYGNka3RuLlRva2VuLm51bGxWYWx1ZSgpYCwgdGhlIHNhbWUgd2F5IGEgZml4ZWQgbnVsbGFibGVcbiAgICAgIC8vIHBhcmFtZXRlciBkb2VzIChzZWUgYHdpdGhOdWxsYWJsZVJlc29sdmFibGVVbmlvbmApOyB0aGUgZG9jc3RyaW5nXG4gICAgICAvLyBrZWVwcyB0aGUgaG9uZXN0IHBlci1lbGVtZW50IHR5cGUgcGx1cyB0aGF0IGd1aWRhbmNlIGluIGl0cyBub3RlLlxuICAgICAgY29uc3QgeyB0c1R5cGUsIGRvY3N0cmluZ1R5cGUgfSA9XG4gICAgICAgIHdpdGhOdWxsYWJsZVJlc29sdmFibGVVbmlvbihlbGVtZW50TW9kZWwpO1xuICAgICAgdmFyaWFkaWNQYXJhbWV0ZXIgPSB7XG4gICAgICAgIC4uLmVsZW1lbnRNb2RlbCxcbiAgICAgICAgdHNUeXBlLFxuICAgICAgICBkb2NzdHJpbmdUeXBlOiBgQXJyYXk8JHtkb2NzdHJpbmdUeXBlfT5gLFxuICAgICAgICBkb2NzdHJpbmdOb3RlOiBbXG4gICAgICAgICAgZWxlbWVudE1vZGVsLmRvY3N0cmluZ05vdGUsXG4gICAgICAgICAgXCJQYXNzIGNka3RuLlRva2VuLm51bGxWYWx1ZSgpIGZvciBhbiBleHBsaWNpdCBUZXJyYWZvcm0gbnVsbC5cIixcbiAgICAgICAgXVxuICAgICAgICAgIC5maWx0ZXIoQm9vbGVhbilcbiAgICAgICAgICAuam9pbihcIiBcIiksXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBOb24tbnVsbGFibGU6IHRoZSBkb2NzdHJpbmcgd3JhcHMgdGhlIGVsZW1lbnQncyBkb2NzdHJpbmcgdHlwZSBpblxuICAgICAgLy8gYEFycmF5PC4uLj5gIGhlcmUgKHJhdGhlciB0aGFuIGluIHRoZSBlbWl0dGVyKSwgc28gZXZlcnkgcGFyYW1ldGVyXG4gICAgICAvLyAtIGZpeGVkIG9yIHZhcmlhZGljIC0gY2FuIHNoYXJlIG9uZSBgQHBhcmFtIHtkb2NzdHJpbmdUeXBlfWBcbiAgICAgIC8vIGVtaXNzaW9uIHBhdGguXG4gICAgICB2YXJpYWRpY1BhcmFtZXRlciA9IHtcbiAgICAgICAgLi4uZWxlbWVudE1vZGVsLFxuICAgICAgICBkb2NzdHJpbmdUeXBlOiBgQXJyYXk8JHtlbGVtZW50TW9kZWwuZG9jc3RyaW5nVHlwZX0+YCxcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICB0ZXJyYWZvcm1OYW1lLFxuICAgIG1ldGhvZE5hbWU6IHNhbml0aXplTWV0aG9kTmFtZSh0ZXJyYWZvcm1OYW1lKSxcbiAgICBkZXNjcmlwdGlvbjogc2lnbmF0dXJlLmRlc2NyaXB0aW9uLFxuICAgIHN1bW1hcnk6IHNpZ25hdHVyZS5zdW1tYXJ5LFxuICAgIGRlcHJlY2F0aW9uTWVzc2FnZTogc2lnbmF0dXJlLmRlcHJlY2F0aW9uX21lc3NhZ2UsXG4gICAgcmV0dXJuVHNUeXBlLFxuICAgIHJldHVybkRvY3N0cmluZ1R5cGUsXG4gICAgcmV0dXJuRG9jc3RyaW5nTm90ZSxcbiAgICB3cmFwUmV0dXJuLFxuICAgIHBhcmFtZXRlcnMsXG4gICAgdmFyaWFkaWNQYXJhbWV0ZXIsXG4gIH07XG59XG5cbi8qKlxuICogVGhyb3dzIGlmIHR3byBmdW5jdGlvbnMgaW4gdGhlIHNhbWUgcHJvdmlkZXIgc2FuaXRpemUgdG8gdGhlIHNhbWVcbiAqIGdlbmVyYXRlZCBtZXRob2QgbmFtZS4gVGVycmFmb3JtIGZ1bmN0aW9uIG5hbWVzIGFyZSB1bmlxdWUsIGJ1dFxuICogYHNhbml0aXplTWV0aG9kTmFtZWAgKGNhbWVsQ2FzaW5nLCBgbGVuZ3RoYCAtPiBgbGVuZ3RoT2ZgKSBpcyBub3RcbiAqIG5lY2Vzc2FyaWx5IGluamVjdGl2ZSwgc28gYSByZWFsIC0gaWYgdW5saWtlbHkgLSBwcm92aWRlciBzY2hlbWEgY291bGRcbiAqIHN0aWxsIHByb2R1Y2UgYSBkdXBsaWNhdGUgbWV0aG9kLiBHZW5lcmF0aW9uIGlzIGFib3J0ZWQgcmF0aGVyIHRoYW5cbiAqIHNpbGVudGx5IGVtaXR0aW5nIG9uZSBtZXRob2QgdGhhdCBzaGFkb3dzIHRoZSBvdGhlci5cbiAqL1xuZnVuY3Rpb24gYXNzZXJ0Tm9NZXRob2ROYW1lQ29sbGlzaW9ucyhcbiAgcHJvdmlkZXJOYW1lOiBzdHJpbmcsXG4gIGZ1bmN0aW9uczogUHJvdmlkZXJGdW5jdGlvbk1vZGVsW10sXG4pOiB2b2lkIHtcbiAgY29uc3Qgc2VlbkJ5ID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZz4oKTsgLy8gbWV0aG9kTmFtZSAtPiB0ZXJyYWZvcm1OYW1lXG5cbiAgZm9yIChjb25zdCBmbiBvZiBmdW5jdGlvbnMpIHtcbiAgICBjb25zdCBleGlzdGluZ1RlcnJhZm9ybU5hbWUgPSBzZWVuQnkuZ2V0KGZuLm1ldGhvZE5hbWUpO1xuICAgIGlmIChleGlzdGluZ1RlcnJhZm9ybU5hbWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgUHJvdmlkZXIgXCIke3Byb3ZpZGVyTmFtZX1cIiBkZWNsYXJlcyB0d28gcHJvdmlkZXItZGVmaW5lZCBmdW5jdGlvbnMsIGAgK1xuICAgICAgICAgIGBcIiR7ZXhpc3RpbmdUZXJyYWZvcm1OYW1lfVwiIGFuZCBcIiR7Zm4udGVycmFmb3JtTmFtZX1cIiwgdGhhdCBib3RoIGAgK1xuICAgICAgICAgIGBzYW5pdGl6ZSB0byB0aGUgZ2VuZXJhdGVkIG1ldGhvZCBuYW1lIFwiJHtmbi5tZXRob2ROYW1lfVwiLiBgICtcbiAgICAgICAgICBgR2VuZXJhdGlvbiBhYm9ydGVkIHRvIGF2b2lkIHNpbGVudGx5IG92ZXJ3cml0aW5nIG9uZSBtZXRob2Qgd2l0aCBgICtcbiAgICAgICAgICBgdGhlIG90aGVyIC0gcGxlYXNlIHJlcG9ydCB0aGlzIGFzIGFuIGlzc3VlLmAsXG4gICAgICApO1xuICAgIH1cbiAgICBzZWVuQnkuc2V0KGZuLm1ldGhvZE5hbWUsIGZuLnRlcnJhZm9ybU5hbWUpO1xuICB9XG59XG5cbi8qKlxuICogVGhyb3dzIGlmIGEgZnVuY3Rpb24ncyBzYW5pdGl6ZWQgYG1ldGhvZE5hbWVgIGxhbmRzIG9uIGEgbWVtYmVyIG5hbWVcbiAqIGBQcm92aWRlckZ1bmN0aW9uc0VtaXR0ZXJgIGFscmVhZHkgcHV0cyBvbiBldmVyeSB3cmFwcGVyIGNsYXNzIChzZWVcbiAqIGBSRVNFUlZFRF9XUkFQUEVSX01FTUJFUl9OQU1FU2ApLiBVbmxpa2UgYGFzc2VydE5vTWV0aG9kTmFtZUNvbGxpc2lvbnNgLFxuICogd2hpY2ggb25seSBjYXRjaGVzIHR3byAqZnVuY3Rpb25zKiBjb2xsaWRpbmcgd2l0aCBlYWNoIG90aGVyLCB0aGlzIGNhdGNoZXNcbiAqIGEgc2luZ2xlIGZ1bmN0aW9uIGNvbGxpZGluZyB3aXRoIHRoZSB3cmFwcGVyIGNsYXNzIGl0c2VsZiAtIGUuZy4gYVxuICogVGVycmFmb3JtIGZ1bmN0aW9uIGxpdGVyYWxseSBuYW1lZCBcImNvbnN0cnVjdG9yXCIsIG9yIFwicHJvdmlkZXJfbG9jYWxfbmFtZVwiXG4gKiBjYW1lbENhc2luZyB0byBcInByb3ZpZGVyTG9jYWxOYW1lXCIuXG4gKlxuICogVGhpcyBpbnRlbnRpb25hbGx5IGRvZXMgTk9UIGFsc28gY2hlY2sgc2FuaXRpemVkICpwYXJhbWV0ZXIqIG5hbWVzIGFnYWluc3RcbiAqIFwicHJvdmlkZXJMb2NhbE5hbWVcIjogcGFyYW1ldGVycyBhcmUgZGVjbGFyZWQgaW4gdGhlIGdlbmVyYXRlZCBtZXRob2QncyBvd25cbiAqIHNjb3BlLCBub3QgdGhlIGNsYXNzJ3MsIHNvIGEgcGFyYW1ldGVyIG5hbWVkIGBwcm92aWRlckxvY2FsTmFtZWAgc2hhZG93c1xuICogdGhlIGNsYXNzIGZpZWxkIHdpdGhpbiB0aGF0IG1ldGhvZCBib2R5IHdpdGhvdXQgY29sbGlkaW5nIHdpdGggaXQgKHZhbGlkLFxuICogaWYgY29uZnVzaW5nLCBUeXBlU2NyaXB0KSAtIHRoZXJlIGlzIG5vdGhpbmcgdG8gYWJvcnQgZ2VuZXJhdGlvbiBvdmVyLlxuICovXG5mdW5jdGlvbiBhc3NlcnROb1Jlc2VydmVkV3JhcHBlck1lbWJlckNvbGxpc2lvbnMoXG4gIHByb3ZpZGVyTmFtZTogc3RyaW5nLFxuICBmdW5jdGlvbnM6IFByb3ZpZGVyRnVuY3Rpb25Nb2RlbFtdLFxuKTogdm9pZCB7XG4gIGZvciAoY29uc3QgZm4gb2YgZnVuY3Rpb25zKSB7XG4gICAgaWYgKFJFU0VSVkVEX1dSQVBQRVJfTUVNQkVSX05BTUVTLmhhcyhmbi5tZXRob2ROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgUHJvdmlkZXIgXCIke3Byb3ZpZGVyTmFtZX1cIiBkZWNsYXJlcyBhIHByb3ZpZGVyLWRlZmluZWQgZnVuY3Rpb24gYCArXG4gICAgICAgICAgYFwiJHtmbi50ZXJyYWZvcm1OYW1lfVwiIHRoYXQgc2FuaXRpemVzIHRvIHRoZSBnZW5lcmF0ZWQgbWV0aG9kIG5hbWUgYCArXG4gICAgICAgICAgYFwiJHtmbi5tZXRob2ROYW1lfVwiLCB3aGljaCBjb2xsaWRlcyB3aXRoIGEgbWVtYmVyIHRoYXQgYCArXG4gICAgICAgICAgYFByb3ZpZGVyRnVuY3Rpb25zRW1pdHRlciBhbHJlYWR5IHB1dHMgb24gZXZlcnkgYCArXG4gICAgICAgICAgYFwiPFByb3ZpZGVyPlByb3ZpZGVyRnVuY3Rpb25zXCIgd3JhcHBlciBjbGFzcyAodGhlIGNsYXNzIGAgK1xuICAgICAgICAgIGBjb25zdHJ1Y3Rvciwgb3IgaXRzIFwicHJvdmlkZXJMb2NhbE5hbWVcIiBmaWVsZCkuIEdlbmVyYXRpb24gYCArXG4gICAgICAgICAgYGFib3J0ZWQgdG8gYXZvaWQgZW1pdHRpbmcgaW52YWxpZCBUeXBlU2NyaXB0IG9yIHNpbGVudGx5IGAgK1xuICAgICAgICAgIGBzaGFkb3dpbmcgdGhhdCBtZW1iZXIgLSBwbGVhc2UgcmVwb3J0IHRoaXMgYXMgYW4gaXNzdWUuYCxcbiAgICAgICk7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogVGhyb3dzIGlmIHR3byBwYXJhbWV0ZXJzIG9mIHRoZSBzYW1lIGZ1bmN0aW9uIChpbmNsdWRpbmcgdGhlIHZhcmlhZGljXG4gKiBwYXJhbWV0ZXIpIHNhbml0aXplIHRvIHRoZSBzYW1lIGdlbmVyYXRlZCBwYXJhbWV0ZXIgbmFtZSwgZm9yIHRoZSBzYW1lXG4gKiByZWFzb24gYXMgYGFzc2VydE5vTWV0aG9kTmFtZUNvbGxpc2lvbnNgIGFib3ZlIGJ1dCBhdCB0aGUgcGFyYW1ldGVyIGxldmVsLlxuICovXG5mdW5jdGlvbiBhc3NlcnROb1BhcmFtZXRlck5hbWVDb2xsaXNpb25zKFxuICBwcm92aWRlck5hbWU6IHN0cmluZyxcbiAgZm46IFByb3ZpZGVyRnVuY3Rpb25Nb2RlbCxcbik6IHZvaWQge1xuICBjb25zdCBzZWVuQnkgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpOyAvLyBzYW5pdGl6ZWQgbmFtZSAtPiB0ZXJyYWZvcm1OYW1lXG4gIGNvbnN0IGFsbFBhcmFtZXRlcnMgPSBmbi52YXJpYWRpY1BhcmFtZXRlclxuICAgID8gWy4uLmZuLnBhcmFtZXRlcnMsIGZuLnZhcmlhZGljUGFyYW1ldGVyXVxuICAgIDogZm4ucGFyYW1ldGVycztcblxuICBmb3IgKGNvbnN0IHBhcmFtIG9mIGFsbFBhcmFtZXRlcnMpIHtcbiAgICBjb25zdCBleGlzdGluZ1RlcnJhZm9ybU5hbWUgPSBzZWVuQnkuZ2V0KHBhcmFtLm5hbWUpO1xuICAgIGlmIChleGlzdGluZ1RlcnJhZm9ybU5hbWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgUHJvdmlkZXIgXCIke3Byb3ZpZGVyTmFtZX1cIiBmdW5jdGlvbiBcIiR7Zm4udGVycmFmb3JtTmFtZX1cIiBkZWNsYXJlcyBgICtcbiAgICAgICAgICBgdHdvIHBhcmFtZXRlcnMsIFwiJHtleGlzdGluZ1RlcnJhZm9ybU5hbWV9XCIgYW5kIGAgK1xuICAgICAgICAgIGBcIiR7cGFyYW0udGVycmFmb3JtTmFtZX1cIiwgdGhhdCBib3RoIHNhbml0aXplIHRvIHRoZSBnZW5lcmF0ZWQgYCArXG4gICAgICAgICAgYHBhcmFtZXRlciBuYW1lIFwiJHtwYXJhbS5uYW1lfVwiLiBHZW5lcmF0aW9uIGFib3J0ZWQgdG8gYXZvaWQgYCArXG4gICAgICAgICAgYHNpbGVudGx5IGRyb3BwaW5nIG9uZSBwYXJhbWV0ZXIgLSBwbGVhc2UgcmVwb3J0IHRoaXMgYXMgYW4gaXNzdWUuYCxcbiAgICAgICk7XG4gICAgfVxuICAgIHNlZW5CeS5zZXQocGFyYW0ubmFtZSwgcGFyYW0udGVycmFmb3JtTmFtZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBUaHJvd3MgaWYgdGhlIHByb3ZpZGVyJ3Mgb3duIGNvbmZpZyBzY2hlbWEgZGVjbGFyZXMgYW4gYXR0cmlidXRlIHdob3NlXG4gKiBnZW5lcmF0ZWQgcHJvcGVydHkgbmFtZSAoc2VlIGBBdHRyaWJ1dGVNb2RlbC5uYW1lYCAvXG4gKiBgZXNjYXBlQXR0cmlidXRlTmFtZWApIGlzIGV4YWN0bHkgXCJmdW5jdGlvbnNcIiwgd2hpbGUgdGhlIHByb3ZpZGVyIGFsc29cbiAqIGRlY2xhcmVzIHByb3ZpZGVyLWRlZmluZWQgZnVuY3Rpb25zLiBUaGF0IGNvbWJpbmF0aW9uIHdvdWxkIGNvbGxpZGUgd2l0aFxuICogdGhlIG1lbW9pemVkIGBmdW5jdGlvbnNgIGdldHRlciBgUmVzb3VyY2VFbWl0dGVyYCBlbWl0cyBvbiB0aGUgcHJvdmlkZXJcbiAqIGNsYXNzIChzZWUgYHJlc291cmNlLWVtaXR0ZXIudHNgJ3MgYGVtaXRGdW5jdGlvbnNHZXR0ZXJgKSAtIG9uZSB3b3VsZFxuICogc2lsZW50bHkgc2hhZG93IHRoZSBvdGhlci4gU2FtZSBsb3VkLWZhaWx1cmUgY29udmVudGlvbiBhc1xuICogYGFzc2VydE5vTWV0aG9kTmFtZUNvbGxpc2lvbnNgL2Bhc3NlcnROb1BhcmFtZXRlck5hbWVDb2xsaXNpb25zYCBhYm92ZTpcbiAqIGdlbmVyYXRpb24gaXMgYWJvcnRlZCByYXRoZXIgdGhhbiBzaWxlbnRseSBwaWNraW5nIGEgd2lubmVyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYXNzZXJ0Tm9GdW5jdGlvbnNHZXR0ZXJDb2xsaXNpb24oXG4gIHByb3ZpZGVyTmFtZTogc3RyaW5nLFxuICBhdHRyaWJ1dGVOYW1lczogc3RyaW5nW10sXG4pOiB2b2lkIHtcbiAgaWYgKGF0dHJpYnV0ZU5hbWVzLmluY2x1ZGVzKFwiZnVuY3Rpb25zXCIpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYFByb3ZpZGVyIFwiJHtwcm92aWRlck5hbWV9XCIgZGVjbGFyZXMgcHJvdmlkZXItZGVmaW5lZCBmdW5jdGlvbnMgYW5kIGl0cyBgICtcbiAgICAgICAgYG93biBjb25maWcgc2NoZW1hIGFsc28gaGFzIGFuIGF0dHJpYnV0ZSB0aGF0IGdlbmVyYXRlcyB0aGUgcHJvcGVydHkgYCArXG4gICAgICAgIGBuYW1lIFwiZnVuY3Rpb25zXCIgb24gdGhlIHByb3ZpZGVyIGNsYXNzLiBUaGlzIGNvbGxpZGVzIHdpdGggdGhlIGAgK1xuICAgICAgICBgZ2VuZXJhdGVkIFwiZnVuY3Rpb25zXCIgZ2V0dGVyIHVzZWQgdG8gaW52b2tlIHByb3ZpZGVyLWRlZmluZWQgYCArXG4gICAgICAgIGBmdW5jdGlvbnMuIEdlbmVyYXRpb24gYWJvcnRlZCB0byBhdm9pZCBzaWxlbnRseSBzaGFkb3dpbmcgb25lIHdpdGggYCArXG4gICAgICAgIGB0aGUgb3RoZXIgLSBwbGVhc2UgcmVwb3J0IHRoaXMgYXMgYW4gaXNzdWUuYCxcbiAgICApO1xuICB9XG59XG5cbi8qKlxuICogQnVpbGRzIHRoZSBtb2RlbCBmb3IgYSBwcm92aWRlcidzIGBwcm92aWRlci1mdW5jdGlvbnMvaW5kZXgudHNgIGZpbGUgZnJvbVxuICogaXRzIHByb3ZpZGVyIHNjaGVtYSBgZnVuY3Rpb25zYCBtYXAuIFJldHVybnMgYHVuZGVmaW5lZGAgd2hlbiB0aGUgcHJvdmlkZXJcbiAqIGRlY2xhcmVzIG5vIGZ1bmN0aW9ucyAtIGNhbGxlcnMgc2hvdWxkIHNraXAgZW1pdHRpbmcgdGhlIGZpbGUgZW50aXJlbHkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidWlsZFByb3ZpZGVyRnVuY3Rpb25zTW9kZWwoXG4gIHByb3ZpZGVyTmFtZTogc3RyaW5nLFxuICBmdW5jdGlvbnM6IHsgW25hbWU6IHN0cmluZ106IEZ1bmN0aW9uU2lnbmF0dXJlIH0gfCB1bmRlZmluZWQsXG4pOiBQcm92aWRlckZ1bmN0aW9uc01vZGVsIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgZW50cmllcyA9IE9iamVjdC5lbnRyaWVzKGZ1bmN0aW9ucyA/PyB7fSk7XG4gIGlmIChlbnRyaWVzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIHVuZGVmaW5lZDtcblxuICBjb25zdCBtYXBwZWRGdW5jdGlvbnMgPSBlbnRyaWVzXG4gICAgLnNvcnQoKFthXSwgW2JdKSA9PiBhLmxvY2FsZUNvbXBhcmUoYikpXG4gICAgLm1hcCgoW25hbWUsIHNpZ25hdHVyZV0pID0+IGJ1aWxkRnVuY3Rpb25Nb2RlbChuYW1lLCBzaWduYXR1cmUpKTtcblxuICBhc3NlcnROb01ldGhvZE5hbWVDb2xsaXNpb25zKHByb3ZpZGVyTmFtZSwgbWFwcGVkRnVuY3Rpb25zKTtcbiAgYXNzZXJ0Tm9SZXNlcnZlZFdyYXBwZXJNZW1iZXJDb2xsaXNpb25zKHByb3ZpZGVyTmFtZSwgbWFwcGVkRnVuY3Rpb25zKTtcbiAgZm9yIChjb25zdCBmbiBvZiBtYXBwZWRGdW5jdGlvbnMpIHtcbiAgICBhc3NlcnROb1BhcmFtZXRlck5hbWVDb2xsaXNpb25zKHByb3ZpZGVyTmFtZSwgZm4pO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBwcm92aWRlck5hbWUsXG4gICAgY2xhc3NOYW1lOiBgJHt0b1Bhc2NhbENhc2UocHJvdmlkZXJOYW1lKX1Qcm92aWRlckZ1bmN0aW9uc2AsXG4gICAgZnVuY3Rpb25zOiBtYXBwZWRGdW5jdGlvbnMsXG4gIH07XG59XG4iXX0=
|