cdk-common 2.0.30 → 2.0.34

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/.jsii +4 -4
  2. package/lib/main.js +1 -1
  3. package/node_modules/@aws-cdk/assert/LICENSE +1 -1
  4. package/node_modules/@aws-cdk/assert/NOTICE +1 -1
  5. package/node_modules/@aws-cdk/assert/package.json +9 -9
  6. package/node_modules/@aws-cdk/cfnspec/CHANGELOG.md +16 -0
  7. package/node_modules/@aws-cdk/cfnspec/build-tools/build.js +7 -53
  8. package/node_modules/@aws-cdk/cfnspec/build-tools/massage-spec.d.ts +0 -4
  9. package/node_modules/@aws-cdk/cfnspec/build-tools/massage-spec.js +2 -61
  10. package/node_modules/@aws-cdk/cfnspec/build-tools/patch-set.d.ts +25 -0
  11. package/node_modules/@aws-cdk/cfnspec/build-tools/patch-set.js +239 -0
  12. package/node_modules/@aws-cdk/cfnspec/build-tools/report-issues.d.ts +4 -0
  13. package/node_modules/@aws-cdk/cfnspec/build-tools/report-issues.js +44 -0
  14. package/node_modules/@aws-cdk/cfnspec/build-tools/split-spec-by-service.d.ts +1 -0
  15. package/node_modules/@aws-cdk/cfnspec/build-tools/split-spec-by-service.js +86 -0
  16. package/node_modules/@aws-cdk/cfnspec/build-tools/template/LICENSE +1 -1
  17. package/node_modules/@aws-cdk/cfnspec/build-tools/template/NOTICE +1 -1
  18. package/node_modules/@aws-cdk/cfnspec/build-tools/update-metrics.sh +2 -0
  19. package/node_modules/@aws-cdk/cfnspec/build-tools/update.sh +34 -18
  20. package/node_modules/@aws-cdk/cfnspec/build-tools/validate-cfn.d.ts +67 -0
  21. package/node_modules/@aws-cdk/cfnspec/build-tools/validate-cfn.js +285 -0
  22. package/node_modules/@aws-cdk/cfnspec/coverage/build-tools/index.html +49 -20
  23. package/node_modules/@aws-cdk/cfnspec/coverage/build-tools/massage-spec.ts.html +12 -166
  24. package/node_modules/@aws-cdk/cfnspec/coverage/build-tools/patch-set.ts.html +907 -0
  25. package/node_modules/@aws-cdk/cfnspec/coverage/build-tools/scrutiny.ts.html +1 -2
  26. package/node_modules/@aws-cdk/cfnspec/coverage/build-tools/validate-cfn.ts.html +1093 -0
  27. package/node_modules/@aws-cdk/cfnspec/coverage/index.html +34 -35
  28. package/node_modules/@aws-cdk/cfnspec/coverage/junit.xml +6217 -6177
  29. package/node_modules/@aws-cdk/cfnspec/coverage/lcov-report/build-tools/index.html +49 -20
  30. package/node_modules/@aws-cdk/cfnspec/coverage/lcov-report/build-tools/massage-spec.ts.html +12 -166
  31. package/node_modules/@aws-cdk/cfnspec/coverage/lcov-report/build-tools/patch-set.ts.html +907 -0
  32. package/node_modules/@aws-cdk/cfnspec/coverage/lcov-report/build-tools/scrutiny.ts.html +1 -2
  33. package/node_modules/@aws-cdk/cfnspec/coverage/lcov-report/build-tools/validate-cfn.ts.html +1093 -0
  34. package/node_modules/@aws-cdk/cfnspec/coverage/lcov-report/index.html +34 -35
  35. package/node_modules/@aws-cdk/cfnspec/coverage/lcov-report/lib/canned-metrics/canned-metrics-schema.ts.html +2 -3
  36. package/node_modules/@aws-cdk/cfnspec/coverage/lcov-report/lib/canned-metrics/index.html +1 -2
  37. package/node_modules/@aws-cdk/cfnspec/coverage/lcov-report/lib/canned-metrics.ts.html +22 -23
  38. package/node_modules/@aws-cdk/cfnspec/coverage/lcov-report/lib/index.html +19 -20
  39. package/node_modules/@aws-cdk/cfnspec/coverage/lcov-report/lib/index.ts.html +96 -25
  40. package/node_modules/@aws-cdk/cfnspec/coverage/lcov-report/lib/schema/augmentation.ts.html +5 -6
  41. package/node_modules/@aws-cdk/cfnspec/coverage/lcov-report/lib/schema/base-types.ts.html +12 -13
  42. package/node_modules/@aws-cdk/cfnspec/coverage/lcov-report/lib/schema/index.html +7 -8
  43. package/node_modules/@aws-cdk/cfnspec/coverage/lcov-report/lib/schema/index.ts.html +11 -12
  44. package/node_modules/@aws-cdk/cfnspec/coverage/lcov-report/lib/schema/property.ts.html +39 -40
  45. package/node_modules/@aws-cdk/cfnspec/coverage/lcov-report/lib/schema/resource-type.ts.html +20 -21
  46. package/node_modules/@aws-cdk/cfnspec/coverage/lcov-report/lib/schema/specification.ts.html +2 -3
  47. package/node_modules/@aws-cdk/cfnspec/coverage/lcov.info +744 -346
  48. package/node_modules/@aws-cdk/cfnspec/coverage/lib/canned-metrics/canned-metrics-schema.ts.html +2 -3
  49. package/node_modules/@aws-cdk/cfnspec/coverage/lib/canned-metrics/index.html +1 -2
  50. package/node_modules/@aws-cdk/cfnspec/coverage/lib/canned-metrics.ts.html +22 -23
  51. package/node_modules/@aws-cdk/cfnspec/coverage/lib/index.html +19 -20
  52. package/node_modules/@aws-cdk/cfnspec/coverage/lib/index.ts.html +96 -25
  53. package/node_modules/@aws-cdk/cfnspec/coverage/lib/schema/augmentation.ts.html +5 -6
  54. package/node_modules/@aws-cdk/cfnspec/coverage/lib/schema/base-types.ts.html +12 -13
  55. package/node_modules/@aws-cdk/cfnspec/coverage/lib/schema/index.html +7 -8
  56. package/node_modules/@aws-cdk/cfnspec/coverage/lib/schema/index.ts.html +11 -12
  57. package/node_modules/@aws-cdk/cfnspec/coverage/lib/schema/property.ts.html +39 -40
  58. package/node_modules/@aws-cdk/cfnspec/coverage/lib/schema/resource-type.ts.html +20 -21
  59. package/node_modules/@aws-cdk/cfnspec/coverage/lib/schema/specification.ts.html +2 -3
  60. package/node_modules/@aws-cdk/cfnspec/lib/canned-metrics/README.md +6 -1
  61. package/node_modules/@aws-cdk/cfnspec/lib/canned-metrics/services.json +19997 -10215
  62. package/node_modules/@aws-cdk/cfnspec/lib/index.d.ts +8 -0
  63. package/node_modules/@aws-cdk/cfnspec/lib/index.js +25 -2
  64. package/node_modules/@aws-cdk/cfnspec/lib/schema/docs.d.ts +20 -0
  65. package/node_modules/@aws-cdk/cfnspec/lib/schema/docs.js +3 -0
  66. package/node_modules/@aws-cdk/cfnspec/lib/schema/index.d.ts +1 -0
  67. package/node_modules/@aws-cdk/cfnspec/lib/schema/index.js +2 -1
  68. package/node_modules/@aws-cdk/cfnspec/package.json +5 -5
  69. package/node_modules/@aws-cdk/cfnspec/spec/cfn-docs.json +38910 -0
  70. package/node_modules/@aws-cdk/cfnspec/spec/cfn-lint.json +3 -3
  71. package/node_modules/@aws-cdk/cfnspec/spec/specification.json +319 -311
  72. package/node_modules/@aws-cdk/cfnspec/tsconfig.tsbuildinfo +285 -179
  73. package/node_modules/@aws-cdk/cloudformation-diff/LICENSE +1 -1
  74. package/node_modules/@aws-cdk/cloudformation-diff/NOTICE +1 -1
  75. package/node_modules/@aws-cdk/cloudformation-diff/package.json +7 -7
  76. package/package.json +5 -5
