@aws-cdk/cloudformation-diff 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +2 -0
  3. package/README.md +12 -0
  4. package/lib/diff/index.d.ts +9 -0
  5. package/lib/diff/index.js +92 -0
  6. package/lib/diff/maybe-parsed.d.ts +14 -0
  7. package/lib/diff/maybe-parsed.js +14 -0
  8. package/lib/diff/template-and-changeset-diff-merger.d.ts +33 -0
  9. package/lib/diff/template-and-changeset-diff-merger.js +128 -0
  10. package/lib/diff/types.d.ts +368 -0
  11. package/lib/diff/types.js +498 -0
  12. package/lib/diff/util.d.ts +57 -0
  13. package/lib/diff/util.js +199 -0
  14. package/lib/diff-template.d.ts +25 -0
  15. package/lib/diff-template.js +212 -0
  16. package/lib/diffable.d.ts +22 -0
  17. package/lib/diffable.js +47 -0
  18. package/lib/format-table.d.ts +6 -0
  19. package/lib/format-table.js +108 -0
  20. package/lib/format.d.ts +106 -0
  21. package/lib/format.js +436 -0
  22. package/lib/iam/iam-changes.d.ts +66 -0
  23. package/lib/iam/iam-changes.js +421 -0
  24. package/lib/iam/iam-identity-center.d.ts +78 -0
  25. package/lib/iam/iam-identity-center.js +46 -0
  26. package/lib/iam/managed-policy.d.ts +11 -0
  27. package/lib/iam/managed-policy.js +33 -0
  28. package/lib/iam/statement.d.ts +113 -0
  29. package/lib/iam/statement.js +270 -0
  30. package/lib/index.d.ts +4 -0
  31. package/lib/index.js +24 -0
  32. package/lib/network/security-group-changes.d.ts +32 -0
  33. package/lib/network/security-group-changes.js +99 -0
  34. package/lib/network/security-group-rule.d.ts +50 -0
  35. package/lib/network/security-group-rule.js +97 -0
  36. package/lib/render-intrinsics.d.ts +21 -0
  37. package/lib/render-intrinsics.js +78 -0
  38. package/lib/util.d.ts +7 -0
  39. package/lib/util.js +62 -0
  40. package/package.json +80 -0