@@ -0,0 +1,285 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatErrorInContext = exports.CfnSpecValidator = void 0;
4
+ /* eslint-disable no-console */
5
+ /**
6
+ * CloudFormation spec validator
7
+ *
8
+ * "Why not JSON Schema?", you might ask, and it's a fair question. The answer is:
9
+ * because the error reporting from JSON schema is pretty bad, and I want the validation
10
+ * errors reported from this check to be blindingly obvious, as non-spec-experts
11
+ * are going to have to consume and understand them.
12
+ *
13
+ * I tried JSON Schema validation and its errors look like:
14
+ *
15
+ * ```
16
+ * - instance.PropertyTypes["..."].Properties.Xyz does not match allOf schema <#/definitions/Typed> with 7 error[s]:
17
+ * - instance.PropertyTypes["..."].Properties.Xyz requires property "PrimitiveType"
18
+ * - instance.PropertyTypes["..."].Properties.Xyz requires property "Type"
19
+ * - instance.PropertyTypes["..."].Properties.Xyz requires property "Type"
20
+ * - instance.PropertyTypes["..."].Properties.Xyz requires property "ItemType"
21
+ * - instance.PropertyTypes["..."].Properties.Xyz requires property "Type"
22
+ * - instance.PropertyTypes["..."].Properties.Xyz requires property "PrimitiveItemType"
23
+ * - instance.PropertyTypes["..."].Properties.Xyz is not exactly one from "Primitive","Complex Type","Collection of Primitives","Collection of Complex Types"
24
+ * ```
25
+ *
26
+ * No bueno. In contrast, this script prints:
27
+ *
28
+ * ```
29
+ * {
30
+ * "ResourceTypes": {
31
+ * "AWS::SageMaker::Device": {
32
+ * "Properties": {
33
+ * "Device": {
34
+ *
35
+ * !!! must have exactly one of 'Type', 'PrimitiveType', found: {"Type":"Device","PrimitiveType":"Json"} !!!
36
+ *
37
+ * "Documentation": "http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sagemaker-device.html#cfn-sagemaker-device-device",
38
+ * "UpdateType": "Mutable",
39
+ * "Required": false,
40
+ * "PrimitiveType": "Json",
41
+ * "Type": "Device"
42
+ * }
43
+ * }
44
+ * }
45
+ * }
46
+ * }
47
+ * ```
48
+ */
49
+ const fs = require("fs-extra");
50
+ class CfnSpecValidator {
51
+ constructor(spec) {
52
+ this.errors = new Array();
53
+ this.root = JsonValue.of(spec);
54
+ }
55
+ static validate(spec) {
56
+ const ret = new CfnSpecValidator(spec);
57
+ ret.validateSpec();
58
+ return ret.errors;
59
+ }
60
+ validateSpec() {
61
+ this.assert(this.root.get('PropertyTypes'), isObject, (propTypes) => {
62
+ this.validateMap(propTypes, (propType) => this.validatePropertyType(propType));
63
+ });
64
+ this.assert(this.root.get('ResourceTypes'), isObject, (resTypes) => {
65
+ this.validateMap(resTypes, (propType) => this.validateResourceType(propType));
66
+ });
67
+ }
68
+ /**
69
+ * Property types are extremely weird
70
+ *
71
+ * Nominally, they define "records" that have a `Properties` field with the defined
72
+ * properties.
73
+ *
74
+ * However, they are also commonly used as aliases for other types, meaning they have
75
+ * the same type-indicating fields as individual property *fields* would have.
76
+ *
77
+ * Also also, it seems to be quite common to have them empty--have no fields at all.
78
+ * This seems to be taken as an alias for an unstructured `Json` type. It's probably
79
+ * just a mistake, but unfortunately a mistake that S3 is participating in, so if we
80
+ * fail on that we won't be able to consume updates to S3's schema. Our codegen is
81
+ * ready to deal with this and just renders it to an empty struct.
82
+ */
83
+ validatePropertyType(propType) {
84
+ // If the only set of properties is "Documentation", we take this to be an alias
85
+ // for an empty struct and allow it. I feel icky allowing this, but it seems to
86
+ // be pragmatic for now.
87
+ if (Object.keys(propType.value).join(',') === 'Documentation') {
88
+ return;
89
+ }
90
+ const properties = propType.get('Properties');
91
+ if (properties.hasValue) {
92
+ this.assert(properties, isObject, (props) => {
93
+ this.validateProperties(props);
94
+ });
95
+ }
96
+ else {
97
+ this.validateType(propType, 'if a property type doesn\'t have "Properties", it ');
98
+ }
99
+ }
100
+ validateResourceType(resType) {
101
+ this.assertOptional(resType.get('Properties'), isObject, (props) => {
102
+ this.validateProperties(props);
103
+ });
104
+ this.assertOptional(resType.get('Attributes'), isObject, (attrs) => {
105
+ this.validateMap(attrs, attr => {
106
+ this.validateType(attr);
107
+ });
108
+ });
109
+ }
110
+ validateProperties(properties) {
111
+ this.validateMap(properties, prop => {
112
+ this.validateType(prop);
113
+ this.assertOptional(prop.get('UpdateType'), (x) => {
114
+ if (!['Mutable', 'Immutable', 'Conditional'].includes(x)) {
115
+ throw new Error(`invalid value for enum: '${x}'`);
116
+ }
117
+ });
118
+ });
119
+ }
120
+ /**
121
+ * Validate the type
122
+ *
123
+ * There must be:
124
+ * - Either Type or PrimitiveType
125
+ * - Only if Type is List or Map, there will be either an ItemType or a PrimitiveItemType
126
+ * - Non-primitive Types must correspond to a property type
127
+ */
128
+ validateType(typedObject, errorPrefix = '') {
129
+ const type = typedObject.get('Type');
130
+ const primitiveType = typedObject.get('PrimitiveType');
131
+ if (type.hasValue === primitiveType.hasValue) {
132
+ this.report(typedObject, `${errorPrefix}must have exactly one of 'Type', 'PrimitiveType', found: ${JSON.stringify({
133
+ Type: type.valueOrUndefined,
134
+ PrimitiveType: primitiveType.valueOrUndefined,
135
+ })}`);
136
+ }
137
+ this.assertOptional(primitiveType, isValidPrimitive);
138
+ let isCollectionType = false;
139
+ const itemType = typedObject.get('ItemType');
140
+ const primitiveItemType = typedObject.get('PrimitiveItemType');
141
+ if (type.hasValue) {
142
+ isCollectionType = COLLECTION_TYPES.includes(type.value);
143
+ if (isCollectionType) {
144
+ if (itemType.hasValue === primitiveItemType.hasValue) {
145
+ this.report(typedObject, `must have exactly one of 'ItemType', 'PrimitiveItemType', found: ${JSON.stringify({
146
+ ItemType: itemType.valueOrUndefined,
147
+ PrimitiveItemType: primitiveItemType.valueOrUndefined,
148
+ })}`);
149
+ }
150
+ this.assertOptional(primitiveItemType, isValidPrimitive);
151
+ if (itemType.hasValue) {
152
+ this.assertValidPropertyTypeReference(itemType);
153
+ }
154
+ }
155
+ else {
156
+ this.assertValidPropertyTypeReference(type);
157
+ }
158
+ }
159
+ if (!isCollectionType) {
160
+ if (itemType.hasValue || primitiveItemType.hasValue) {
161
+ this.report(typedObject, 'only \'List\' or \'Map\' types can have \'ItemType\', \'PrimitiveItemType\'');
162
+ }
163
+ }
164
+ const dupes = typedObject.get('DuplicatesAllowed');
165
+ if (dupes.hasValue && !isCollectionType) {
166
+ this.report(dupes, 'occurs on non-collection type');
167
+ }
168
+ }
169
+ assertValidPropertyTypeReference(typeName) {
170
+ if (BUILTIN_COMPLEX_TYPES.includes(typeName.value)) {
171
+ return;
172
+ }
173
+ const cfnName = typeName.path[1]; // AWS::Xyz::Resource[.Property]
174
+ const namespace = cfnName.split('.')[0];
175
+ const propTypeName = `${namespace}.${typeName.value}`;
176
+ if (!this.root.get('PropertyTypes').get(propTypeName).hasValue) {
177
+ this.report(typeName, `unknown property type name '${typeName.value}' (missing definition for '${propTypeName}')`);
178
+ }
179
+ }
180
+ assertOptional(x, pred, block) {
181
+ return x.hasValue ? this.assert(x, pred, block) : true;
182
+ }
183
+ assert(x, pred, block) {
184
+ try {
185
+ pred(x.value);
186
+ if (block) {
187
+ block(new JsonValue(x.value, x.path));
188
+ }
189
+ return true;
190
+ }
191
+ catch (e) {
192
+ this.report(x, e.message);
193
+ return false;
194
+ }
195
+ }
196
+ validateMap(x, block) {
197
+ for (const key in x.value) {
198
+ block(x.get(key));
199
+ }
200
+ }
201
+ report(value, message) {
202
+ this.errors.push({ value, message });
203
+ }
204
+ }
205
+ exports.CfnSpecValidator = CfnSpecValidator;
206
+ function isObject(x) {
207
+ if (x == null || typeof x !== 'object' || Array.isArray(x)) {
208
+ throw new Error(`expected object, found '${x}'`);
209
+ }
210
+ }
211
+ const COLLECTION_TYPES = ['List', 'Map'];
212
+ const BUILTIN_COMPLEX_TYPES = ['Tag'];
213
+ function isValidPrimitive(x) {
214
+ const primitives = ['String', 'Long', 'Integer', 'Double', 'Boolean', 'Timestamp', 'Json'];
215
+ if (!primitives.includes(x)) {
216
+ throw new Error(`must be one of ${primitives.join(', ')}, got: ${x}`);
217
+ }
218
+ }
219
+ class JsonValue {
220
+ constructor(value, path) {
221
+ this.value = value;
222
+ this.path = path;
223
+ this.hasValue = true;
224
+ this.valueOrUndefined = this.value;
225
+ this.pathValue = this.value;
226
+ }
227
+ static of(x) {
228
+ return new JsonValue(x, []);
229
+ }
230
+ get(k) {
231
+ if (!this.value || typeof this.value !== 'object' || Array.isArray(this.value)) {
232
+ return new ErrorValue(`expected object, found ${this.value}`, this.path, this.value);
233
+ }
234
+ const ret = this.value[k];
235
+ if (ret === undefined) {
236
+ return new ErrorValue(`missing required key '${k}'`, this.path, this.value);
237
+ }
238
+ return new JsonValue(ret, [...this.path, `${k}`]);
239
+ }
240
+ }
241
+ class ErrorValue {
242
+ constructor(error, path, pathValue) {
243
+ this.error = error;
244
+ this.path = path;
245
+ this.pathValue = pathValue;
246
+ this.hasValue = false;
247
+ this.valueOrUndefined = undefined;
248
+ }
249
+ get(_k) {
250
+ return this;
251
+ }
252
+ get value() {
253
+ throw new Error(this.error);
254
+ }
255
+ }
256
+ function formatErrorInContext(error) {
257
+ let reportValue = error.value.pathValue;
258
+ for (let i = error.value.path.length; i > 0; i--) {
259
+ reportValue = { [error.value.path[i - 1]]: reportValue };
260
+ }
261
+ const formattedLines = JSON.stringify(reportValue, undefined, 2).split('\n');
262
+ const indent = 2 * (error.value.path.length + 1);
263
+ // Insert the error message at line N with an appropriate indent
264
+ formattedLines.splice(error.value.path.length + 1, 0, `\n!!!${' '.repeat(indent - 3)}${error.message} !!!\n`);
265
+ return formattedLines.join('\n');
266
+ }
267
+ exports.formatErrorInContext = formatErrorInContext;
268
+ async function main(args) {
269
+ const spec = await fs.readJson(args[0]);
270
+ const errors = CfnSpecValidator.validate(spec);
271
+ if (errors.length !== 0) {
272
+ for (const error of errors) {
273
+ console.error(formatErrorInContext(error));
274
+ }
275
+ process.exitCode = 1;
276
+ }
277
+ }
278
+ if (require.main === module) {
279
+ main(process.argv.slice(2)).catch(e => {
280
+ process.exitCode = 1;
281
+ // eslint-disable-next-line no-console
282
+ console.error(e.message);
283
+ });
284
+ }
285
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdGUtY2ZuLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsidmFsaWRhdGUtY2ZuLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLCtCQUErQjtBQUMvQjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQTJDRztBQUNILCtCQUErQjtBQWEvQixNQUFhLGdCQUFnQjtJQVUzQixZQUFZLElBQWE7UUFIVCxXQUFNLEdBQUcsSUFBSSxLQUFLLEVBQW1CLENBQUM7UUFJcEQsSUFBSSxDQUFDLElBQUksR0FBRyxTQUFTLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2pDLENBQUM7SUFYTSxNQUFNLENBQUMsUUFBUSxDQUFDLElBQWE7UUFDbEMsTUFBTSxHQUFHLEdBQUcsSUFBSSxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN2QyxHQUFHLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDbkIsT0FBTyxHQUFHLENBQUMsTUFBTSxDQUFDO0lBQ3BCLENBQUM7SUFTTSxZQUFZO1FBQ2pCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUMsU0FBUyxFQUFFLEVBQUU7WUFDbEUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1FBQ2pGLENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxlQUFlLENBQUMsRUFBRSxRQUFRLEVBQUUsQ0FBQyxRQUFRLEVBQUUsRUFBRTtZQUNqRSxJQUFJLENBQUMsV0FBVyxDQUFDLFFBQVEsRUFBRSxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLG9CQUFvQixD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LWNvbnNvbGUgKi9cbi8qKlxuICogQ2xvdWRGb3JtYXRpb24gc3BlYyB2YWxpZGF0b3JcbiAqXG4gKiBcIldoeSBub3QgSlNPTiBTY2hlbWE/XCIsIHlvdSBtaWdodCBhc2ssIGFuZCBpdCdzIGEgZmFpciBxdWVzdGlvbi4gVGhlIGFuc3dlciBpczpcbiAqIGJlY2F1c2UgdGhlIGVycm9yIHJlcG9ydGluZyBmcm9tIEpTT04gc2NoZW1hIGlzIHByZXR0eSBiYWQsIGFuZCBJIHdhbnQgdGhlIHZhbGlkYXRpb25cbiAqIGVycm9ycyByZXBvcnRlZCBmcm9tIHRoaXMgY2hlY2sgdG8gYmUgYmxpbmRpbmdseSBvYnZpb3VzLCBhcyBub24tc3BlYy1leHBlcnRzXG4gKiBhcmUgZ29pbmcgdG8gaGF2ZSB0byBjb25zdW1lIGFuZCB1bmRlcnN0YW5kIHRoZW0uXG4gKlxuICogSSB0cmllZCBKU09OIFNjaGVtYSB2YWxpZGF0aW9uIGFuZCBpdHMgZXJyb3JzIGxvb2sgbGlrZTpcbiAqXG4gKiBgYGBcbiAqIC0gaW5zdGFuY2UuUHJvcGVydHlUeXBlc1tcIi4uLlwiXS5Qcm9wZXJ0aWVzLlh5eiBkb2VzIG5vdCBtYXRjaCBhbGxPZiBzY2hlbWEgPCMvZGVmaW5pdGlvbnMvVHlwZWQ+IHdpdGggNyBlcnJvcltzXTpcbiAqIC0gaW5zdGFuY2UuUHJvcGVydHlUeXBlc1tcIi4uLlwiXS5Qcm9wZXJ0aWVzLlh5eiByZXF1aXJlcyBwcm9wZXJ0eSBcIlByaW1pdGl2ZVR5cGVcIlxuICogLSBpbnN0YW5jZS5Qcm9wZXJ0eVR5cGVzW1wiLi4uXCJdLlByb3BlcnRpZXMuWHl6IHJlcXVpcmVzIHByb3BlcnR5IFwiVHlwZVwiXG4gKiAtIGluc3RhbmNlLlByb3BlcnR5VHlwZXNbXCIuLi5cIl0uUHJvcGVydGllcy5YeXogcmVxdWlyZXMgcHJvcGVydHkgXCJUeXBlXCJcbiAqIC0gaW5zdGFuY2UuUHJvcGVydHlUeXBlc1tcIi4uLlwiXS5Qcm9wZXJ0aWVzLlh5eiByZXF1aXJlcyBwcm9wZXJ0eSBcIkl0ZW1UeXBlXCJcbiAqIC0gaW5zdGFuY2UuUHJvcGVydHlUeXBlc1tcIi4uLlwiXS5Qcm9wZXJ0aWVzLlh5eiByZXF1aXJlcyBwcm9wZXJ0eSBcIlR5cGVcIlxuICogLSBpbnN0YW5jZS5Qcm9wZXJ0eVR5cGVzW1wiLi4uXCJdLlByb3BlcnRpZXMuWHl6IHJlcXVpcmVzIHByb3BlcnR5IFwiUHJpbWl0aXZlSXRlbVR5cGVcIlxuICogLSBpbnN0YW5jZS5Qcm9wZXJ0eVR5cGVzW1wiLi4uXCJdLlByb3BlcnRpZXMuWHl6IGlzIG5vdCBleGFjdGx5IG9uZSBmcm9tIFwiUHJpbWl0aXZlXCIsXCJDb21wbGV4IFR5cGVcIixcIkNvbGxlY3Rpb24gb2YgUHJpbWl0aXZlc1wiLFwiQ29sbGVjdGlvbiBvZiBDb21wbGV4IFR5cGVzXCJcbiAqIGBgYFxuICpcbiAqIE5vIGJ1ZW5vLiBJbiBjb250cmFzdCwgdGhpcyBzY3JpcHQgcHJpbnRzOlxuICpcbiAqIGBgYFxuICoge1xuICogICBcIlJlc291cmNlVHlwZXNcIjoge1xuICogICAgIFwiQVdTOjpTYWdlTWFrZXI6OkRldmljZVwiOiB7XG4gKiAgICAgICBcIlByb3BlcnRpZXNcIjoge1xuICogICAgICAgICBcIkRldmljZVwiOiB7XG4gKlxuICogISEhICAgICAgIG11c3QgaGF2ZSBleGFjdGx5IG9uZSBvZiAnVHlwZScsICdQcmltaXRpdmVUeXBlJywgZm91bmQ6IHtcIlR5cGVcIjpcIkRldmljZVwiLFwiUHJpbWl0aXZlVHlwZVwiOlwiSnNvblwifSAhISFcbiAqXG4gKiAgICAgICAgICAgXCJEb2N1bWVudGF0aW9uXCI6IFwiaHR0cDovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcmVzb3VyY2Utc2FnZW1ha2VyLWRldmljZS5odG1sI2Nmbi1zYWdlbWFrZXItZGV2aWNlLWRldmljZVwiLFxuICogICAgICAgICAgIFwiVXBkYXRlVHlwZVwiOiBcIk11dGFibGVcIixcbiAqICAgICAgICAgICBcIlJlcXVpcmVkXCI6IGZhbHNlLFxuICogICAgICAgICAgIFwiUHJpbWl0aXZlVHlwZVwiOiBcIkpzb25cIixcbiAqICAgICAgICAgICBcIlR5cGVcIjogXCJEZXZpY2VcIlxuICogICAgICAgICB9XG4gKiAgICAgICB9XG4gKiAgICAgfVxuICogICB9XG4gKiB9XG4gKiBgYGBcbiAqL1xuaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMtZXh0cmEnO1xuXG5leHBvcnQgaW50ZXJmYWNlIENmblNwZWMge1xuICBQcm9wZXJ0eVR5cGVzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICBSZXNvdXJjZVR5cGVzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xuICBSZXNvdXJjZVNwZWNpZmljYXRpb25WZXJzaW9uOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVmFsaWRhdGlvbkVycm9yIHtcbiAgcmVhZG9ubHkgdmFsdWU6IEpzb25WYWx1ZTxhbnk+O1xuICByZWFkb25seSBtZXNzYWdlOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBjbGFzcyBDZm5TcGVjVmFsaWRhdG9yIHtcbiAgcHVibGljIHN0YXRpYyB2YWxpZGF0ZShzcGVjOiBDZm5TcGVjKSB7XG4gICAgY29uc3QgcmV0ID0gbmV3IENmblNwZWNWYWxpZGF0b3Ioc3BlYyk7XG4gICAgcmV0LnZhbGlkYXRlU3BlYygpO1xuICAgIHJldHVybiByZXQuZXJyb3JzO1xuICB9XG5cbiAgcHVibGljIHJlYWRvbmx5IGVycm9ycyA9IG5ldyBBcnJheTxWYWxpZGF0aW9uRXJyb3I+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgcm9vdDogSnNvblZhbHVlPENmblNwZWM+O1xuXG4gIGNvbnN0cnVjdG9yKHNwZWM6IENmblNwZWMpIHtcbiAgICB0aGlzLnJvb3QgPSBKc29uVmFsdWUub2Yoc3BlYyk7XG4gIH1cblxuICBwdWJsaWMgdmFsaWRhdGVTcGVjKCkge1xuICAgIHRoaXMuYXNzZXJ0KHRoaXMucm9vdC5nZXQoJ1Byb3BlcnR5VHlwZXMnKSwgaXNPYmplY3QsIChwcm9wVHlwZXMpID0+IHtcbiAgICAgIHRoaXMudmFsaWRhdGVNYXAocHJvcFR5cGVzLCAocHJvcFR5cGUpID0+IHRoaXMudmFsaWRhdGVQcm9wZXJ0eVR5cGUocHJvcFR5cGUpKTtcbiAgICB9KTtcblxuICAgIHRoaXMuYXNzZXJ0KHRoaXMucm9vdC5nZXQoJ1Jlc291cmNlVHlwZXMnKSwgaXNPYmplY3QsIChyZXNUeXBlcykgPT4ge1xuICAgICAgdGhpcy52YWxpZGF0ZU1hcChyZXNUeXBlcywgKHByb3BUeXBlKSA9PiB0aGlzLnZhbGlkYXRlUmVzb3VyY2VUeXBlKHByb3BUeXBlKSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUHJvcGVydHkgdHlwZXMgYXJlIGV4dHJlbWVseSB3ZWlyZFxuICAgKlxuICAgKiBOb21pbmFsbHksIHRoZXkgZGVmaW5lIFwicmVjb3Jkc1wiIHRoYXQgaGF2ZSBhIGBQcm9wZXJ0aWVzYCBmaWVsZCB3aXRoIHRoZSBkZWZpbmVkXG4gICAqIHByb3BlcnRpZXMuXG4gICAqXG4gICAqIEhvd2V2ZXIsIHRoZXkgYXJlIGFsc28gY29tbW9ubHkgdXNlZCBhcyBhbGlhc2VzIGZvciBvdGhlciB0eXBlcywgbWVhbmluZyB0aGV5IGhhdmVcbiAgICogdGhlIHNhbWUgdHlwZS1pbmRpY2F0aW5nIGZpZWxkcyBhcyBpbmRpdmlkdWFsIHByb3BlcnR5ICpmaWVsZHMqIHdvdWxkIGhhdmUuXG4gICAqXG4gICAqIEFsc28gYWxzbywgaXQgc2VlbXMgdG8gYmUgcXVpdGUgY29tbW9uIHRvIGhhdmUgdGhlbSBlbXB0eS0taGF2ZSBubyBmaWVsZHMgYXQgYWxsLlxuICAgKiBUaGlzIHNlZW1zIHRvIGJlIHRha2VuIGFzIGFuIGFsaWFzIGZvciBhbiB1bnN0cnVjdHVyZWQgYEpzb25gIHR5cGUuIEl0J3MgcHJvYmFibHlcbiAgICoganVzdCBhIG1pc3Rha2UsIGJ1dCB1bmZvcnR1bmF0ZWx5IGEgbWlzdGFrZSB0aGF0IFMzIGlzIHBhcnRpY2lwYXRpbmcgaW4sIHNvIGlmIHdlXG4gICAqIGZhaWwgb24gdGhhdCB3ZSB3b24ndCBiZSBhYmxlIHRvIGNvbnN1bWUgdXBkYXRlcyB0byBTMydzIHNjaGVtYS4gT3VyIGNvZGVnZW4gaXNcbiAgICogcmVhZHkgdG8gZGVhbCB3aXRoIHRoaXMgYW5kIGp1c3QgcmVuZGVycyBpdCB0byBhbiBlbXB0eSBzdHJ1Y3QuXG4gICAqL1xuICBwcml2YXRlIHZhbGlkYXRlUHJvcGVydHlUeXBlKHByb3BUeXBlOiBKc29uVmFsdWU8UmVjb3JkPHN0cmluZywgYW55Pj4pIHtcbiAgICAvLyBJZiB0aGUgb25seSBzZXQgb2YgcHJvcGVydGllcyBpcyBcIkRvY3VtZW50YXRpb25cIiwgd2UgdGFrZSB0aGlzIHRvIGJlIGFuIGFsaWFzXG4gICAgLy8gZm9yIGFuIGVtcHR5IHN0cnVjdCBhbmQgYWxsb3cgaXQuIEkgZmVlbCBpY2t5IGFsbG93aW5nIHRoaXMsIGJ1dCBpdCBzZWVtcyB0b1xuICAgIC8vIGJlIHByYWdtYXRpYyBmb3Igbm93LlxuICAgIGlmIChPYmplY3Qua2V5cyhwcm9wVHlwZS52YWx1ZSkuam9pbignLCcpID09PSAnRG9jdW1lbnRhdGlvbicpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBwcm9wZXJ0aWVzID0gcHJvcFR5cGUuZ2V0KCdQcm9wZXJ0aWVzJyk7XG4gICAgaWYgKHByb3BlcnRpZXMuaGFzVmFsdWUpIHtcbiAgICAgIHRoaXMuYXNzZXJ0KHByb3BlcnRpZXMsIGlzT2JqZWN0LCAocHJvcHMpID0+IHtcbiAgICAgICAgdGhpcy52YWxpZGF0ZVByb3BlcnRpZXMocHJvcHMpO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMudmFsaWRhdGVUeXBlKHByb3BUeXBlLCAnaWYgYSBwcm9wZXJ0eSB0eXBlIGRvZXNuXFwndCBoYXZlIFwiUHJvcGVydGllc1wiLCBpdCAnKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHZhbGlkYXRlUmVzb3VyY2VUeXBlKHJlc1R5cGU6IEpzb25WYWx1ZTxhbnk+KSB7XG4gICAgdGhpcy5hc3NlcnRPcHRpb25hbChyZXNUeXBlLmdldCgnUHJvcGVydGllcycpLCBpc09iamVjdCwgKHByb3BzKSA9PiB7XG4gICAgICB0aGlzLnZhbGlkYXRlUHJvcGVydGllcyhwcm9wcyk7XG4gICAgfSk7XG5cbiAgICB0aGlzLmFzc2VydE9wdGlvbmFsKHJlc1R5cGUuZ2V0KCdBdHRyaWJ1dGVzJyksIGlzT2JqZWN0LCAoYXR0cnMpID0+IHtcbiAgICAgIHRoaXMudmFsaWRhdGVNYXAoYXR0cnMsIGF0dHIgPT4ge1xuICAgICAgICB0aGlzLnZhbGlkYXRlVHlwZShhdHRyKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSB2YWxpZGF0ZVByb3BlcnRpZXMocHJvcGVydGllczogSnNvblZhbHVlPFJlY29yZDxzdHJpbmcsIGFueT4+KSB7XG4gICAgdGhpcy52YWxpZGF0ZU1hcChwcm9wZXJ0aWVzLCBwcm9wID0+IHtcbiAgICAgIHRoaXMudmFsaWRhdGVUeXBlKHByb3ApO1xuXG4gICAgICB0aGlzLmFzc2VydE9wdGlvbmFsKHByb3AuZ2V0KCdVcGRhdGVUeXBlJyksICh4OiBhbnkpID0+IHtcbiAgICAgICAgaWYgKCFbJ011dGFibGUnLCAnSW1tdXRhYmxlJywgJ0NvbmRpdGlvbmFsJ10uaW5jbHVkZXMoeCkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGludmFsaWQgdmFsdWUgZm9yIGVudW06ICcke3h9J2ApO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZSB0aGUgdHlwZVxuICAgKlxuICAgKiBUaGVyZSBtdXN0IGJlOlxuICAgKiAtIEVpdGhlciBUeXBlIG9yIFByaW1pdGl2ZVR5cGVcbiAgICogLSBPbmx5IGlmIFR5cGUgaXMgTGlzdCBvciBNYXAsIHRoZXJlIHdpbGwgYmUgZWl0aGVyIGFuIEl0ZW1UeXBlIG9yIGEgUHJpbWl0aXZlSXRlbVR5cGVcbiAgICogLSBOb24tcHJpbWl0aXZlIFR5cGVzIG11c3QgY29ycmVzcG9uZCB0byBhIHByb3BlcnR5IHR5cGVcbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVUeXBlKHR5cGVkT2JqZWN0OiBKc29uVmFsdWU8UmVjb3JkPHN0cmluZywgYW55Pj4sIGVycm9yUHJlZml4ID0gJycpIHtcbiAgICBjb25zdCB0eXBlID0gdHlwZWRPYmplY3QuZ2V0KCdUeXBlJyk7XG4gICAgY29uc3QgcHJpbWl0aXZlVHlwZSA9IHR5cGVkT2JqZWN0LmdldCgnUHJpbWl0aXZlVHlwZScpO1xuXG4gICAgaWYgKHR5cGUuaGFzVmFsdWUgPT09IHByaW1pdGl2ZVR5cGUuaGFzVmFsdWUpIHtcbiAgICAgIHRoaXMucmVwb3J0KHR5cGVkT2JqZWN0LCBgJHtlcnJvclByZWZpeH1tdXN0IGhhdmUgZXhhY3RseSBvbmUgb2YgJ1R5cGUnLCAnUHJpbWl0aXZlVHlwZScsIGZvdW5kOiAke0pTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgVHlwZTogdHlwZS52YWx1ZU9yVW5kZWZpbmVkLFxuICAgICAgICBQcmltaXRpdmVUeXBlOiBwcmltaXRpdmVUeXBlLnZhbHVlT3JVbmRlZmluZWQsXG4gICAgICB9KX1gKTtcbiAgICB9XG5cbiAgICB0aGlzLmFzc2VydE9wdGlvbmFsKHByaW1pdGl2ZVR5cGUsIGlzVmFsaWRQcmltaXRpdmUpO1xuXG4gICAgbGV0IGlzQ29sbGVjdGlvblR5cGUgPSBmYWxzZTtcbiAgICBjb25zdCBpdGVtVHlwZSA9IHR5cGVkT2JqZWN0LmdldCgnSXRlbVR5cGUnKTtcbiAgICBjb25zdCBwcmltaXRpdmVJdGVtVHlwZSA9IHR5cGVkT2JqZWN0LmdldCgnUHJpbWl0aXZlSXRlbVR5cGUnKTtcblxuICAgIGlmICh0eXBlLmhhc1ZhbHVlKSB7XG4gICAgICBpc0NvbGxlY3Rpb25UeXBlID0gQ09MTEVDVElPTl9UWVBFUy5pbmNsdWRlcyh0eXBlLnZhbHVlKTtcbiAgICAgIGlmIChpc0NvbGxlY3Rpb25UeXBlKSB7XG4gICAgICAgIGlmIChpdGVtVHlwZS5oYXNWYWx1ZSA9PT0gcHJpbWl0aXZlSXRlbVR5cGUuaGFzVmFsdWUpIHtcbiAgICAgICAgICB0aGlzLnJlcG9ydCh0eXBlZE9iamVjdCwgYG11c3QgaGF2ZSBleGFjdGx5IG9uZSBvZiAnSXRlbVR5cGUnLCAnUHJpbWl0aXZlSXRlbVR5cGUnLCBmb3VuZDogJHtKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICBJdGVtVHlwZTogaXRlbVR5cGUudmFsdWVPclVuZGVmaW5lZCxcbiAgICAgICAgICAgIFByaW1pdGl2ZUl0ZW1UeXBlOiBwcmltaXRpdmVJdGVtVHlwZS52YWx1ZU9yVW5kZWZpbmVkLFxuICAgICAgICAgIH0pfWApO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5hc3NlcnRPcHRpb25hbChwcmltaXRpdmVJdGVtVHlwZSwgaXNWYWxpZFByaW1pdGl2ZSk7XG4gICAgICAgIGlmIChpdGVtVHlwZS5oYXNWYWx1ZSkge1xuICAgICAgICAgIHRoaXMuYXNzZXJ0VmFsaWRQcm9wZXJ0eVR5cGVSZWZlcmVuY2UoaXRlbVR5cGUpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmFzc2VydFZhbGlkUHJvcGVydHlUeXBlUmVmZXJlbmNlKHR5cGUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICghaXNDb2xsZWN0aW9uVHlwZSkge1xuICAgICAgaWYgKGl0ZW1UeXBlLmhhc1ZhbHVlIHx8IHByaW1pdGl2ZUl0ZW1UeXBlLmhhc1ZhbHVlKSB7XG4gICAgICAgIHRoaXMucmVwb3J0KHR5cGVkT2JqZWN0LCAnb25seSBcXCdMaXN0XFwnIG9yIFxcJ01hcFxcJyB0eXBlcyBjYW4gaGF2ZSBcXCdJdGVtVHlwZVxcJywgXFwnUHJpbWl0aXZlSXRlbVR5cGVcXCcnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBkdXBlcyA9IHR5cGVkT2JqZWN0LmdldCgnRHVwbGljYXRlc0FsbG93ZWQnKTtcbiAgICBpZiAoZHVwZXMuaGFzVmFsdWUgJiYgIWlzQ29sbGVjdGlvblR5cGUpIHtcbiAgICAgIHRoaXMucmVwb3J0KGR1cGVzLCAnb2NjdXJzIG9uIG5vbi1jb2xsZWN0aW9uIHR5cGUnKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzc2VydFZhbGlkUHJvcGVydHlUeXBlUmVmZXJlbmNlKHR5cGVOYW1lOiBKc29uVmFsdWU8c3RyaW5nPikge1xuICAgIGlmIChCVUlMVElOX0NPTVBMRVhfVFlQRVMuaW5jbHVkZXModHlwZU5hbWUudmFsdWUpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgY2ZuTmFtZSA9IHR5cGVOYW1lLnBhdGhbMV07IC8vIEFXUzo6WHl6OjpSZXNvdXJjZVsuUHJvcGVydHldXG4gICAgY29uc3QgbmFtZXNwYWNlID0gY2ZuTmFtZS5zcGxpdCgnLicpWzBdO1xuXG4gICAgY29uc3QgcHJvcFR5cGVOYW1lID0gYCR7bmFtZXNwYWNlfS4ke3R5cGVOYW1lLnZhbHVlfWA7XG4gICAgaWYgKCF0aGlzLnJvb3QuZ2V0KCdQcm9wZXJ0eVR5cGVzJykuZ2V0KHByb3BUeXBlTmFtZSkuaGFzVmFsdWUpIHtcbiAgICAgIHRoaXMucmVwb3J0KHR5cGVOYW1lLCBgdW5rbm93biBwcm9wZXJ0eSB0eXBlIG5hbWUgJyR7dHlwZU5hbWUudmFsdWV9JyAobWlzc2luZyBkZWZpbml0aW9uIGZvciAnJHtwcm9wVHlwZU5hbWV9JylgKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzc2VydE9wdGlvbmFsPEEsIEIgZXh0ZW5kcyBBPih4OiBKc29uVmFsdWU8QT4sIHByZWQ6ICh4OiBBKSA9PiBhc3NlcnRzIHggaXMgQiwgYmxvY2s/OiAoeDogSnNvblZhbHVlPEI+KSA9PiB2b2lkKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHguaGFzVmFsdWUgPyB0aGlzLmFzc2VydCh4LCBwcmVkLCBibG9jaykgOiB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3NlcnQ8QSwgQiBleHRlbmRzIEE+KHg6IEpzb25WYWx1ZTxBPiwgcHJlZDogKHg6IEEpID0+IGFzc2VydHMgeCBpcyBCLCBibG9jaz86ICh4OiBKc29uVmFsdWU8Qj4pID0+IHZvaWQpOiBib29sZWFuIHtcbiAgICB0cnkge1xuICAgICAgcHJlZCh4LnZhbHVlKTtcbiAgICAgIGlmIChibG9jaykge1xuICAgICAgICBibG9jayhuZXcgSnNvblZhbHVlKHgudmFsdWUsIHgucGF0aCkpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhpcy5yZXBvcnQoeCwgZS5tZXNzYWdlKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHZhbGlkYXRlTWFwPEE+KHg6IEpzb25WYWx1ZTxSZWNvcmQ8c3RyaW5nLCBBPj4sIGJsb2NrOiAoeDogSnNvblZhbHVlPEE+KSA9PiB2b2lkKSB7XG4gICAgZm9yIChjb25zdCBrZXkgaW4geC52YWx1ZSkge1xuICAgICAgYmxvY2soeC5nZXQoa2V5KSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZXBvcnQodmFsdWU6IEpzb25WYWx1ZTxhbnk+LCBtZXNzYWdlOiBzdHJpbmcpIHtcbiAgICB0aGlzLmVycm9ycy5wdXNoKHsgdmFsdWUsIG1lc3NhZ2UgfSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gaXNPYmplY3QoeDogYW55KTogYXNzZXJ0cyB4IGlzIFJlY29yZDxzdHJpbmcsIGFueT4ge1xuICBpZiAoeCA9PSBudWxsIHx8IHR5cGVvZiB4ICE9PSAnb2JqZWN0JyB8fCBBcnJheS5pc0FycmF5KHgpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBleHBlY3RlZCBvYmplY3QsIGZvdW5kICcke3h9J2ApO1xuICB9XG59XG5cbmNvbnN0IENPTExFQ1RJT05fVFlQRVMgPSBbJ0xpc3QnLCAnTWFwJ107XG5jb25zdCBCVUlMVElOX0NPTVBMRVhfVFlQRVMgPSBbJ1RhZyddO1xuXG5mdW5jdGlvbiBpc1ZhbGlkUHJpbWl0aXZlKHg6IGFueSk6IGFzc2VydHMgeCBpcyBzdHJpbmcge1xuICBjb25zdCBwcmltaXRpdmVzID0gWydTdHJpbmcnLCAnTG9uZycsICdJbnRlZ2VyJywgJ0RvdWJsZScsICdCb29sZWFuJywgJ1RpbWVzdGFtcCcsICdKc29uJ107XG5cbiAgaWYgKCFwcmltaXRpdmVzLmluY2x1ZGVzKHgpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBtdXN0IGJlIG9uZSBvZiAke3ByaW1pdGl2ZXMuam9pbignLCAnKX0sIGdvdDogJHt4fWApO1xuICB9XG59XG5cbmludGVyZmFjZSBKc29uVmFsdWU8QT4ge1xuICByZWFkb25seSBwYXRoOiBzdHJpbmdbXTtcbiAgcmVhZG9ubHkgcGF0aFZhbHVlOiBhbnk7XG4gIHJlYWRvbmx5IGhhc1ZhbHVlOiBib29sZWFuO1xuICByZWFkb25seSB2YWx1ZTogQTtcbiAgcmVhZG9ubHkgdmFsdWVPclVuZGVmaW5lZDogQSB8IHVuZGVmaW5lZDtcbiAgZ2V0PEsgZXh0ZW5kcyBrZXlvZiBBPihrOiBLKTogSnNvblZhbHVlPEFbS10+O1xufVxuXG5jbGFzcyBKc29uVmFsdWU8QT4gaW1wbGVtZW50cyBKc29uVmFsdWU8QT4ge1xuICBwdWJsaWMgc3RhdGljIG9mPEI+KHg6IEIpOiBKc29uVmFsdWU8Qj4ge1xuICAgIHJldHVybiBuZXcgSnNvblZhbHVlKHgsIFtdKTtcbiAgfVxuXG4gIHB1YmxpYyByZWFkb25seSBoYXNWYWx1ZTogYm9vbGVhbiA9IHRydWU7XG4gIHB1YmxpYyByZWFkb25seSB2YWx1ZU9yVW5kZWZpbmVkOiBBIHwgdW5kZWZpbmVkID0gdGhpcy52YWx1ZTtcbiAgcHVibGljIHJlYWRvbmx5IHBhdGhWYWx1ZTogYW55ID0gdGhpcy52YWx1ZTtcblxuICBjb25zdHJ1Y3RvcihwdWJsaWMgcmVhZG9ubHkgdmFsdWU6IEEsIHB1YmxpYyByZWFkb25seSBwYXRoOiBzdHJpbmdbXSkge1xuICB9XG5cbiAgcHVibGljIGdldDxLIGV4dGVuZHMga2V5b2YgQT4oazogSyk6IEpzb25WYWx1ZTxBW0tdPiB7XG4gICAgaWYgKCF0aGlzLnZhbHVlIHx8IHR5cGVvZiB0aGlzLnZhbHVlICE9PSAnb2JqZWN0JyB8fCBBcnJheS5pc0FycmF5KHRoaXMudmFsdWUpKSB7XG4gICAgICByZXR1cm4gbmV3IEVycm9yVmFsdWUoYGV4cGVjdGVkIG9iamVjdCwgZm91bmQgJHt0aGlzLnZhbHVlfWAsIHRoaXMucGF0aCwgdGhpcy52YWx1ZSk7XG4gICAgfVxuICAgIGNvbnN0IHJldCA9IHRoaXMudmFsdWVba107XG4gICAgaWYgKHJldCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gbmV3IEVycm9yVmFsdWUoYG1pc3NpbmcgcmVxdWlyZWQga2V5ICcke2t9J2AsIHRoaXMucGF0aCwgdGhpcy52YWx1ZSk7XG4gICAgfVxuICAgIHJldHVybiBuZXcgSnNvblZhbHVlKHJldCwgWy4uLnRoaXMucGF0aCwgYCR7a31gXSk7XG4gIH1cbn1cblxuY2xhc3MgRXJyb3JWYWx1ZTxBPiBpbXBsZW1lbnRzIEpzb25WYWx1ZTxBPiB7XG4gIHB1YmxpYyByZWFkb25seSBoYXNWYWx1ZSA9IGZhbHNlO1xuICBwdWJsaWMgcmVhZG9ubHkgdmFsdWVPclVuZGVmaW5lZDogQSB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IGVycm9yOiBzdHJpbmcsIHB1YmxpYyByZWFkb25seSBwYXRoOiBzdHJpbmdbXSwgcHVibGljIHJlYWRvbmx5IHBhdGhWYWx1ZTogYW55KSB7XG4gIH1cblxuICBwdWJsaWMgZ2V0PEsgZXh0ZW5kcyBrZXlvZiBBPihfazogSyk6IEpzb25WYWx1ZTxBW0tdPiB7XG4gICAgcmV0dXJuIHRoaXMgYXMgYW55O1xuICB9XG5cbiAgcHVibGljIGdldCB2YWx1ZSgpOiBBIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IodGhpcy5lcnJvcik7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdEVycm9ySW5Db250ZXh0KGVycm9yOiBWYWxpZGF0aW9uRXJyb3IpIHtcbiAgbGV0IHJlcG9ydFZhbHVlID0gZXJyb3IudmFsdWUucGF0aFZhbHVlO1xuICBmb3IgKGxldCBpID0gZXJyb3IudmFsdWUucGF0aC5sZW5ndGg7IGkgPiAwOyBpLS0pIHtcbiAgICByZXBvcnRWYWx1ZSA9IHsgW2Vycm9yLnZhbHVlLnBhdGhbaSAtIDFdXTogcmVwb3J0VmFsdWUgfTtcbiAgfVxuXG4gIGNvbnN0IGZvcm1hdHRlZExpbmVzID0gSlNPTi5zdHJpbmdpZnkocmVwb3J0VmFsdWUsIHVuZGVmaW5lZCwgMikuc3BsaXQoJ1xcbicpO1xuXG4gIGNvbnN0IGluZGVudCA9IDIgKiAoZXJyb3IudmFsdWUucGF0aC5sZW5ndGggKyAxKTtcblxuICAvLyBJbnNlcnQgdGhlIGVycm9yIG1lc3NhZ2UgYXQgbGluZSBOIHdpdGggYW4gYXBwcm9wcmlhdGUgaW5kZW50XG4gIGZvcm1hdHRlZExpbmVzLnNwbGljZShlcnJvci52YWx1ZS5wYXRoLmxlbmd0aCArIDEsIDAsIGBcXG4hISEkeycgJy5yZXBlYXQoaW5kZW50IC0gMyl9JHtlcnJvci5tZXNzYWdlfSAhISFcXG5gKTtcblxuICByZXR1cm4gZm9ybWF0dGVkTGluZXMuam9pbignXFxuJyk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG1haW4oYXJnczogc3RyaW5nW10pIHtcbiAgY29uc3Qgc3BlYyA9IGF3YWl0IGZzLnJlYWRKc29uKGFyZ3NbMF0pO1xuICBjb25zdCBlcnJvcnMgPSBDZm5TcGVjVmFsaWRhdG9yLnZhbGlkYXRlKHNwZWMpO1xuICBpZiAoZXJyb3JzLmxlbmd0aCAhPT0gMCkge1xuICAgIGZvciAoY29uc3QgZXJyb3Igb2YgZXJyb3JzKSB7XG4gICAgICBjb25zb2xlLmVycm9yKGZvcm1hdEVycm9ySW5Db250ZXh0KGVycm9yKSk7XG4gICAgfVxuICAgIHByb2Nlc3MuZXhpdENvZGUgPSAxO1xuICB9XG59XG5cbmlmIChyZXF1aXJlLm1haW4gPT09IG1vZHVsZSkge1xuICBtYWluKHByb2Nlc3MuYXJndi5zbGljZSgyKSkuY2F0Y2goZSA9PiB7XG4gICAgcHJvY2Vzcy5leGl0Q29kZSA9IDE7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGVcbiAgICBjb25zb2xlLmVycm9yKGUubWVzc2FnZSk7XG4gIH0pO1xufSJdfQ==
@@ -23,30 +23,30 @@
23
23
  <div class='clearfix'>