@@ -0,0 +1,498 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ResourceDifference = exports.ResourceImpact = exports.ParameterDifference = exports.OutputDifference = exports.MetadataDifference = exports.MappingDifference = exports.ConditionDifference = exports.DifferenceCollection = exports.PropertyDifference = exports.Difference = exports.TemplateDiff = void 0;
4
+ exports.isPropertyDifference = isPropertyDifference;
5
+ const assert_1 = require("assert");
6
+ const service_spec_types_1 = require("@aws-cdk/service-spec-types");
7
+ const util_1 = require("./util");
8
+ const iam_changes_1 = require("../iam/iam-changes");
9
+ const security_group_changes_1 = require("../network/security-group-changes");
10
+ /** Semantic differences between two CloudFormation templates. */
11
+ class TemplateDiff {
12
+ constructor(args) {
13
+ if (args.awsTemplateFormatVersion !== undefined) {
14
+ this.awsTemplateFormatVersion = args.awsTemplateFormatVersion;
15
+ }
16
+ if (args.description !== undefined) {
17
+ this.description = args.description;
18
+ }
19
+ if (args.transform !== undefined) {
20
+ this.transform = args.transform;
21
+ }
22
+ this.conditions = args.conditions || new DifferenceCollection({});
23
+ this.mappings = args.mappings || new DifferenceCollection({});
24
+ this.metadata = args.metadata || new DifferenceCollection({});
25
+ this.outputs = args.outputs || new DifferenceCollection({});
26
+ this.parameters = args.parameters || new DifferenceCollection({});
27
+ this.resources = args.resources || new DifferenceCollection({});
28
+ this.unknown = args.unknown || new DifferenceCollection({});
29
+ this.iamChanges = new iam_changes_1.IamChanges({
30
+ propertyChanges: this.scrutinizablePropertyChanges(iam_changes_1.IamChanges.IamPropertyScrutinies),
31
+ resourceChanges: this.scrutinizableResourceChanges(iam_changes_1.IamChanges.IamResourceScrutinies),
32
+ });
33
+ this.securityGroupChanges = new security_group_changes_1.SecurityGroupChanges({
34
+ egressRulePropertyChanges: this.scrutinizablePropertyChanges([service_spec_types_1.PropertyScrutinyType.EgressRules]),
35
+ ingressRulePropertyChanges: this.scrutinizablePropertyChanges([service_spec_types_1.PropertyScrutinyType.IngressRules]),
36
+ egressRuleResourceChanges: this.scrutinizableResourceChanges([service_spec_types_1.ResourceScrutinyType.EgressRuleResource]),
37
+ ingressRuleResourceChanges: this.scrutinizableResourceChanges([service_spec_types_1.ResourceScrutinyType.IngressRuleResource]),
38
+ });
39
+ }
40
+ get differenceCount() {
41
+ let count = 0;
42
+ if (this.awsTemplateFormatVersion !== undefined) {
43
+ count += 1;
44
+ }
45
+ if (this.description !== undefined) {
46
+ count += 1;
47
+ }
48
+ if (this.transform !== undefined) {
49
+ count += 1;
50
+ }
51
+ count += this.conditions.differenceCount;
52
+ count += this.mappings.differenceCount;
53
+ count += this.metadata.differenceCount;
54
+ count += this.outputs.differenceCount;
55
+ count += this.parameters.differenceCount;
56
+ count += this.resources.differenceCount;
57
+ count += this.unknown.differenceCount;
58
+ return count;
59
+ }
60
+ get isEmpty() {
61
+ return this.differenceCount === 0;
62
+ }
63
+ /**
64
+ * Return true if any of the permissions objects involve a broadening of permissions
65
+ */
66
+ get permissionsBroadened() {
67
+ return this.iamChanges.permissionsBroadened || this.securityGroupChanges.rulesAdded;
68
+ }
69
+ /**
70
+ * Return true if any of the permissions objects have changed
71
+ */
72
+ get permissionsAnyChanges() {
73
+ return this.iamChanges.hasChanges || this.securityGroupChanges.hasChanges;
74
+ }
75
+ /**
76
+ * Return all property changes of a given scrutiny type
77
+ *
78
+ * We don't just look at property updates; we also look at resource additions and deletions (in which
79
+ * case there is no further detail on property values), and resource type changes.
80
+ */
81
+ scrutinizablePropertyChanges(scrutinyTypes) {
82
+ var _a, _b, _c;
83
+ const ret = new Array();
84
+ for (const [resourceLogicalId, resourceChange] of Object.entries(this.resources.changes)) {
85
+ if (resourceChange.resourceTypeChanged) {
86
+ // we ignore resource type changes here, and handle them in scrutinizableResourceChanges()
87
+ continue;
88
+ }
89
+ if (!resourceChange.resourceType) {
90
+ // We use resourceChange.resourceType to loadResourceModel so that we can inspect the
91
+ // properties of a resource even after the resource is removed from the template.
92
+ continue;
93
+ }
94
+ const newTypeProps = ((_a = (0, util_1.loadResourceModel)(resourceChange.resourceType)) === null || _a === void 0 ? void 0 : _a.properties) || {};
95
+ for (const [propertyName, prop] of Object.entries(newTypeProps)) {
96
+ const propScrutinyType = prop.scrutinizable || service_spec_types_1.PropertyScrutinyType.None;
97
+ if (scrutinyTypes.includes(propScrutinyType)) {
98
+ ret.push({
99
+ resourceLogicalId,
100
+ propertyName,
101
+ resourceType: resourceChange.resourceType,
102
+ scrutinyType: propScrutinyType,
103
+ oldValue: (_b = resourceChange.oldProperties) === null || _b === void 0 ? void 0 : _b[propertyName],
104
+ newValue: (_c = resourceChange.newProperties) === null || _c === void 0 ? void 0 : _c[propertyName],
105
+ });
106
+ }
107
+ }
108
+ }
109
+ return ret;
110
+ }
111
+ /**
112
+ * Return all resource changes of a given scrutiny type
113
+ *
114
+ * We don't just look at resource updates; we also look at resource additions and deletions (in which
115
+ * case there is no further detail on property values), and resource type changes.
116
+ */
117
+ scrutinizableResourceChanges(scrutinyTypes) {
118
+ const ret = new Array();
119
+ for (const [resourceLogicalId, resourceChange] of Object.entries(this.resources.changes)) {
120
+ if (!resourceChange) {
121
+ continue;
122
+ }
123
+ const commonProps = {
124
+ oldProperties: resourceChange.oldProperties,
125
+ newProperties: resourceChange.newProperties,
126
+ resourceLogicalId,
127
+ };
128
+ // changes to the Type of resources can happen when migrating from CFN templates that use Transforms
129
+ if (resourceChange.resourceTypeChanged) {
130
+ // Treat as DELETE+ADD
131
+ if (resourceChange.oldResourceType) {
132
+ const oldResourceModel = (0, util_1.loadResourceModel)(resourceChange.oldResourceType);
133
+ if (oldResourceModel && this.resourceIsScrutinizable(oldResourceModel, scrutinyTypes)) {
134
+ ret.push({
135
+ ...commonProps,
136
+ newProperties: undefined,
137
+ resourceType: resourceChange.oldResourceType,
138
+ scrutinyType: oldResourceModel.scrutinizable,
139
+ });
140
+ }
141
+ }
142
+ if (resourceChange.newResourceType) {
143
+ const newResourceModel = (0, util_1.loadResourceModel)(resourceChange.newResourceType);
144
+ if (newResourceModel && this.resourceIsScrutinizable(newResourceModel, scrutinyTypes)) {
145
+ ret.push({
146
+ ...commonProps,
147
+ oldProperties: undefined,
148
+ resourceType: resourceChange.newResourceType,
149
+ scrutinyType: newResourceModel.scrutinizable,
150
+ });
151
+ }
152
+ }
153
+ }
154
+ else {
155
+ if (!resourceChange.resourceType) {
156
+ continue;
157
+ }
158
+ const resourceModel = (0, util_1.loadResourceModel)(resourceChange.resourceType);
159
+ if (resourceModel && this.resourceIsScrutinizable(resourceModel, scrutinyTypes)) {
160
+ ret.push({
161
+ ...commonProps,
162
+ resourceType: resourceChange.resourceType,
163
+ scrutinyType: resourceModel.scrutinizable,
164
+ });
165
+ }
166
+ }
167
+ }
168
+ return ret;
169
+ }
170
+ resourceIsScrutinizable(res, scrutinyTypes) {
171
+ return scrutinyTypes.includes(res.scrutinizable || service_spec_types_1.ResourceScrutinyType.None);
172
+ }
173
+ }
174
+ exports.TemplateDiff = TemplateDiff;
175
+ /**
176
+ * Models an entity that changed between two versions of a CloudFormation template.
177
+ */
178
+ class Difference {
179
+ /**
180
+ * @param oldValue the old value, cannot be equal (to the sense of +deepEqual+) to +newValue+.
181
+ * @param newValue the new value, cannot be equal (to the sense of +deepEqual+) to +oldValue+.
182
+ */
183
+ constructor(oldValue, newValue) {
184
+ this.oldValue = oldValue;
185
+ this.newValue = newValue;
186
+ if (oldValue === undefined && newValue === undefined) {
187
+ throw new assert_1.AssertionError({ message: 'oldValue and newValue are both undefined!' });
188
+ }
189
+ this.isDifferent = !(0, util_1.deepEqual)(oldValue, newValue);
190
+ }
191
+ /** @returns +true+ if the element is new to the template. */
192
+ get isAddition() {
193
+ return this.oldValue === undefined;
194
+ }
195
+ /** @returns +true+ if the element was removed from the template. */
196
+ get isRemoval() {
197
+ return this.newValue === undefined;
198
+ }
199
+ /** @returns +true+ if the element was already in the template and is updated. */
200
+ get isUpdate() {
201
+ return this.oldValue !== undefined
202
+ && this.newValue !== undefined;
203
+ }
204
+ }
205
+ exports.Difference = Difference;
206
+ class PropertyDifference extends Difference {
207
+ constructor(oldValue, newValue, args) {
208
+ super(oldValue, newValue);
209
+ this.changeImpact = args.changeImpact;
210
+ }
211
+ }
212
+ exports.PropertyDifference = PropertyDifference;
213
+ class DifferenceCollection {
214
+ constructor(diffs) {
215
+ this.diffs = diffs;
216
+ }
217
+ get changes() {
218
+ return onlyChanges(this.diffs);
219
+ }
220
+ get differenceCount() {
221
+ return Object.values(this.changes).length;
222
+ }
223
+ get(logicalId) {
224
+ const ret = this.diffs[logicalId];
225
+ if (!ret) {
226
+ throw new Error(`No object with logical ID '${logicalId}'`);
227
+ }
228
+ return ret;
229
+ }
230
+ remove(logicalId) {
231
+ delete this.diffs[logicalId];
232
+ }
233
+ get logicalIds() {
234
+ return Object.keys(this.changes);
235
+ }
236
+ /**
237
+ * Returns a new TemplateDiff which only contains changes for which `predicate`
238
+ * returns `true`.
239
+ */
240
+ filter(predicate) {
241
+ const newChanges = {};
242
+ for (const id of Object.keys(this.changes)) {
243
+ const diff = this.changes[id];
244
+ if (predicate(diff)) {
245
+ newChanges[id] = diff;
246
+ }
247
+ }
248
+ return new DifferenceCollection(newChanges);
249
+ }
250
+ /**
251
+ * Invokes `cb` for all changes in this collection.
252
+ *
253
+ * Changes will be sorted as follows:
254
+ * - Removed
255
+ * - Added
256
+ * - Updated
257
+ * - Others
258
+ *
259
+ */
260
+ forEachDifference(cb) {
261
+ const removed = new Array();
262
+ const added = new Array();
263
+ const updated = new Array();
264
+ const others = new Array();
265
+ for (const logicalId of this.logicalIds) {
266
+ const change = this.changes[logicalId];
267
+ if (change.isAddition) {
268
+ added.push({ logicalId, change });
269
+ }
270
+ else if (change.isRemoval) {
271
+ removed.push({ logicalId, change });
272
+ }
273
+ else if (change.isUpdate) {
274
+ updated.push({ logicalId, change });
275
+ }
276
+ else if (change.isDifferent) {
277
+ others.push({ logicalId, change });
278
+ }
279
+ }
280
+ removed.forEach(v => cb(v.logicalId, v.change));
281
+ added.forEach(v => cb(v.logicalId, v.change));
282
+ updated.forEach(v => cb(v.logicalId, v.change));
283
+ others.forEach(v => cb(v.logicalId, v.change));
284
+ }
285
+ }
286
+ exports.DifferenceCollection = DifferenceCollection;
287
+ class ConditionDifference extends Difference {
288
+ }
289
+ exports.ConditionDifference = ConditionDifference;
290
+ class MappingDifference extends Difference {
291
+ }
292
+ exports.MappingDifference = MappingDifference;
293
+ class MetadataDifference extends Difference {
294
+ }
295
+ exports.MetadataDifference = MetadataDifference;
296
+ class OutputDifference extends Difference {
297
+ }
298
+ exports.OutputDifference = OutputDifference;
299
+ class ParameterDifference extends Difference {
300
+ }
301
+ exports.ParameterDifference = ParameterDifference;
302
+ var ResourceImpact;
303
+ (function (ResourceImpact) {
304
+ /** The existing physical resource will be updated */
305
+ ResourceImpact["WILL_UPDATE"] = "WILL_UPDATE";
306
+ /** A new physical resource will be created */
307
+ ResourceImpact["WILL_CREATE"] = "WILL_CREATE";
308
+ /** The existing physical resource will be replaced */
309
+ ResourceImpact["WILL_REPLACE"] = "WILL_REPLACE";
310
+ /** The existing physical resource may be replaced */
311
+ ResourceImpact["MAY_REPLACE"] = "MAY_REPLACE";
312
+ /** The existing physical resource will be destroyed */
313
+ ResourceImpact["WILL_DESTROY"] = "WILL_DESTROY";
314
+ /** The existing physical resource will be removed from CloudFormation supervision */
315
+ ResourceImpact["WILL_ORPHAN"] = "WILL_ORPHAN";
316
+ /** The existing physical resource will be added to CloudFormation supervision */
317
+ ResourceImpact["WILL_IMPORT"] = "WILL_IMPORT";
318
+ /** There is no change in this resource */
319
+ ResourceImpact["NO_CHANGE"] = "NO_CHANGE";
320
+ })(ResourceImpact || (exports.ResourceImpact = ResourceImpact = {}));
321
+ /**
322
+ * This function can be used as a reducer to obtain the resource-level impact of a list
323
+ * of property-level impacts.
324
+ * @param one the current worst impact so far.
325
+ * @param two the new impact being considered (can be undefined, as we may not always be
326
+ * able to determine some properties impact).
327
+ */
328
+ function worstImpact(one, two) {
329
+ if (!two) {
330
+ return one;
331
+ }
332
+ const badness = {
333
+ [ResourceImpact.NO_CHANGE]: 0,
334
+ [ResourceImpact.WILL_IMPORT]: 0,
335
+ [ResourceImpact.WILL_UPDATE]: 1,
336
+ [ResourceImpact.WILL_CREATE]: 2,
337
+ [ResourceImpact.WILL_ORPHAN]: 3,
338
+ [ResourceImpact.MAY_REPLACE]: 4,
339
+ [ResourceImpact.WILL_REPLACE]: 5,
340
+ [ResourceImpact.WILL_DESTROY]: 6,
341
+ };
342
+ return badness[one] > badness[two] ? one : two;
343
+ }
344
+ /**
345
+ * Change to a single resource between two CloudFormation templates
346
+ *
347
+ * This class can be mutated after construction.
348
+ */
349
+ class ResourceDifference {
350
+ constructor(oldValue, newValue, args) {
351
+ this.oldValue = oldValue;
352
+ this.newValue = newValue;
353
+ this.resourceTypes = args.resourceType;
354
+ this.propertyDiffs = args.propertyDiffs;
355
+ this.otherDiffs = args.otherDiffs;
356
+ this.isAddition = oldValue === undefined;
357
+ this.isRemoval = newValue === undefined;
358
+ this.isImport = undefined;
359
+ }
360
+ get oldProperties() {
361
+ return this.oldValue && this.oldValue.Properties;
362
+ }
363
+ get newProperties() {
364
+ return this.newValue && this.newValue.Properties;
365
+ }
366
+ /**
367
+ * Whether this resource was modified at all
368
+ */
369
+ get isDifferent() {
370
+ return this.differenceCount > 0 || this.oldResourceType !== this.newResourceType;
371
+ }
372
+ /**
373
+ * Whether the resource was updated in-place
374
+ */
375
+ get isUpdate() {
376
+ return this.isDifferent && !this.isAddition && !this.isRemoval;
377
+ }
378
+ get oldResourceType() {
379
+ return this.resourceTypes.oldType;
380
+ }
381
+ get newResourceType() {
382
+ return this.resourceTypes.newType;
383
+ }
384
+ /**
385
+ * All actual property updates
386
+ */
387
+ get propertyUpdates() {
388
+ return onlyChanges(this.propertyDiffs);
389
+ }
390
+ /**
391
+ * All actual "other" updates
392
+ */
393
+ get otherChanges() {
394
+ return onlyChanges(this.otherDiffs);
395
+ }
396
+ /**
397
+ * Return whether the resource type was changed in this diff
398
+ *
399
+ * This is not a valid operation in CloudFormation but to be defensive we're going
400
+ * to be aware of it anyway.
401
+ */
402
+ get resourceTypeChanged() {
403
+ return (this.resourceTypes.oldType !== undefined
404
+ && this.resourceTypes.newType !== undefined
405
+ && this.resourceTypes.oldType !== this.resourceTypes.newType);
406
+ }
407
+ /**
408
+ * Return the resource type if it was unchanged
409
+ *
410
+ * If the resource type was changed, it's an error to call this.
411
+ */
412
+ get resourceType() {
413
+ if (this.resourceTypeChanged) {
414
+ throw new Error('Cannot get .resourceType, because the type was changed');
415
+ }
416
+ return this.resourceTypes.oldType || this.resourceTypes.newType;
417
+ }
418
+ /**
419
+ * Replace a PropertyChange in this object
420
+ *
421
+ * This affects the property diff as it is summarized to users, but it DOES
422
+ * NOT affect either the "oldValue" or "newValue" values; those still contain
423
+ * the actual template values as provided by the user (they might still be
424
+ * used for downstream processing).
425
+ */
426
+ setPropertyChange(propertyName, change) {
427
+ this.propertyDiffs[propertyName] = change;
428
+ }
429
+ /**
430
+ * Replace a OtherChange in this object
431
+ *
432
+ * This affects the property diff as it is summarized to users, but it DOES
433
+ * NOT affect either the "oldValue" or "newValue" values; those still contain
434
+ * the actual template values as provided by the user (they might still be
435
+ * used for downstream processing).
436
+ */
437
+ setOtherChange(otherName, change) {
438
+ this.otherDiffs[otherName] = change;
439
+ }
440
+ get changeImpact() {
441
+ if (this.isImport) {
442
+ return ResourceImpact.WILL_IMPORT;
443
+ }
444
+ // Check the Type first
445
+ if (this.resourceTypes.oldType !== this.resourceTypes.newType) {
446
+ if (this.resourceTypes.oldType === undefined) {
447
+ return ResourceImpact.WILL_CREATE;
448
+ }
449
+ if (this.resourceTypes.newType === undefined) {
450
+ return this.oldValue.DeletionPolicy === 'Retain'
451
+ ? ResourceImpact.WILL_ORPHAN
452
+ : ResourceImpact.WILL_DESTROY;
453
+ }
454
+ return ResourceImpact.WILL_REPLACE;
455
+ }
456
+ // Base impact (before we mix in the worst of the property impacts);
457
+ // WILL_UPDATE if we have "other" changes, NO_CHANGE if there are no "other" changes.
458
+ const baseImpact = Object.keys(this.otherChanges).length > 0 ? ResourceImpact.WILL_UPDATE : ResourceImpact.NO_CHANGE;
459
+ return Object.values(this.propertyDiffs)
460
+ .map(elt => elt.changeImpact)
461
+ .reduce(worstImpact, baseImpact);
462
+ }
463
+ /**
464
+ * Count of actual differences (not of elements)
465
+ */
466
+ get differenceCount() {
467
+ return Object.values(this.propertyUpdates).length
468
+ + Object.values(this.otherChanges).length;
469
+ }
470
+ /**
471
+ * Invoke a callback for each actual difference
472
+ */
473
+ forEachDifference(cb) {
474
+ for (const key of Object.keys(this.propertyUpdates).sort()) {
475
+ cb('Property', key, this.propertyUpdates[key]);
476
+ }
477
+ for (const key of Object.keys(this.otherChanges).sort()) {
478
+ cb('Other', key, this.otherDiffs[key]);
479
+ }
480
+ }
481
+ }
482
+ exports.ResourceDifference = ResourceDifference;
483
+ function isPropertyDifference(diff) {
484
+ return diff.changeImpact !== undefined;
485
+ }
486
+ /**
487
+ * Filter a map of IDifferences down to only retain the actual changes
488
+ */
489
+ function onlyChanges(xs) {
490
+ const ret = {};
491
+ for (const [key, diff] of Object.entries(xs)) {
492
+ if (diff.isDifferent) {
493
+ ret[key] = diff;
494
+ }
495
+ }
496
+ return ret;
497
+ }
498
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ0eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFzdEJBLG9EQUVDO0FBeHRCRCxtQ0FBd0M7QUFDeEMsb0VBQW9IO0FBQ3BILGlDQUFzRDtBQUN0RCxvREFBZ0Q7QUFDaEQsOEVBQXlFO0FBZ0N6RSxpRUFBaUU7QUFDakUsTUFBYSxZQUFZO0lBdUJ2QixZQUFZLElBQW1CO1FBQzdCLElBQUksSUFBSSxDQUFDLHdCQUF3QixLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ2hELElBQUksQ0FBQyx3QkFBd0IsR0FBRyxJQUFJLENBQUMsd0JBQXdCLENBQUM7UUFDaEUsQ0FBQztRQUNELElBQUksSUFBSSxDQUFDLFdBQVcsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUNuQyxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUM7UUFDdEMsQ0FBQztRQUNELElBQUksSUFBSSxDQUFDLFNBQVMsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUNqQyxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUM7UUFDbEMsQ0FBQztRQUVELElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsSUFBSSxJQUFJLG9CQUFvQixDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ2xFLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsSUFBSSxJQUFJLG9CQUFvQixDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQzlELElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsSUFBSSxJQUFJLG9CQUFvQixDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQzlELElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sSUFBSSxJQUFJLG9CQUFvQixDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQzVELElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsSUFBSSxJQUFJLG9C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QUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDO1FBQzdDLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1lBQ3JCLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUM7UUFDbEIsQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBBc3NlcnRpb25FcnJvciB9IGZyb20gJ2Fzc2VydCc7XG5pbXBvcnQgeyBQcm9wZXJ0eVNjcnV0aW55VHlwZSwgUmVzb3VyY2VTY3J1dGlueVR5cGUsIFJlc291cmNlIGFzIFJlc291cmNlTW9kZWwgfSBmcm9tICdAYXdzLWNkay9zZXJ2aWNlLXNwZWMtdHlwZXMnO1xuaW1wb3J0IHsgZGVlcEVxdWFsLCBsb2FkUmVzb3VyY2VNb2RlbCB9IGZyb20gJy4vdXRpbCc7XG5pbXBvcnQgeyBJYW1DaGFuZ2VzIH0gZnJvbSAnLi4vaWFtL2lhbS1jaGFuZ2VzJztcbmltcG9ydCB7IFNlY3VyaXR5R3JvdXBDaGFuZ2VzIH0gZnJvbSAnLi4vbmV0d29yay9zZWN1cml0eS1ncm91cC1jaGFuZ2VzJztcblxuZXhwb3J0IHR5cGUgUHJvcGVydHlNYXAgPSB7W2tleTogc3RyaW5nXTogYW55IH07XG5cbmV4cG9ydCB0eXBlIENoYW5nZVNldFJlc291cmNlcyA9IHsgW2xvZ2ljYWxJZDogc3RyaW5nXTogQ2hhbmdlU2V0UmVzb3VyY2UgfTtcblxuLyoqXG4gKiBAcGFyYW0gYmVmb3JlQ29udGV4dCBpcyB0aGUgQmVmb3JlQ29udGV4dCBmaWVsZCBmcm9tIHRoZSBDaGFuZ2VTZXQuUmVzb3VyY2VDaGFuZ2UuQmVmb3JlQ29udGV4dC4gVGhpcyBpcyB0aGUgcGFydCBvZiB0aGUgQ2xvdWRGb3JtYXRpb24gdGVtcGxhdGVcbiAqIHRoYXQgZGVmaW5lcyB3aGF0IHRoZSByZXNvdXJjZSBpcyBiZWZvcmUgdGhlIGNoYW5nZSBpcyBhcHBsaWVkOyB0aGF0IGlzLCBCZWZvcmVDb250ZXh0IGlzIENsb3VkRm9ybWF0aW9uVGVtcGxhdGUuUmVzb3VyY2VzW0xvZ2ljYWxJZF0gYmVmb3JlIHRoZSBDaGFuZ2VTZXQgaXMgZXhlY3V0ZWQuXG4gKlxuICogQHBhcmFtIGFmdGVyQ29udGV4dCBzYW1lIGFzIGJlZm9yZUNvbnRleHQgYnV0IGZvciBhZnRlciB0aGUgY2hhbmdlIGlzIG1hZGU7IHRoYXQgaXMsIEFmdGVyQ29udGV4dCBpcyBDbG91ZEZvcm1hdGlvblRlbXBsYXRlLlJlc291cmNlc1tMb2dpY2FsSWRdIGFmdGVyIHRoZSBDaGFuZ2VTZXQgaXMgZXhlY3V0ZWQuXG4gKlxuICogICogSGVyZSBpcyBhbiBleGFtcGxlIG9mIHdoYXQgYSBiZWZvcmVDb250ZXh0L2FmdGVyQ29udGV4dCBsb29rcyBsaWtlOlxuICogICd7XCJQcm9wZXJ0aWVzXCI6e1wiVmFsdWVcIjpcInNkZmxramFcIixcIlR5cGVcIjpcIlN0cmluZ1wiLFwiTmFtZVwiOlwibXlTc21QYXJhbWV0ZXJGcm9tU3RhY2tcIn0sXCJNZXRhZGF0YVwiOntcImF3czpjZGs6cGF0aFwiOlwiY2RrL215U3NtUGFyYW1ldGVyL1Jlc291cmNlXCJ9fSdcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDaGFuZ2VTZXRSZXNvdXJjZSB7XG4gIHJlc291cmNlV2FzUmVwbGFjZWQ6IGJvb2xlYW47XG4gIHJlc291cmNlVHlwZTogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICBwcm9wZXJ0eVJlcGxhY2VtZW50TW9kZXM6IFByb3BlcnR5UmVwbGFjZW1lbnRNb2RlTWFwIHwgdW5kZWZpbmVkO1xufVxuXG5leHBvcnQgdHlwZSBQcm9wZXJ0eVJlcGxhY2VtZW50TW9kZU1hcCA9IHtcbiAgW3Byb3BlcnR5TmFtZTogc3RyaW5nXToge1xuICAgIHJlcGxhY2VtZW50TW9kZTogUmVwbGFjZW1lbnRNb2RlcyB8IHVuZGVmaW5lZDtcbiAgfTtcbn1cblxuLyoqXG4gKiAnQWx3YXlzJyBtZWFucyB0aGF0IGNoYW5naW5nIHRoZSBjb3JyZXNwb25kaW5nIHByb3BlcnR5IHdpbGwgYWx3YXlzIGNhdXNlIGEgcmVzb3VyY2UgcmVwbGFjZW1lbnQuIE5ldmVyIG1lYW5zIG5ldmVyLiBDb25kaXRpb25hbGx5IG1lYW5zIG1heWJlLlxuICovXG5leHBvcnQgdHlwZSBSZXBsYWNlbWVudE1vZGVzID0gJ0Fsd2F5cycgfCAnTmV2ZXInIHwgJ0NvbmRpdGlvbmFsbHknO1xuXG4vKiogU2VtYW50aWMgZGlmZmVyZW5jZXMgYmV0d2VlbiB0d28gQ2xvdWRGb3JtYXRpb24gdGVtcGxhdGVzLiAqL1xuZXhwb3J0IGNsYXNzIFRlbXBsYXRlRGlmZiBpbXBsZW1lbnRzIElUZW1wbGF0ZURpZmYge1xuICBwdWJsaWMgYXdzVGVtcGxhdGVGb3JtYXRWZXJzaW9uPzogRGlmZmVyZW5jZTxzdHJpbmc+O1xuICBwdWJsaWMgZGVzY3JpcHRpb24/OiBEaWZmZXJlbmNlPHN0cmluZz47XG4gIHB1YmxpYyB0cmFuc2Zvcm0/OiBEaWZmZXJlbmNlPHN0cmluZz47XG4gIHB1YmxpYyBjb25kaXRpb25zOiBEaWZmZXJlbmNlQ29sbGVjdGlvbjxDb25kaXRpb24sIENvbmRpdGlvbkRpZmZlcmVuY2U+O1xuICBwdWJsaWMgbWFwcGluZ3M6IERpZmZlcmVuY2VDb2xsZWN0aW9uPE1hcHBpbmcsIE1hcHBpbmdEaWZmZXJlbmNlPjtcbiAgcHVibGljIG1ldGFkYXRhOiBEaWZmZXJlbmNlQ29sbGVjdGlvbjxNZXRhZGF0YSwgTWV0YWRhdGFEaWZmZXJlbmNlPjtcbiAgcHVibGljIG91dHB1dHM6IERpZmZlcmVuY2VDb2xsZWN0aW9uPE91dHB1dCwgT3V0cHV0RGlmZmVyZW5jZT47XG4gIHB1YmxpYyBwYXJhbWV0ZXJzOiBEaWZmZXJlbmNlQ29sbGVjdGlvbjxQYXJhbWV0ZXIsIFBhcmFtZXRlckRpZmZlcmVuY2U+O1xuICBwdWJsaWMgcmVzb3VyY2VzOiBEaWZmZXJlbmNlQ29sbGVjdGlvbjxSZXNvdXJjZSwgUmVzb3VyY2VEaWZmZXJlbmNlPjtcbiAgLyoqIFRoZSBkaWZmZXJlbmNlcyBpbiB1bmtub3duL3VuZXhwZWN0ZWQgcGFydHMgb2YgdGhlIHRlbXBsYXRlICovXG4gIHB1YmxpYyB1bmtub3duOiBEaWZmZXJlbmNlQ29sbGVjdGlvbjxhbnksIERpZmZlcmVuY2U8YW55Pj47XG5cbiAgLyoqXG4gICAqIENoYW5nZXMgdG8gSUFNIHBvbGljaWVzXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgaWFtQ2hhbmdlczogSWFtQ2hhbmdlcztcblxuICAvKipcbiAgICogQ2hhbmdlcyB0byBTZWN1cml0eSBHcm91cCBpbmdyZXNzIGFuZCBlZ3Jlc3MgcnVsZXNcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBzZWN1cml0eUdyb3VwQ2hhbmdlczogU2VjdXJpdHlHcm91cENoYW5nZXM7XG5cbiAgY29uc3RydWN0b3IoYXJnczogSVRlbXBsYXRlRGlmZikge1xuICAgIGlmIChhcmdzLmF3c1RlbXBsYXRlRm9ybWF0VmVyc2lvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmF3c1RlbXBsYXRlRm9ybWF0VmVyc2lvbiA9IGFyZ3MuYXdzVGVtcGxhdGVGb3JtYXRWZXJzaW9uO1xuICAgIH1cbiAgICBpZiAoYXJncy5kZXNjcmlwdGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmRlc2NyaXB0aW9uID0gYXJncy5kZXNjcmlwdGlvbjtcbiAgICB9XG4gICAgaWYgKGFyZ3MudHJhbnNmb3JtICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMudHJhbnNmb3JtID0gYXJncy50cmFuc2Zvcm07XG4gICAgfVxuXG4gICAgdGhpcy5jb25kaXRpb25zID0gYXJncy5jb25kaXRpb25zIHx8IG5ldyBEaWZmZXJlbmNlQ29sbGVjdGlvbih7fSk7XG4gICAgdGhpcy5tYXBwaW5ncyA9IGFyZ3MubWFwcGluZ3MgfHwgbmV3IERpZmZlcmVuY2VDb2xsZWN0aW9uKHt9KTtcbiAgICB0aGlzLm1ldGFkYXRhID0gYXJncy5tZXRhZGF0YSB8fCBuZXcgRGlmZmVyZW5jZUNvbGxlY3Rpb24oe30pO1xuICAgIHRoaXMub3V0cHV0cyA9IGFyZ3Mub3V0cHV0cyB8fCBuZXcgRGlmZmVyZW5jZUNvbGxlY3Rpb24oe30pO1xuICAgIHRoaXMucGFyYW1ldGVycyA9IGFyZ3MucGFyYW1ldGVycyB8fCBuZXcgRGlmZmVyZW5jZUNvbGxlY3Rpb24oe30pO1xuICAgIHRoaXMucmVzb3VyY2VzID0gYXJncy5yZXNvdXJjZXMgfHwgbmV3IERpZmZlcmVuY2VDb2xsZWN0aW9uKHt9KTtcbiAgICB0aGlzLnVua25vd24gPSBhcmdzLnVua25vd24gfHwgbmV3IERpZmZlcmVuY2VDb2xsZWN0aW9uKHt9KTtcblxuICAgIHRoaXMuaWFtQ2hhbmdlcyA9IG5ldyBJYW1DaGFuZ2VzKHtcbiAgICAgIHByb3BlcnR5Q2hhbmdlczogdGhpcy5zY3J1dGluaXphYmxlUHJvcGVydHlDaGFuZ2VzKElhbUNoYW5nZXMuSWFtUHJvcGVydHlTY3J1dGluaWVzKSxcbiAgICAgIHJlc291cmNlQ2hhbmdlczogdGhpcy5zY3J1dGluaXphYmxlUmVzb3VyY2VDaGFuZ2VzKElhbUNoYW5nZXMuSWFtUmVzb3VyY2VTY3J1dGluaWVzKSxcbiAgICB9KTtcblxuICAgIHRoaXMuc2VjdXJpdHlHcm91cENoYW5nZXMgPSBuZXcgU2VjdXJpdHlHcm91cENoYW5nZXMoe1xuICAgICAgZWdyZXNzUnVsZVByb3BlcnR5Q2hhbmdlczogdGhpcy5zY3J1dGluaXphYmxlUHJvcGVydHlDaGFuZ2VzKFtQcm9wZXJ0eVNjcnV0aW55VHlwZS5FZ3Jlc3NSdWxlc10pLFxuICAgICAgaW5ncmVzc1J1bGVQcm9wZXJ0eUNoYW5nZXM6IHRoaXMuc2NydXRpbml6YWJsZVByb3BlcnR5Q2hhbmdlcyhbUHJvcGVydHlTY3J1dGlueVR5cGUuSW5ncmVzc1J1bGVzXSksXG4gICAgICBlZ3Jlc3NSdWxlUmVzb3VyY2VDaGFuZ2VzOiB0aGlzLnNjcnV0aW5pemFibGVSZXNvdXJjZUNoYW5nZXMoW1Jlc291cmNlU2NydXRpbnlUeXBlLkVncmVzc1J1bGVSZXNvdXJjZV0pLFxuICAgICAgaW5ncmVzc1J1bGVSZXNvdXJjZUNoYW5nZXM6IHRoaXMuc2NydXRpbml6YWJsZVJlc291cmNlQ2hhbmdlcyhbUmVzb3VyY2VTY3J1dGlueVR5cGUuSW5ncmVzc1J1bGVSZXNvdXJjZV0pLFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGdldCBkaWZmZXJlbmNlQ291bnQoKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGlmICh0aGlzLmF3c1RlbXBsYXRlRm9ybWF0VmVyc2lvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb3VudCArPSAxO1xuICAgIH1cbiAgICBpZiAodGhpcy5kZXNjcmlwdGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb3VudCArPSAxO1xuICAgIH1cbiAgICBpZiAodGhpcy50cmFuc2Zvcm0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgY291bnQgKz0gMTtcbiAgICB9XG5cbiAgICBjb3VudCArPSB0aGlzLmNvbmRpdGlvbnMuZGlmZmVyZW5jZUNvdW50O1xuICAgIGNvdW50ICs9IHRoaXMubWFwcGluZ3MuZGlmZmVyZW5jZUNvdW50O1xuICAgIGNvdW50ICs9IHRoaXMubWV0YWRhdGEuZGlmZmVyZW5jZUNvdW50O1xuICAgIGNvdW50ICs9IHRoaXMub3V0cHV0cy5kaWZmZXJlbmNlQ291bnQ7XG4gICAgY291bnQgKz0gdGhpcy5wYXJhbWV0ZXJzLmRpZmZlcmVuY2VDb3VudDtcbiAgICBjb3VudCArPSB0aGlzLnJlc291cmNlcy5kaWZmZXJlbmNlQ291bnQ7XG4gICAgY291bnQgKz0gdGhpcy51bmtub3duLmRpZmZlcmVuY2VDb3VudDtcblxuICAgIHJldHVybiBjb3VudDtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgaXNFbXB0eSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5kaWZmZXJlbmNlQ291bnQgPT09IDA7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIHRydWUgaWYgYW55IG9mIHRoZSBwZXJtaXNzaW9ucyBvYmplY3RzIGludm9sdmUgYSBicm9hZGVuaW5nIG9mIHBlcm1pc3Npb25zXG4gICAqL1xuICBwdWJsaWMgZ2V0IHBlcm1pc3Npb25zQnJvYWRlbmVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmlhbUNoYW5nZXMucGVybWlzc2lvbnNCcm9hZGVuZWQgfHwgdGhpcy5zZWN1cml0eUdyb3VwQ2hhbmdlcy5ydWxlc0FkZGVkO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiB0cnVlIGlmIGFueSBvZiB0aGUgcGVybWlzc2lvbnMgb2JqZWN0cyBoYXZlIGNoYW5nZWRcbiAgICovXG4gIHB1YmxpYyBnZXQgcGVybWlzc2lvbnNBbnlDaGFuZ2VzKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmlhbUNoYW5nZXMuaGFzQ2hhbmdlcyB8fCB0aGlzLnNlY3VyaXR5R3JvdXBDaGFuZ2VzLmhhc0NoYW5nZXM7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIGFsbCBwcm9wZXJ0eSBjaGFuZ2VzIG9mIGEgZ2l2ZW4gc2NydXRpbnkgdHlwZVxuICAgKlxuICAgKiBXZSBkb24ndCBqdXN0IGxvb2sgYXQgcHJvcGVydHkgdXBkYXRlczsgd2UgYWxzbyBsb29rIGF0IHJlc291cmNlIGFkZGl0aW9ucyBhbmQgZGVsZXRpb25zIChpbiB3aGljaFxuICAgKiBjYXNlIHRoZXJlIGlzIG5vIGZ1cnRoZXIgZGV0YWlsIG9uIHByb3BlcnR5IHZhbHVlcyksIGFuZCByZXNvdXJjZSB0eXBlIGNoYW5nZXMuXG4gICAqL1xuICBwcml2YXRlIHNjcnV0aW5pemFibGVQcm9wZXJ0eUNoYW5nZXMoc2NydXRpbnlUeXBlczogUHJvcGVydHlTY3J1dGlueVR5cGVbXSk6IFByb3BlcnR5Q2hhbmdlW10ge1xuICAgIGNvbnN0IHJldCA9IG5ldyBBcnJheTxQcm9wZXJ0eUNoYW5nZT4oKTtcblxuICAgIGZvciAoY29uc3QgW3Jlc291cmNlTG9naWNhbElkLCByZXNvdXJjZUNoYW5nZV0gb2YgT2JqZWN0LmVudHJpZXModGhpcy5yZXNvdXJjZXMuY2hhbmdlcykpIHtcbiAgICAgIGlmIChyZXNvdXJjZUNoYW5nZS5yZXNvdXJjZVR5cGVDaGFuZ2VkKSB7XG4gICAgICAgIC8vIHdlIGlnbm9yZSByZXNvdXJjZSB0eXBlIGNoYW5nZXMgaGVyZSwgYW5kIGhhbmRsZSB0aGVtIGluIHNjcnV0aW5pemFibGVSZXNvdXJjZUNoYW5nZXMoKVxuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKCFyZXNvdXJjZUNoYW5nZS5yZXNvdXJjZVR5cGUpIHtcbiAgICAgICAgLy8gV2UgdXNlIHJlc291cmNlQ2hhbmdlLnJlc291cmNlVHlwZSB0byBsb2FkUmVzb3VyY2VNb2RlbCBzbyB0aGF0IHdlIGNhbiBpbnNwZWN0IHRoZVxuICAgICAgICAvLyBwcm9wZXJ0aWVzIG9mIGEgcmVzb3VyY2UgZXZlbiBhZnRlciB0aGUgcmVzb3VyY2UgaXMgcmVtb3ZlZCBmcm9tIHRoZSB0ZW1wbGF0ZS5cbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG5ld1R5cGVQcm9wcyA9IGxvYWRSZXNvdXJjZU1vZGVsKHJlc291cmNlQ2hhbmdlLnJlc291cmNlVHlwZSk/LnByb3BlcnRpZXMgfHwge307XG4gICAgICBmb3IgKGNvbnN0IFtwcm9wZXJ0eU5hbWUsIHByb3BdIG9mIE9iamVjdC5lbnRyaWVzKG5ld1R5cGVQcm9wcykpIHtcbiAgICAgICAgY29uc3QgcHJvcFNjcnV0aW55VHlwZSA9IHByb3Auc2NydXRpbml6YWJsZSB8fCBQcm9wZXJ0eVNjcnV0aW55VHlwZS5Ob25lO1xuICAgICAgICBpZiAoc2NydXRpbnlUeXBlcy5pbmNsdWRlcyhwcm9wU2NydXRpbnlUeXBlKSkge1xuICAgICAgICAgIHJldC5wdXNoKHtcbiAgICAgICAgICAgIHJlc291cmNlTG9naWNhbElkLFxuICAgICAgICAgICAgcHJvcGVydHlOYW1lLFxuICAgICAgICAgICAgcmVzb3VyY2VUeXBlOiByZXNvdXJjZUNoYW5nZS5yZXNvdXJjZVR5cGUsXG4gICAgICAgICAgICBzY3J1dGlueVR5cGU6IHByb3BTY3J1dGlueVR5cGUsXG4gICAgICAgICAgICBvbGRWYWx1ZTogcmVzb3VyY2VDaGFuZ2Uub2xkUHJvcGVydGllcz8uW3Byb3BlcnR5TmFtZV0sXG4gICAgICAgICAgICBuZXdWYWx1ZTogcmVzb3VyY2VDaGFuZ2UubmV3UHJvcGVydGllcz8uW3Byb3BlcnR5TmFtZV0sXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmV0O1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiBhbGwgcmVzb3VyY2UgY2hhbmdlcyBvZiBhIGdpdmVuIHNjcnV0aW55IHR5cGVcbiAgICpcbiAgICogV2UgZG9uJ3QganVzdCBsb29rIGF0IHJlc291cmNlIHVwZGF0ZXM7IHdlIGFsc28gbG9vayBhdCByZXNvdXJjZSBhZGRpdGlvbnMgYW5kIGRlbGV0aW9ucyAoaW4gd2hpY2hcbiAgICogY2FzZSB0aGVyZSBpcyBubyBmdXJ0aGVyIGRldGFpbCBvbiBwcm9wZXJ0eSB2YWx1ZXMpLCBhbmQgcmVzb3VyY2UgdHlwZSBjaGFuZ2VzLlxuICAgKi9cbiAgcHJpdmF0ZSBzY3J1dGluaXphYmxlUmVzb3VyY2VDaGFuZ2VzKHNjcnV0aW55VHlwZXM6IFJlc291cmNlU2NydXRpbnlUeXBlW10pOiBSZXNvdXJjZUNoYW5nZVtdIHtcbiAgICBjb25zdCByZXQgPSBuZXcgQXJyYXk8UmVzb3VyY2VDaGFuZ2U+KCk7XG5cbiAgICBmb3IgKGNvbnN0IFtyZXNvdXJjZUxvZ2ljYWxJZCwgcmVzb3VyY2VDaGFuZ2VdIG9mIE9iamVjdC5lbnRyaWVzKHRoaXMucmVzb3VyY2VzLmNoYW5nZXMpKSB7XG4gICAgICBpZiAoIXJlc291cmNlQ2hhbmdlKSB7IGNvbnRpbnVlOyB9XG5cbiAgICAgIGNvbnN0IGNvbW1vblByb3BzID0ge1xuICAgICAgICBvbGRQcm9wZXJ0aWVzOiByZXNvdXJjZUNoYW5nZS5vbGRQcm9wZXJ0aWVzLFxuICAgICAgICBuZXdQcm9wZXJ0aWVzOiByZXNvdXJjZUNoYW5nZS5uZXdQcm9wZXJ0aWVzLFxuICAgICAgICByZXNvdXJjZUxvZ2ljYWxJZCxcbiAgICAgIH07XG5cbiAgICAgIC8vIGNoYW5nZXMgdG8gdGhlIFR5cGUgb2YgcmVzb3VyY2VzIGNhbiBoYXBwZW4gd2hlbiBtaWdyYXRpbmcgZnJvbSBDRk4gdGVtcGxhdGVzIHRoYXQgdXNlIFRyYW5zZm9ybXNcbiAgICAgIGlmIChyZXNvdXJjZUNoYW5nZS5yZXNvdXJjZVR5cGVDaGFuZ2VkKSB7XG4gICAgICAgIC8vIFRyZWF0IGFzIERFTEVURStBRERcbiAgICAgICAgaWYgKHJlc291cmNlQ2hhbmdlLm9sZFJlc291cmNlVHlwZSkge1xuICAgICAgICAgIGNvbnN0IG9sZFJlc291cmNlTW9kZWwgPSBsb2FkUmVzb3VyY2VNb2RlbChyZXNvdXJjZUNoYW5nZS5vbGRSZXNvdXJjZVR5cGUpO1xuICAgICAgICAgIGlmIChvbGRSZXNvdXJjZU1vZGVsICYmIHRoaXMucmVzb3VyY2VJc1NjcnV0aW5pemFibGUob2xkUmVzb3VyY2VNb2RlbCwgc2NydXRpbnlUeXBlcykpIHtcbiAgICAgICAgICAgIHJldC5wdXNoKHtcbiAgICAgICAgICAgICAgLi4uY29tbW9uUHJvcHMsXG4gICAgICAgICAgICAgIG5ld1Byb3BlcnRpZXM6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgcmVzb3VyY2VUeXBlOiByZXNvdXJjZUNoYW5nZS5vbGRSZXNvdXJjZVR5cGUhLFxuICAgICAgICAgICAgICBzY3J1dGlueVR5cGU6IG9sZFJlc291cmNlTW9kZWwuc2NydXRpbml6YWJsZSEsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocmVzb3VyY2VDaGFuZ2UubmV3UmVzb3VyY2VUeXBlKSB7XG4gICAgICAgICAgY29uc3QgbmV3UmVzb3VyY2VNb2RlbCA9IGxvYWRSZXNvdXJjZU1vZGVsKHJlc291cmNlQ2hhbmdlLm5ld1Jlc291cmNlVHlwZSk7XG4gICAgICAgICAgaWYgKG5ld1Jlc291cmNlTW9kZWwgJiYgdGhpcy5yZXNvdXJjZUlzU2NydXRpbml6YWJsZShuZXdSZXNvdXJjZU1vZGVsLCBzY3J1dGlueVR5cGVzKSkge1xuICAgICAgICAgICAgcmV0LnB1c2goe1xuICAgICAgICAgICAgICAuLi5jb21tb25Qcm9wcyxcbiAgICAgICAgICAgICAgb2xkUHJvcGVydGllczogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICByZXNvdXJjZVR5cGU6IHJlc291cmNlQ2hhbmdlLm5ld1Jlc291cmNlVHlwZSEsXG4gICAgICAgICAgICAgIHNjcnV0aW55VHlwZTogbmV3UmVzb3VyY2VNb2RlbC5zY3J1dGluaXphYmxlISxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKCFyZXNvdXJjZUNoYW5nZS5yZXNvdXJjZVR5cGUpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlc291cmNlTW9kZWwgPSBsb2FkUmVzb3VyY2VNb2RlbChyZXNvdXJjZUNoYW5nZS5yZXNvdXJjZVR5cGUpO1xuICAgICAgICBpZiAocmVzb3VyY2VNb2RlbCAmJiB0aGlzLnJlc291cmNlSXNTY3J1dGluaXphYmxlKHJlc291cmNlTW9kZWwsIHNjcnV0aW55VHlwZXMpKSB7XG4gICAgICAgICAgcmV0LnB1c2goe1xuICAgICAgICAgICAgLi4uY29tbW9uUHJvcHMsXG4gICAgICAgICAgICByZXNvdXJjZVR5cGU6IHJlc291cmNlQ2hhbmdlLnJlc291cmNlVHlwZSxcbiAgICAgICAgICAgIHNjcnV0aW55VHlwZTogcmVzb3VyY2VNb2RlbC5zY3J1dGluaXphYmxlISxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICBwcml2YXRlIHJlc291cmNlSXNTY3J1dGluaXphYmxlKHJlczogUmVzb3VyY2VNb2RlbCwgc2NydXRpbnlUeXBlczogQXJyYXk8UmVzb3VyY2VTY3J1dGlueVR5cGU+KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHNjcnV0aW55VHlwZXMuaW5jbHVkZXMocmVzLnNjcnV0aW5pemFibGUgfHwgUmVzb3VyY2VTY3J1dGlueVR5cGUuTm9uZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBBIGNoYW5nZSBpbiBwcm9wZXJ0eSB2YWx1ZXNcbiAqXG4gKiBOb3QgbmVjZXNzYXJpbHkgYW4gdXBkYXRlLCBpdCBjb3VsZCBiZSB0aGF0IHRoZXJlIHVzZWQgdG8gYmUgbm8gdmFsdWUgdGhlcmVcbiAqIGJlY2F1c2UgdGhlcmUgd2FzIG5vIHJlc291cmNlLCBhbmQgbm93IHRoZXJlIGlzIChvciB2aWNlIHZlcnNhKS5cbiAqXG4gKiBUaGVyZWZvcmUsIHdlIGp1c3QgY29udGFpbiBwbGFpbiB2YWx1ZXMgYW5kIG5vdCBhIFByb3BlcnR5RGlmZmVyZW5jZTxhbnk+LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFByb3BlcnR5Q2hhbmdlIHtcbiAgLyoqXG4gICAqIExvZ2ljYWwgSUQgb2YgdGhlIHJlc291cmNlIHdoZXJlIHRoaXMgcHJvcGVydHkgY2hhbmdlIHdhcyBmb3VuZFxuICAgKi9cbiAgcmVzb3VyY2VMb2dpY2FsSWQ6IHN0cmluZztcblxuICAvKipcbiAgICogVHlwZSBvZiB0aGUgcmVzb3VyY2VcbiAgICovXG4gIHJlc291cmNlVHlwZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBTY3J1dGlueSB0eXBlIGZvciB0aGlzIHByb3BlcnR5IGNoYW5nZVxuICAgKi9cbiAgc2NydXRpbnlUeXBlOiBQcm9wZXJ0eVNjcnV0aW55VHlwZTtcblxuICAvKipcbiAgICogTmFtZSBvZiB0aGUgcHJvcGVydHkgdGhhdCBpcyBjaGFuZ2luZ1xuICAgKi9cbiAgcHJvcGVydHlOYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBvbGQgcHJvcGVydHkgdmFsdWVcbiAgICovXG4gIG9sZFZhbHVlPzogYW55O1xuXG4gIC8qKlxuICAgKiBUaGUgbmV3IHByb3BlcnR5IHZhbHVlXG4gICAqL1xuICBuZXdWYWx1ZT86IGFueTtcbn1cblxuLyoqXG4gKiBBIHJlc291cmNlIGNoYW5nZVxuICpcbiAqIEVpdGhlciBhIGNyZWF0aW9uLCBkZWxldGlvbiBvciB1cGRhdGUuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVzb3VyY2VDaGFuZ2Uge1xuICAvKipcbiAgICogTG9naWNhbCBJRCBvZiB0aGUgcmVzb3VyY2Ugd2hlcmUgdGhpcyBwcm9wZXJ0eSBjaGFuZ2Ugd2FzIGZvdW5kXG4gICAqL1xuICByZXNvdXJjZUxvZ2ljYWxJZDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBTY3J1dGlueSB0eXBlIGZvciB0aGlzIHJlc291cmNlIGNoYW5nZVxuICAgKi9cbiAgc2NydXRpbnlUeXBlOiBSZXNvdXJjZVNjcnV0aW55VHlwZTtcblxuICAvKipcbiAgICogVGhlIHR5cGUgb2YgdGhlIHJlc291cmNlXG4gICAqL1xuICByZXNvdXJjZVR5cGU6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIG9sZCBwcm9wZXJ0aWVzIHZhbHVlIChtaWdodCBiZSB1bmRlZmluZWQgaW4gY2FzZSBvZiBjcmVhdGlvbilcbiAgICovXG4gIG9sZFByb3BlcnRpZXM/OiBQcm9wZXJ0eU1hcDtcblxuICAvKipcbiAgICogVGhlIG5ldyBwcm9wZXJ0aWVzIHZhbHVlIChtaWdodCBiZSB1bmRlZmluZWQgaW4gY2FzZSBvZiBkZWxldGlvbilcbiAgICovXG4gIG5ld1Byb3BlcnRpZXM/OiBQcm9wZXJ0eU1hcDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJRGlmZmVyZW5jZTxWYWx1ZVR5cGU+IHtcbiAgcmVhZG9ubHkgb2xkVmFsdWU6IFZhbHVlVHlwZSB8IHVuZGVmaW5lZDtcbiAgcmVhZG9ubHkgbmV3VmFsdWU6IFZhbHVlVHlwZSB8IHVuZGVmaW5lZDtcbiAgcmVhZG9ubHkgaXNEaWZmZXJlbnQ6IGJvb2xlYW47XG4gIHJlYWRvbmx5IGlzQWRkaXRpb246IGJvb2xlYW47XG4gIHJlYWRvbmx5IGlzUmVtb3ZhbDogYm9vbGVhbjtcbiAgcmVhZG9ubHkgaXNVcGRhdGU6IGJvb2xlYW47XG59XG5cbi8qKlxuICogTW9kZWxzIGFuIGVudGl0eSB0aGF0IGNoYW5nZWQgYmV0d2VlbiB0d28gdmVyc2lvbnMgb2YgYSBDbG91ZEZvcm1hdGlvbiB0ZW1wbGF0ZS5cbiAqL1xuZXhwb3J0IGNsYXNzIERpZmZlcmVuY2U8VmFsdWVUeXBlPiBpbXBsZW1lbnRzIElEaWZmZXJlbmNlPFZhbHVlVHlwZT4ge1xuICAvKipcbiAgICogV2hldGhlciB0aGlzIGlzIGFuIGFjdHVhbCBkaWZmZXJlbnQgb3IgdGhlIHZhbHVlcyBhcmUgYWN0dWFsbHkgdGhlIHNhbWVcbiAgICpcbiAgICogaXNEaWZmZXJlbnQgPT4gKGlzVXBkYXRlIHwgaXNSZW1vdmVkIHwgaXNVcGRhdGUpXG4gICAqL1xuICBwdWJsaWMgaXNEaWZmZXJlbnQ6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEBwYXJhbSBvbGRWYWx1ZSB0aGUgb2xkIHZhbHVlLCBjYW5ub3QgYmUgZXF1YWwgKHRvIHRoZSBzZW5zZSBvZiArZGVlcEVxdWFsKykgdG8gK25ld1ZhbHVlKy5cbiAgICogQHBhcmFtIG5ld1ZhbHVlIHRoZSBuZXcgdmFsdWUsIGNhbm5vdCBiZSBlcXVhbCAodG8gdGhlIHNlbnNlIG9mICtkZWVwRXF1YWwrKSB0byArb2xkVmFsdWUrLlxuICAgKi9cbiAgY29uc3RydWN0b3IocHVibGljIHJlYWRvbmx5IG9sZFZhbHVlOiBWYWx1ZVR5cGUgfCB1bmRlZmluZWQsIHB1YmxpYyByZWFkb25seSBuZXdWYWx1ZTogVmFsdWVUeXBlIHwgdW5kZWZpbmVkKSB7XG4gICAgaWYgKG9sZFZhbHVlID09PSB1bmRlZmluZWQgJiYgbmV3VmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEFzc2VydGlvbkVycm9yKHsgbWVzc2FnZTogJ29sZFZhbHVlIGFuZCBuZXdWYWx1ZSBhcmUgYm90aCB1bmRlZmluZWQhJyB9KTtcbiAgICB9XG4gICAgdGhpcy5pc0RpZmZlcmVudCA9ICFkZWVwRXF1YWwob2xkVmFsdWUsIG5ld1ZhbHVlKTtcbiAgfVxuXG4gIC8qKiBAcmV0dXJucyArdHJ1ZSsgaWYgdGhlIGVsZW1lbnQgaXMgbmV3IHRvIHRoZSB0ZW1wbGF0ZS4gKi9cbiAgcHVibGljIGdldCBpc0FkZGl0aW9uKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLm9sZFZhbHVlID09PSB1bmRlZmluZWQ7XG4gIH1cblxuICAvKiogQHJldHVybnMgK3RydWUrIGlmIHRoZSBlbGVtZW50IHdhcyByZW1vdmVkIGZyb20gdGhlIHRlbXBsYXRlLiAqL1xuICBwdWJsaWMgZ2V0IGlzUmVtb3ZhbCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5uZXdWYWx1ZSA9PT0gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqIEByZXR1cm5zICt0cnVlKyBpZiB0aGUgZWxlbWVudCB3YXMgYWxyZWFkeSBpbiB0aGUgdGVtcGxhdGUgYW5kIGlzIHVwZGF0ZWQuICovXG4gIHB1YmxpYyBnZXQgaXNVcGRhdGUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMub2xkVmFsdWUgIT09IHVuZGVmaW5lZFxuICAgICAgJiYgdGhpcy5uZXdWYWx1ZSAhPT0gdW5kZWZpbmVkO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBQcm9wZXJ0eURpZmZlcmVuY2U8VmFsdWVUeXBlPiBleHRlbmRzIERpZmZlcmVuY2U8VmFsdWVUeXBlPiB7XG4gIHB1YmxpYyBjaGFuZ2VJbXBhY3Q/OiBSZXNvdXJjZUltcGFjdDtcblxuICBjb25zdHJ1Y3RvcihvbGRWYWx1ZTogVmFsdWVUeXBlIHwgdW5kZWZpbmVkLCBuZXdWYWx1ZTogVmFsdWVUeXBlIHwgdW5kZWZpbmVkLCBhcmdzOiB7IGNoYW5nZUltcGFjdD86IFJlc291cmNlSW1wYWN0IH0pIHtcbiAgICBzdXBlcihvbGRWYWx1ZSwgbmV3VmFsdWUpO1xuICAgIHRoaXMuY2hhbmdlSW1wYWN0ID0gYXJncy5jaGFuZ2VJbXBhY3Q7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIERpZmZlcmVuY2VDb2xsZWN0aW9uPFYsIFQgZXh0ZW5kcyBJRGlmZmVyZW5jZTxWPj4ge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IGRpZmZzOiB7IFtsb2dpY2FsSWQ6IHN0cmluZ106IFQgfSkge31cblxuICBwdWJsaWMgZ2V0IGNoYW5nZXMoKTogeyBbbG9naWNhbElkOiBzdHJpbmddOiBUIH0ge1xuICAgIHJldHVybiBvbmx5Q2hhbmdlcyh0aGlzLmRpZmZzKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgZGlmZmVyZW5jZUNvdW50KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIE9iamVjdC52YWx1ZXModGhpcy5jaGFuZ2VzKS5sZW5ndGg7XG4gIH1cblxuICBwdWJsaWMgZ2V0KGxvZ2ljYWxJZDogc3RyaW5nKTogVCB7XG4gICAgY29uc3QgcmV0ID0gdGhpcy5kaWZmc1tsb2dpY2FsSWRdO1xuICAgIGlmICghcmV0KSB7IHRocm93IG5ldyBFcnJvcihgTm8gb2JqZWN0IHdpdGggbG9naWNhbCBJRCAnJHtsb2dpY2FsSWR9J2ApOyB9XG4gICAgcmV0dXJuIHJldDtcbiAgfVxuXG4gIHB1YmxpYyByZW1vdmUobG9naWNhbElkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBkZWxldGUgdGhpcy5kaWZmc1tsb2dpY2FsSWRdO1xuICB9XG5cbiAgcHVibGljIGdldCBsb2dpY2FsSWRzKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gT2JqZWN0LmtleXModGhpcy5jaGFuZ2VzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbmV3IFRlbXBsYXRlRGlmZiB3aGljaCBvbmx5IGNvbnRhaW5zIGNoYW5nZXMgZm9yIHdoaWNoIGBwcmVkaWNhdGVgXG4gICAqIHJldHVybnMgYHRydWVgLlxuICAgKi9cbiAgcHVibGljIGZpbHRlcihwcmVkaWNhdGU6IChkaWZmOiBUIHwgdW5kZWZpbmVkKSA9PiBib29sZWFuKTogRGlmZmVyZW5jZUNvbGxlY3Rpb248ViwgVD4ge1xuICAgIGNvbnN0IG5ld0NoYW5nZXM6IHsgW2xvZ2ljYWxJZDogc3RyaW5nXTogVCB9ID0geyB9O1xuICAgIGZvciAoY29uc3QgaWQgb2YgT2JqZWN0LmtleXModGhpcy5jaGFuZ2VzKSkge1xuICAgICAgY29uc3QgZGlmZiA9IHRoaXMuY2hhbmdlc1tpZF07XG5cbiAgICAgIGlmIChwcmVkaWNhdGUoZGlmZikpIHtcbiAgICAgICAgbmV3Q2hhbmdlc1tpZF0gPSBkaWZmO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBuZXcgRGlmZmVyZW5jZUNvbGxlY3Rpb248ViwgVD4obmV3Q2hhbmdlcyk7XG4gIH1cblxuICAvKipcbiAgICogSW52b2tlcyBgY2JgIGZvciBhbGwgY2hhbmdlcyBpbiB0aGlzIGNvbGxlY3Rpb24uXG4gICAqXG4gICAqIENoYW5nZXMgd2lsbCBiZSBzb3J0ZWQgYXMgZm9sbG93czpcbiAgICogIC0gUmVtb3ZlZFxuICAgKiAgLSBBZGRlZFxuICAgKiAgLSBVcGRhdGVkXG4gICAqICAtIE90aGVyc1xuICAgKlxuICAgKi9cbiAgcHVibGljIGZvckVhY2hEaWZmZXJlbmNlKGNiOiAobG9naWNhbElkOiBzdHJpbmcsIGNoYW5nZTogVCkgPT4gYW55KTogdm9pZCB7XG4gICAgY29uc3QgcmVtb3ZlZCA9IG5ldyBBcnJheTx7IGxvZ2ljYWxJZDogc3RyaW5nOyBjaGFuZ2U6IFQgfT4oKTtcbiAgICBjb25zdCBhZGRlZCA9IG5ldyBBcnJheTx7IGxvZ2ljYWxJZDogc3RyaW5nOyBjaGFuZ2U6IFQgfT4oKTtcbiAgICBjb25zdCB1cGRhdGVkID0gbmV3IEFycmF5PHsgbG9naWNhbElkOiBzdHJpbmc7IGNoYW5nZTogVCB9PigpO1xuICAgIGNvbnN0IG90aGVycyA9IG5ldyBBcnJheTx7IGxvZ2ljYWxJZDogc3RyaW5nOyBjaGFuZ2U6IFQgfT4oKTtcblxuICAgIGZvciAoY29uc3QgbG9naWNhbElkIG9mIHRoaXMubG9naWNhbElkcykge1xuICAgICAgY29uc3QgY2hhbmdlOiBUID0gdGhpcy5jaGFuZ2VzW2xvZ2ljYWxJZF0hO1xuICAgICAgaWYgKGNoYW5nZS5pc0FkZGl0aW9uKSB7XG4gICAgICAgIGFkZGVkLnB1c2goeyBsb2dpY2FsSWQsIGNoYW5nZSB9KTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhbmdlLmlzUmVtb3ZhbCkge1xuICAgICAgICByZW1vdmVkLnB1c2goeyBsb2dpY2FsSWQsIGNoYW5nZSB9KTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhbmdlLmlzVXBkYXRlKSB7XG4gICAgICAgIHVwZGF0ZWQucHVzaCh7IGxvZ2ljYWxJZCwgY2hhbmdlIH0pO1xuICAgICAgfSBlbHNlIGlmIChjaGFuZ2UuaXNEaWZmZXJlbnQpIHtcbiAgICAgICAgb3RoZXJzLnB1c2goeyBsb2dpY2FsSWQsIGNoYW5nZSB9KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZW1vdmVkLmZvckVhY2godiA9PiBjYih2LmxvZ2ljYWxJZCwgdi5jaGFuZ2UpKTtcbiAgICBhZGRlZC5mb3JFYWNoKHYgPT4gY2Iodi5sb2dpY2FsSWQsIHYuY2hhbmdlKSk7XG4gICAgdXBkYXRlZC5mb3JFYWNoKHYgPT4gY2Iodi5sb2dpY2FsSWQsIHYuY2hhbmdlKSk7XG4gICAgb3RoZXJzLmZvckVhY2godiA9PiBjYih2LmxvZ2ljYWxJZCwgdi5jaGFuZ2UpKTtcbiAgfVxufVxuXG4vKipcbiAqIEFyZ3VtZW50cyBleHBlY3RlZCBieSB0aGUgY29uc3RydWN0b3Igb2YgK1RlbXBsYXRlRGlmZissIGV4dHJhY3RlZCBhcyBhbiBpbnRlcmZhY2UgZm9yIHRoZSBzYWtlXG4gKiBvZiAocmVsYXRpdmUpIGNvbmNpc2VuZXNzIG9mIHRoZSBjb25zdHJ1Y3RvcidzIHNpZ25hdHVyZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJVGVtcGxhdGVEaWZmIHtcbiAgYXdzVGVtcGxhdGVGb3JtYXRWZXJzaW9uPzogSURpZmZlcmVuY2U8c3RyaW5nPjtcbiAgZGVzY3JpcHRpb24/OiBJRGlmZmVyZW5jZTxzdHJpbmc+O1xuICB0cmFuc2Zvcm0/OiBJRGlmZmVyZW5jZTxzdHJpbmc+O1xuXG4gIGNvbmRpdGlvbnM/OiBEaWZmZXJlbmNlQ29sbGVjdGlvbjxDb25kaXRpb24sIENvbmRpdGlvbkRpZmZlcmVuY2U+O1xuICBtYXBwaW5ncz86IERpZmZlcmVuY2VDb2xsZWN0aW9uPE1hcHBpbmcsIE1hcHBpbmdEaWZmZXJlbmNlPjtcbiAgbWV0YWRhdGE/OiBEaWZmZXJlbmNlQ29sbGVjdGlvbjxNZXRhZGF0YSwgTWV0YWRhdGFEaWZmZXJlbmNlPjtcbiAgb3V0cHV0cz86IERpZmZlcmVuY2VDb2xsZWN0aW9uPE91dHB1dCwgT3V0cHV0RGlmZmVyZW5jZT47XG4gIHBhcmFtZXRlcnM/OiBEaWZmZXJlbmNlQ29sbGVjdGlvbjxQYXJhbWV0ZXIsIFBhcmFtZXRlckRpZmZlcmVuY2U+O1xuICByZXNvdXJjZXM/OiBEaWZmZXJlbmNlQ29sbGVjdGlvbjxSZXNvdXJjZSwgUmVzb3VyY2VEaWZmZXJlbmNlPjtcblxuICB1bmtub3duPzogRGlmZmVyZW5jZUNvbGxlY3Rpb248YW55LCBJRGlmZmVyZW5jZTxhbnk+Pjtcbn1cblxuZXhwb3J0IHR5cGUgQ29uZGl0aW9uID0gYW55O1xuZXhwb3J0IGNsYXNzIENvbmRpdGlvbkRpZmZlcmVuY2UgZXh0ZW5kcyBEaWZmZXJlbmNlPENvbmRpdGlvbj4ge1xuICAvLyBUT0RPOiBkZWZpbmUgc3BlY2lmaWMgZGlmZmVyZW5jZSBhdHRyaWJ1dGVzXG59XG5cbmV4cG9ydCB0eXBlIE1hcHBpbmcgPSBhbnk7XG5leHBvcnQgY2xhc3MgTWFwcGluZ0RpZmZlcmVuY2UgZXh0ZW5kcyBEaWZmZXJlbmNlPE1hcHBpbmc+IHtcbiAgLy8gVE9ETzogZGVmaW5lIHNwZWNpZmljIGRpZmZlcmVuY2UgYXR0cmlidXRlc1xufVxuXG5leHBvcnQgdHlwZSBNZXRhZGF0YSA9IGFueTtcbmV4cG9ydCBjbGFzcyBNZXRhZGF0YURpZmZlcmVuY2UgZXh0ZW5kcyBEaWZmZXJlbmNlPE1ldGFkYXRhPiB7XG4gIC8vIFRPRE86IGRlZmluZSBzcGVjaWZpYyBkaWZmZXJlbmNlIGF0dHJpYnV0ZXNcbn1cblxuZXhwb3J0IHR5cGUgT3V0cHV0ID0gYW55O1xuZXhwb3J0IGNsYXNzIE91dHB1dERpZmZlcmVuY2UgZXh0ZW5kcyBEaWZmZXJlbmNlPE91dHB1dD4ge1xuICAvLyBUT0RPOiBkZWZpbmUgc3BlY2lmaWMgZGlmZmVyZW5jZSBhdHRyaWJ1dGVzXG59XG5cbmV4cG9ydCB0eXBlIFBhcmFtZXRlciA9IGFueTtcbmV4cG9ydCBjbGFzcyBQYXJhbWV0ZXJEaWZmZXJlbmNlIGV4dGVuZHMgRGlmZmVyZW5jZTxQYXJhbWV0ZXI+IHtcbiAgLy8gVE9ETzogZGVmaW5lIHNwZWNpZmljIGRpZmZlcmVuY2UgYXR0cmlidXRlc1xufVxuXG5leHBvcnQgZW51bSBSZXNvdXJjZUltcGFjdCB7XG4gIC8qKiBUaGUgZXhpc3RpbmcgcGh5c2ljYWwgcmVzb3VyY2Ugd2lsbCBiZSB1cGRhdGVkICovXG4gIFdJTExfVVBEQVRFID0gJ1dJTExfVVBEQVRFJyxcbiAgLyoqIEEgbmV3IHBoeXNpY2FsIHJlc291cmNlIHdpbGwgYmUgY3JlYXRlZCAqL1xuICBXSUxMX0NSRUFURSA9ICdXSUxMX0NSRUFURScsXG4gIC8qKiBUaGUgZXhpc3RpbmcgcGh5c2ljYWwgcmVzb3VyY2Ugd2lsbCBiZSByZXBsYWNlZCAqL1xuICBXSUxMX1JFUExBQ0UgPSAnV0lMTF9SRVBMQUNFJyxcbiAgLyoqIFRoZSBleGlzdGluZyBwaHlzaWNhbCByZXNvdXJjZSBtYXkgYmUgcmVwbGFjZWQgKi9cbiAgTUFZX1JFUExBQ0UgPSAnTUFZX1JFUExBQ0UnLFxuICAvKiogVGhlIGV4aXN0aW5nIHBoeXNpY2FsIHJlc291cmNlIHdpbGwgYmUgZGVzdHJveWVkICovXG4gIFdJTExfREVTVFJPWSA9ICdXSUxMX0RFU1RST1knLFxuICAvKiogVGhlIGV4aXN0aW5nIHBoeXNpY2FsIHJlc291cmNlIHdpbGwgYmUgcmVtb3ZlZCBmcm9tIENsb3VkRm9ybWF0aW9uIHN1cGVydmlzaW9uICovXG4gIFdJTExfT1JQSEFOID0gJ1dJTExfT1JQSEFOJyxcbiAgLyoqIFRoZSBleGlzdGluZyBwaHlzaWNhbCByZXNvdXJjZSB3aWxsIGJlIGFkZGVkIHRvIENsb3VkRm9ybWF0aW9uIHN1cGVydmlzaW9uICovXG4gIFdJTExfSU1QT1JUID0gJ1dJTExfSU1QT1JUJyxcbiAgLyoqIFRoZXJlIGlzIG5vIGNoYW5nZSBpbiB0aGlzIHJlc291cmNlICovXG4gIE5PX0NIQU5HRSA9ICdOT19DSEFOR0UnLFxufVxuXG4vKipcbiAqIFRoaXMgZnVuY3Rpb24gY2FuIGJlIHVzZWQgYXMgYSByZWR1Y2VyIHRvIG9idGFpbiB0aGUgcmVzb3VyY2UtbGV2ZWwgaW1wYWN0IG9mIGEgbGlzdFxuICogb2YgcHJvcGVydHktbGV2ZWwgaW1wYWN0cy5cbiAqIEBwYXJhbSBvbmUgdGhlIGN1cnJlbnQgd29yc3QgaW1wYWN0IHNvIGZhci5cbiAqIEBwYXJhbSB0d28gdGhlIG5ldyBpbXBhY3QgYmVpbmcgY29uc2lkZXJlZCAoY2FuIGJlIHVuZGVmaW5lZCwgYXMgd2UgbWF5IG5vdCBhbHdheXMgYmVcbiAqICAgICAgYWJsZSB0byBkZXRlcm1pbmUgc29tZSBwcm9wZXJ0aWVzIGltcGFjdCkuXG4gKi9cbmZ1bmN0aW9uIHdvcnN0SW1wYWN0KG9uZTogUmVzb3VyY2VJbXBhY3QsIHR3bz86IFJlc291cmNlSW1wYWN0KTogUmVzb3VyY2VJbXBhY3Qge1xuICBpZiAoIXR3bykgeyByZXR1cm4gb25lOyB9XG4gIGNvbnN0IGJhZG5lc3MgPSB7XG4gICAgW1Jlc291cmNlSW1wYWN0Lk5PX0NIQU5HRV06IDAsXG4gICAgW1Jlc291cmNlSW1wYWN0LldJTExfSU1QT1JUXTogMCxcbiAgICBbUmVzb3VyY2VJbXBhY3QuV0lMTF9VUERBVEVdOiAxLFxuICAgIFtSZXNvdXJjZUltcGFjdC5XSUxMX0NSRUFURV06IDIsXG4gICAgW1Jlc291cmNlSW1wYWN0LldJTExfT1JQSEFOXTogMyxcbiAgICBbUmVzb3VyY2VJbXBhY3QuTUFZX1JFUExBQ0VdOiA0LFxuICAgIFtSZXNvdXJjZUltcGFjdC5XSUxMX1JFUExBQ0VdOiA1LFxuICAgIFtSZXNvdXJjZUltcGFjdC5XSUxMX0RFU1RST1ldOiA2LFxuICB9O1xuICByZXR1cm4gYmFkbmVzc1tvbmVdID4gYmFkbmVzc1t0d29dID8gb25lIDogdHdvO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlc291cmNlIHtcbiAgVHlwZTogc3RyaW5nO1xuICBQcm9wZXJ0aWVzPzogeyBbbmFtZTogc3RyaW5nXTogYW55IH07XG5cbiAgW2tleTogc3RyaW5nXTogYW55O1xufVxuXG4vKipcbiAqIENoYW5nZSB0byBhIHNpbmdsZSByZXNvdXJjZSBiZXR3ZWVuIHR3byBDbG91ZEZvcm1hdGlvbiB0ZW1wbGF0ZXNcbiAqXG4gKiBUaGlzIGNsYXNzIGNhbiBiZSBtdXRhdGVkIGFmdGVyIGNvbnN0cnVjdGlvbi5cbiAqL1xuZXhwb3J0IGNsYXNzIFJlc291cmNlRGlmZmVyZW5jZSBpbXBsZW1lbnRzIElEaWZmZXJlbmNlPFJlc291cmNlPiB7XG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoaXMgcmVzb3VyY2Ugd2FzIGFkZGVkXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgaXNBZGRpdGlvbjogYm9vbGVhbjtcblxuICAvKipcbiAgICogV2hldGhlciB0aGlzIHJlc291cmNlIHdhcyByZW1vdmVkXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgaXNSZW1vdmFsOiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRoaXMgcmVzb3VyY2Ugd2FzIGltcG9ydGVkXG4gICAqL1xuICBwdWJsaWMgaXNJbXBvcnQ/OiBib29sZWFuO1xuXG4gIC8qKiBQcm9wZXJ0eS1sZXZlbCBjaGFuZ2VzIG9uIHRoZSByZXNvdXJjZSAqL1xuICBwcml2YXRlIHJlYWRvbmx5IHByb3BlcnR5RGlmZnM6IHsgW2tleTogc3RyaW5nXTogUHJvcGVydHlEaWZmZXJlbmNlPGFueT4gfTtcblxuICAvKiogQ2hhbmdlcyB0byBub24tcHJvcGVydHkgbGV2ZWwgYXR0cmlidXRlcyBvZiB0aGUgcmVzb3VyY2UgKi9cbiAgcHJpdmF0ZSByZWFkb25seSBvdGhlckRpZmZzOiB7IFtrZXk6IHN0cmluZ106IERpZmZlcmVuY2U8YW55PiB9O1xuXG4gIC8qKiBUaGUgcmVzb3VyY2UgdHlwZSAob3Igb2xkIGFuZCBuZXcgdHlwZSBpZiBpdCBoYXMgY2hhbmdlZCkgKi9cbiAgcHJpdmF0ZSByZWFkb25seSByZXNvdXJjZVR5cGVzOiB7IHJlYWRvbmx5IG9sZFR5cGU/OiBzdHJpbmc7IHJlYWRvbmx5IG5ld1R5cGU/OiBzdHJpbmcgfTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgcmVhZG9ubHkgb2xkVmFsdWU6IFJlc291cmNlIHwgdW5kZWZpbmVkLFxuICAgIHB1YmxpYyByZWFkb25seSBuZXdWYWx1ZTogUmVzb3VyY2UgfCB1bmRlZmluZWQsXG4gICAgYXJnczoge1xuICAgICAgcmVzb3VyY2VUeXBlOiB7IG9sZFR5cGU/OiBzdHJpbmc7IG5ld1R5cGU/OiBzdHJpbmcgfTtcbiAgICAgIHByb3BlcnR5RGlmZnM6IHsgW2tleTogc3RyaW5nXTogUHJvcGVydHlEaWZmZXJlbmNlPGFueT4gfTtcbiAgICAgIG90aGVyRGlmZnM6IHsgW2tleTogc3RyaW5nXTogRGlmZmVyZW5jZTxhbnk+IH07XG4gICAgfSxcbiAgKSB7XG4gICAgdGhpcy5yZXNvdXJjZVR5cGVzID0gYXJncy5yZXNvdXJjZVR5cGU7XG4gICAgdGhpcy5wcm9wZXJ0eURpZmZzID0gYXJncy5wcm9wZXJ0eURpZmZzO1xuICAgIHRoaXMub3RoZXJEaWZmcyA9IGFyZ3Mub3RoZXJEaWZmcztcblxuICAgIHRoaXMuaXNBZGRpdGlvbiA9IG9sZFZhbHVlID09PSB1bmRlZmluZWQ7XG4gICAgdGhpcy5pc1JlbW92YWwgPSBuZXdWYWx1ZSA9PT0gdW5kZWZpbmVkO1xuICAgIHRoaXMuaXNJbXBvcnQgPSB1bmRlZmluZWQ7XG4gIH1cblxuICBwdWJsaWMgZ2V0IG9sZFByb3BlcnRpZXMoKTogUHJvcGVydHlNYXAgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLm9sZFZhbHVlICYmIHRoaXMub2xkVmFsdWUuUHJvcGVydGllcztcbiAgfVxuXG4gIHB1YmxpYyBnZXQgbmV3UHJvcGVydGllcygpOiBQcm9wZXJ0eU1hcCB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMubmV3VmFsdWUgJiYgdGhpcy5uZXdWYWx1ZS5Qcm9wZXJ0aWVzO1xuICB9XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhpcyByZXNvdXJjZSB3YXMgbW9kaWZpZWQgYXQgYWxsXG4gICAqL1xuICBwdWJsaWMgZ2V0IGlzRGlmZmVyZW50KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmRpZmZlcmVuY2VDb3VudCA+IDAgfHwgdGhpcy5vbGRSZXNvdXJjZVR5cGUgIT09IHRoaXMubmV3UmVzb3VyY2VUeXBlO1xuICB9XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIHJlc291cmNlIHdhcyB1cGRhdGVkIGluLXBsYWNlXG4gICAqL1xuICBwdWJsaWMgZ2V0IGlzVXBkYXRlKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLmlzRGlmZmVyZW50ICYmICF0aGlzLmlzQWRkaXRpb24gJiYgIXRoaXMuaXNSZW1vdmFsO1xuICB9XG5cbiAgcHVibGljIGdldCBvbGRSZXNvdXJjZVR5cGUoKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5yZXNvdXJjZVR5cGVzLm9sZFR5cGU7XG4gIH1cblxuICBwdWJsaWMgZ2V0IG5ld1Jlc291cmNlVHlwZSgpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLnJlc291cmNlVHlwZXMubmV3VHlwZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbGwgYWN0dWFsIHByb3BlcnR5IHVwZGF0ZXNcbiAgICovXG4gIHB1YmxpYyBnZXQgcHJvcGVydHlVcGRhdGVzKCk6IHsgW2tleTogc3RyaW5nXTogUHJvcGVydHlEaWZmZXJlbmNlPGFueT4gfSB7XG4gICAgcmV0dXJuIG9ubHlDaGFuZ2VzKHRoaXMucHJvcGVydHlEaWZmcyk7XG4gIH1cblxuICAvKipcbiAgICogQWxsIGFjdHVhbCBcIm90aGVyXCIgdXBkYXRlc1xuICAgKi9cbiAgcHVibGljIGdldCBvdGhlckNoYW5nZXMoKTogeyBba2V5OiBzdHJpbmddOiBEaWZmZXJlbmNlPGFueT4gfSB7XG4gICAgcmV0dXJuIG9ubHlDaGFuZ2VzKHRoaXMub3RoZXJEaWZmcyk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIHdoZXRoZXIgdGhlIHJlc291cmNlIHR5cGUgd2FzIGNoYW5nZWQgaW4gdGhpcyBkaWZmXG4gICAqXG4gICAqIFRoaXMgaXMgbm90IGEgdmFsaWQgb3BlcmF0aW9uIGluIENsb3VkRm9ybWF0aW9uIGJ1dCB0byBiZSBkZWZlbnNpdmUgd2UncmUgZ29pbmdcbiAgICogdG8gYmUgYXdhcmUgb2YgaXQgYW55d2F5LlxuICAgKi9cbiAgcHVibGljIGdldCByZXNvdXJjZVR5cGVDaGFuZ2VkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAodGhpcy5yZXNvdXJjZVR5cGVzLm9sZFR5cGUgIT09IHVuZGVmaW5lZFxuICAgICAgICAmJiB0aGlzLnJlc291cmNlVHlwZXMubmV3VHlwZSAhPT0gdW5kZWZpbmVkXG4gICAgICAgICYmIHRoaXMucmVzb3VyY2VUeXBlcy5vbGRUeXBlICE9PSB0aGlzLnJlc291cmNlVHlwZXMubmV3VHlwZSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIHRoZSByZXNvdXJjZSB0eXBlIGlmIGl0IHdhcyB1bmNoYW5nZWRcbiAgICpcbiAgICogSWYgdGhlIHJlc291cmNlIHR5cGUgd2FzIGNoYW5nZWQsIGl0J3MgYW4gZXJyb3IgdG8gY2FsbCB0aGlzLlxuICAgKi9cbiAgcHVibGljIGdldCByZXNvdXJjZVR5cGUoKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAodGhpcy5yZXNvdXJjZVR5cGVDaGFuZ2VkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBnZXQgLnJlc291cmNlVHlwZSwgYmVjYXVzZSB0aGUgdHlwZSB3YXMgY2hhbmdlZCcpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5yZXNvdXJjZVR5cGVzLm9sZFR5cGUgfHwgdGhpcy5yZXNvdXJjZVR5cGVzLm5ld1R5cGU7XG4gIH1cblxuICAvKipcbiAgICogUmVwbGFjZSBhIFByb3BlcnR5Q2hhbmdlIGluIHRoaXMgb2JqZWN0XG4gICAqXG4gICAqIFRoaXMgYWZmZWN0cyB0aGUgcHJvcGVydHkgZGlmZiBhcyBpdCBpcyBzdW1tYXJpemVkIHRvIHVzZXJzLCBidXQgaXQgRE9FU1xuICAgKiBOT1QgYWZmZWN0IGVpdGhlciB0aGUgXCJvbGRWYWx1ZVwiIG9yIFwibmV3VmFsdWVcIiB2YWx1ZXM7IHRob3NlIHN0aWxsIGNvbnRhaW5cbiAgICogdGhlIGFjdHVhbCB0ZW1wbGF0ZSB2YWx1ZXMgYXMgcHJvdmlkZWQgYnkgdGhlIHVzZXIgKHRoZXkgbWlnaHQgc3RpbGwgYmVcbiAgICogdXNlZCBmb3IgZG93bnN0cmVhbSBwcm9jZXNzaW5nKS5cbiAgICovXG4gIHB1YmxpYyBzZXRQcm9wZXJ0eUNoYW5nZShwcm9wZXJ0eU5hbWU6IHN0cmluZywgY2hhbmdlOiBQcm9wZXJ0eURpZmZlcmVuY2U8YW55Pikge1xuICAgIHRoaXMucHJvcGVydHlEaWZmc1twcm9wZXJ0eU5hbWVdID0gY2hhbmdlO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcGxhY2UgYSBPdGhlckNoYW5nZSBpbiB0aGlzIG9iamVjdFxuICAgKlxuICAgKiBUaGlzIGFmZmVjdHMgdGhlIHByb3BlcnR5IGRpZmYgYXMgaXQgaXMgc3VtbWFyaXplZCB0byB1c2VycywgYnV0IGl0IERPRVNcbiAgICogTk9UIGFmZmVjdCBlaXRoZXIgdGhlIFwib2xkVmFsdWVcIiBvciBcIm5ld1ZhbHVlXCIgdmFsdWVzOyB0aG9zZSBzdGlsbCBjb250YWluXG4gICAqIHRoZSBhY3R1YWwgdGVtcGxhdGUgdmFsdWVzIGFzIHByb3ZpZGVkIGJ5IHRoZSB1c2VyICh0aGV5IG1pZ2h0IHN0aWxsIGJlXG4gICAqIHVzZWQgZm9yIGRvd25zdHJlYW0gcHJvY2Vzc2luZykuXG4gICAqL1xuICBwdWJsaWMgc2V0T3RoZXJDaGFuZ2Uob3RoZXJOYW1lOiBzdHJpbmcsIGNoYW5nZTogUHJvcGVydHlEaWZmZXJlbmNlPGFueT4pIHtcbiAgICB0aGlzLm90aGVyRGlmZnNbb3RoZXJOYW1lXSA9IGNoYW5nZTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgY2hhbmdlSW1wYWN0KCk6IFJlc291cmNlSW1wYWN0IHtcbiAgICBpZiAodGhpcy5pc0ltcG9ydCkge1xuICAgICAgcmV0dXJuIFJlc291cmNlSW1wYWN0LldJTExfSU1QT1JUO1xuICAgIH1cbiAgICAvLyBDaGVjayB0aGUgVHlwZSBmaXJzdFxuICAgIGlmICh0aGlzLnJlc291cmNlVHlwZXMub2xkVHlwZSAhPT0gdGhpcy5yZXNvdXJjZVR5cGVzLm5ld1R5cGUpIHtcbiAgICAgIGlmICh0aGlzLnJlc291cmNlVHlwZXMub2xkVHlwZSA9PT0gdW5kZWZpbmVkKSB7IHJldHVybiBSZXNvdXJjZUltcGFjdC5XSUxMX0NSRUFURTsgfVxuICAgICAgaWYgKHRoaXMucmVzb3VyY2VUeXBlcy5uZXdUeXBlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub2xkVmFsdWUhLkRlbGV0aW9uUG9saWN5ID09PSAnUmV0YWluJ1xuICAgICAgICAgID8gUmVzb3VyY2VJbXBhY3QuV0lMTF9PUlBIQU5cbiAgICAgICAgICA6IFJlc291cmNlSW1wYWN0LldJTExfREVTVFJPWTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBSZXNvdXJjZUltcGFjdC5XSUxMX1JFUExBQ0U7XG4gICAgfVxuXG4gICAgLy8gQmFzZSBpbXBhY3QgKGJlZm9yZSB3ZSBtaXggaW4gdGhlIHdvcnN0IG9mIHRoZSBwcm9wZXJ0eSBpbXBhY3RzKTtcbiAgICAvLyBXSUxMX1VQREFURSBpZiB3ZSBoYXZlIFwib3RoZXJcIiBjaGFuZ2VzLCBOT19DSEFOR0UgaWYgdGhlcmUgYXJlIG5vIFwib3RoZXJcIiBjaGFuZ2VzLlxuICAgIGNvbnN0IGJhc2VJbXBhY3QgPSBPYmplY3Qua2V5cyh0aGlzLm90aGVyQ2hhbmdlcykubGVuZ3RoID4gMCA/IFJlc291cmNlSW1wYWN0LldJTExfVVBEQVRFIDogUmVzb3VyY2VJbXBhY3QuTk9fQ0hBTkdFO1xuXG4gICAgcmV0dXJuIE9iamVjdC52YWx1ZXModGhpcy5wcm9wZXJ0eURpZmZzKVxuICAgICAgLm1hcChlbHQgPT4gZWx0LmNoYW5nZUltcGFjdClcbiAgICAgIC5yZWR1Y2Uod29yc3RJbXBhY3QsIGJhc2VJbXBhY3QpO1xuICB9XG5cbiAgLyoqXG4gICAqIENvdW50IG9mIGFjdHVhbCBkaWZmZXJlbmNlcyAobm90IG9mIGVsZW1lbnRzKVxuICAgKi9cbiAgcHVibGljIGdldCBkaWZmZXJlbmNlQ291bnQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyh0aGlzLnByb3BlcnR5VXBkYXRlcykubGVuZ3RoXG4gICAgICArIE9iamVjdC52YWx1ZXModGhpcy5vdGhlckNoYW5nZXMpLmxlbmd0aDtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbnZva2UgYSBjYWxsYmFjayBmb3IgZWFjaCBhY3R1YWwgZGlmZmVyZW5jZVxuICAgKi9cbiAgcHVibGljIGZvckVhY2hEaWZmZXJlbmNlKGNiOiAodHlwZTogJ1Byb3BlcnR5JyB8ICdPdGhlcicsIG5hbWU6IHN0cmluZywgdmFsdWU6IERpZmZlcmVuY2U8YW55PiB8IFByb3BlcnR5RGlmZmVyZW5jZTxhbnk+KSA9PiBhbnkpIHtcbiAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyh0aGlzLnByb3BlcnR5VXBkYXRlcykuc29ydCgpKSB7XG4gICAgICBjYignUHJvcGVydHknLCBrZXksIHRoaXMucHJvcGVydHlVcGRhdGVzW2tleV0pO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyh0aGlzLm90aGVyQ2hhbmdlcykuc29ydCgpKSB7XG4gICAgICBjYignT3RoZXInLCBrZXksIHRoaXMub3RoZXJEaWZmc1trZXldKTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzUHJvcGVydHlEaWZmZXJlbmNlPFQ+KGRpZmY6IERpZmZlcmVuY2U8VD4pOiBkaWZmIGlzIFByb3BlcnR5RGlmZmVyZW5jZTxUPiB7XG4gIHJldHVybiAoZGlmZiBhcyBQcm9wZXJ0eURpZmZlcmVuY2U8VD4pLmNoYW5nZUltcGFjdCAhPT0gdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIEZpbHRlciBhIG1hcCBvZiBJRGlmZmVyZW5jZXMgZG93biB0byBvbmx5IHJldGFpbiB0aGUgYWN0dWFsIGNoYW5nZXNcbiAqL1xuZnVuY3Rpb24gb25seUNoYW5nZXM8ViwgVCBleHRlbmRzIElEaWZmZXJlbmNlPFY+Pih4czoge1trZXk6IHN0cmluZ106IFR9KToge1trZXk6IHN0cmluZ106IFR9IHtcbiAgY29uc3QgcmV0OiB7IFtrZXk6IHN0cmluZ106IFQgfSA9IHt9O1xuICBmb3IgKGNvbnN0IFtrZXksIGRpZmZdIG9mIE9iamVjdC5lbnRyaWVzKHhzKSkge1xuICAgIGlmIChkaWZmLmlzRGlmZmVyZW50KSB7XG4gICAgICByZXRba2V5XSA9IGRpZmY7XG4gICAgfVxuICB9XG4gIHJldHVybiByZXQ7XG59XG4iXX0=
@@ -0,0 +1,57 @@
1
+ import { Resource } from '@aws-cdk/service-spec-types';
2
+ /**
3
+ * Compares two objects for equality, deeply. The function handles arguments that are
4
+ * +null+, +undefined+, arrays and objects. For objects, the function will not take the
5
+ * object prototype into account for the purpose of the comparison, only the values of
6
+ * properties reported by +Object.keys+.
7
+ *
8
+ * If both operands can be parsed to equivalent numbers, will return true.
9
+ * This makes diff consistent with CloudFormation, where a numeric 10 and a literal "10"
10
+ * are considered equivalent.
11
+ *
12
+ * @param lvalue the left operand of the equality comparison.
13
+ * @param rvalue the right operand of the equality comparison.
14
+ *
15
+ * @returns +true+ if both +lvalue+ and +rvalue+ are equivalent to each other.
16
+ */
17
+ export declare function deepEqual(lvalue: any, rvalue: any): boolean;
18
+ /**
19
+ * Produce the differences between two maps, as a map, using a specified diff function.
20
+ *
21
+ * @param oldValue the old map.
22
+ * @param newValue the new map.
23
+ * @param elementDiff the diff function.
24
+ *
25
+ * @returns a map representing the differences between +oldValue+ and +newValue+.
26
+ */
27
+ export declare function diffKeyedEntities<T>(oldValue: {
28
+ [key: string]: any;
29
+ } | undefined, newValue: {
30
+ [key: string]: any;
31
+ } | undefined, elementDiff: (oldElement: any, newElement: any, key: string) => T): {
32
+ [name: string]: T;
33
+ };
34
+ /**
35
+ * Computes the union of two sets of strings.
36
+ *
37
+ * @param lv the left set of strings.
38
+ * @param rv the right set of strings.
39
+ *
40
+ * @returns a new array containing all elemebts from +lv+ and +rv+, with no duplicates.
41
+ */
42
+ export declare function unionOf(lv: string[] | Set<string>, rv: string[] | Set<string>): string[];
43
+ /**
44
+ * GetStackTemplate flattens any codepoint greater than "\u7f" to "?". This is
45
+ * true even for codepoints in the supplemental planes which are represented
46
+ * in JS as surrogate pairs, all the way up to "\u{10ffff}".
47
+ *
48
+ * This function implements the same mangling in order to provide diagnostic
49
+ * information in `cdk diff`.
50
+ */
51
+ export declare function mangleLikeCloudFormation(payload: string): string;
52
+ /**
53
+ * Load a Resource model from the Service Spec Database
54
+ *
55
+ * The database is loaded lazily and cached across multiple calls to `loadResourceModel`.
56
+ */
57
+ export declare function loadResourceModel(type: string): Resource | undefined;