24
24
 
25
25
  <div class='fl pad1y space-right2'>
26
- <span class="strong">43.01% </span>
26
+ <span class="strong">62.24% </span>
27
27
  <span class="quiet">Statements</span>
28
- <span class='fraction'>40/93</span>
28
+ <span class='fraction'>183/294</span>
29
29
  </div>
30
30
 
31
31
 
32
32
  <div class='fl pad1y space-right2'>
33
- <span class="strong">26.66% </span>
33
+ <span class="strong">45.83% </span>
34
34
  <span class="quiet">Branches</span>
35
- <span class='fraction'>12/45</span>
35
+ <span class='fraction'>55/120</span>
36
36
  </div>
37
37
 
38
38
 
39
39
  <div class='fl pad1y space-right2'>
40
- <span class="strong">50% </span>
40
+ <span class="strong">67.16% </span>
41
41
  <span class="quiet">Functions</span>
42
- <span class='fraction'>9/18</span>
42
+ <span class='fraction'>45/67</span>
43
43
  </div>
44
44
 
45
45
 
46
46
  <div class='fl pad1y space-right2'>
47
- <span class="strong">46.51% </span>
47
+ <span class="strong">63.53% </span>
48
48
  <span class="quiet">Lines</span>
49
- <span class='fraction'>40/86</span>
49
+ <span class='fraction'>176/277</span>
50
50
  </div>
51
51
 
52
52
 
@@ -61,7 +61,7 @@
61
61
  </div>
62
62
  </template>
63
63
  </div>
64
- <div class='status-line low'></div>
64
+ <div class='status-line medium'></div>
65
65
  <div class="pad1">
66
66
  <table class="coverage-summary">
67
67
  <thead>
@@ -79,18 +79,33 @@
79
79
  </tr>
80
80
  </thead>
81
81
  <tbody><tr>
82
- <td class="file low" data-value="massage-spec.ts"><a href="massage-spec.ts.html">massage-spec.ts</a></td>
83
- <td data-value="35.59" class="pic low">
84
- <div class="chart"><div class="cover-fill" style="width: 35%"></div><div class="cover-empty" style="width: 65%"></div></div>
82
+ <td class="file medium" data-value="massage-spec.ts"><a href="massage-spec.ts.html">massage-spec.ts</a></td>
83
+ <td data-value="61.53" class="pic medium">
84
+ <div class="chart"><div class="cover-fill" style="width: 61%"></div><div class="cover-empty" style="width: 39%"></div></div>
85
85
  </td>
86
- <td data-value="35.59" class="pct low">35.59%</td>
87
- <td data-value="59" class="abs low">21/59</td>
88
- <td data-value="22.72" class="pct low">22.72%</td>
89
- <td data-value="22" class="abs low">5/22</td>
86
+ <td data-value="61.53" class="pct medium">61.53%</td>
87
+ <td data-value="26" class="abs medium">16/26</td>
90
88
  <td data-value="45.45" class="pct low">45.45%</td>
91
89
  <td data-value="11" class="abs low">5/11</td>
92
- <td data-value="37.5" class="pct low">37.5%</td>
93
- <td data-value="56" class="abs low">21/56</td>
90
+ <td data-value="71.42" class="pct medium">71.42%</td>
91
+ <td data-value="7" class="abs medium">5/7</td>
92
+ <td data-value="61.53" class="pct medium">61.53%</td>
93
+ <td data-value="26" class="abs medium">16/26</td>
94
+ </tr>
95
+
96
+ <tr>
97
+ <td class="file medium" data-value="patch-set.ts"><a href="patch-set.ts.html">patch-set.ts</a></td>
98
+ <td data-value="54.23" class="pic medium">
99
+ <div class="chart"><div class="cover-fill" style="width: 54%"></div><div class="cover-empty" style="width: 46%"></div></div>
100
+ </td>
101
+ <td data-value="54.23" class="pct medium">54.23%</td>
102
+ <td data-value="118" class="abs medium">64/118</td>
103
+ <td data-value="37.25" class="pct low">37.25%</td>
104
+ <td data-value="51" class="abs low">19/51</td>
105
+ <td data-value="55" class="pct medium">55%</td>
106
+ <td data-value="20" class="abs medium">11/20</td>
107
+ <td data-value="55.85" class="pct medium">55.85%</td>
108
+ <td data-value="111" class="abs medium">62/111</td>
94
109
  </tr>
95
110
 
96
111
  <tr>
@@ -108,6 +123,21 @@
108
123
  <td data-value="30" class="abs medium">19/30</td>
109
124
  </tr>
110
125
 
126
+ <tr>
127
+ <td class="file high" data-value="validate-cfn.ts"><a href="validate-cfn.ts.html">validate-cfn.ts</a></td>
128
+ <td data-value="72.41" class="pic high">
129
+ <div class="chart"><div class="cover-fill" style="width: 72%"></div><div class="cover-empty" style="width: 28%"></div></div>
130
+ </td>
131
+ <td data-value="72.41" class="pct high">72.41%</td>
132
+ <td data-value="116" class="abs high">84/116</td>
133
+ <td data-value="68.57" class="pct high">68.57%</td>
134
+ <td data-value="35" class="abs high">24/35</td>
135
+ <td data-value="75.75" class="pct medium">75.75%</td>
136
+ <td data-value="33" class="abs medium">25/33</td>
137
+ <td data-value="71.81" class="pct medium">71.81%</td>
138
+ <td data-value="110" class="abs medium">79/110</td>
139
+ </tr>
140
+
111
141
  </tbody>
112
142
  </table>
113
143
  </div>
@@ -116,9 +146,8 @@
116
146
  <div class='footer quiet pad2 space-top1 center small'>
117
147
  Code coverage generated by
118
148
  <a href="https://istanbul.js.org/" target="_blank" rel="noopener">istanbul</a>
119
- at Wed Dec 22 2021 09:46:21 GMT+0000 (Coordinated Universal Time)
149
+ at Sun Jan 09 2022 18:58:21 GMT+0000 (Coordinated Universal Time)
120
150
  </div>
121
- </div>
122
151
  <script src="../prettify.js"></script>
123
152
  <script>
124
153
  window.onload = function () {