@aws-cdk/toolkit-lib 1.24.0 → 1.25.1

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 (94) hide show
  1. package/build-info.json +2 -2
  2. package/db.json.gz +0 -0
  3. package/lib/actions/deploy/index.d.ts +15 -1
  4. package/lib/actions/deploy/index.js +1 -1
  5. package/lib/actions/deploy/private/deployment-method.d.ts +5 -9
  6. package/lib/actions/deploy/private/deployment-method.js +8 -1
  7. package/lib/actions/diagnose/index.d.ts +89 -0
  8. package/lib/actions/diagnose/index.js +3 -0
  9. package/lib/actions/diff/private/helpers.js +12 -15
  10. package/lib/actions/index.d.ts +2 -0
  11. package/lib/actions/index.js +3 -1
  12. package/lib/actions/orphan/index.d.ts +18 -0
  13. package/lib/actions/orphan/index.js +3 -0
  14. package/lib/api/aws-auth/sdk.d.ts +2 -1
  15. package/lib/api/aws-auth/sdk.js +2 -1
  16. package/lib/api/bootstrap/bootstrap-environment.js +4 -4
  17. package/lib/api/bootstrap/bootstrap-template.yaml +5 -16
  18. package/lib/api/bootstrap/deploy-bootstrap.js +9 -1
  19. package/lib/api/cloud-assembly/stack-selector.d.ts +1 -1
  20. package/lib/api/cloud-assembly/stack-selector.js +1 -1
  21. package/lib/api/cloudformation/index.d.ts +1 -0
  22. package/lib/api/cloudformation/index.js +2 -1
  23. package/lib/api/cloudformation/logical-id-map.d.ts +24 -0
  24. package/lib/api/cloudformation/logical-id-map.js +45 -0
  25. package/lib/api/cloudformation/stack-helpers.d.ts +6 -0
  26. package/lib/api/cloudformation/stack-helpers.js +12 -1
  27. package/lib/api/deployments/cfn-api.d.ts +8 -17
  28. package/lib/api/deployments/cfn-api.js +60 -71
  29. package/lib/api/deployments/deploy-stack.d.ts +6 -2
  30. package/lib/api/deployments/deploy-stack.js +43 -61
  31. package/lib/api/deployments/deployments.d.ts +3 -2
  32. package/lib/api/deployments/deployments.js +31 -7
  33. package/lib/api/diagnosing/changeset-error-fetcher.d.ts +51 -0
  34. package/lib/api/diagnosing/changeset-error-fetcher.js +83 -0
  35. package/lib/api/diagnosing/diagnosis-formatting.d.ts +13 -0
  36. package/lib/api/diagnosing/diagnosis-formatting.js +140 -0
  37. package/lib/api/diagnosing/stack-diagnoser.d.ts +106 -0
  38. package/lib/api/diagnosing/stack-diagnoser.js +354 -0
  39. package/lib/api/diagnosing/tree-builder.d.ts +13 -0
  40. package/lib/api/diagnosing/tree-builder.js +86 -0
  41. package/lib/api/diagnosing/tree.d.ts +19 -0
  42. package/lib/api/diagnosing/tree.js +72 -0
  43. package/lib/api/diff/diff-formatter.js +8 -12
  44. package/lib/api/drift/drift-formatter.d.ts +0 -1
  45. package/lib/api/drift/drift-formatter.js +3 -10
  46. package/lib/api/hotswap/hotswap-deployments.js +14 -2
  47. package/lib/api/hotswap/hotswap-template-cache.d.ts +19 -0
  48. package/lib/api/hotswap/hotswap-template-cache.js +96 -0
  49. package/lib/api/index.d.ts +1 -0
  50. package/lib/api/index.js +2 -1
  51. package/lib/api/io/private/messages.d.ts +5 -0
  52. package/lib/api/io/private/messages.js +23 -1
  53. package/lib/api/io/toolkit-action.d.ts +1 -1
  54. package/lib/api/io/toolkit-action.js +1 -1
  55. package/lib/api/orphan/orphaner.d.ts +75 -0
  56. package/lib/api/orphan/orphaner.js +246 -0
  57. package/lib/api/orphan/private/helpers.d.ts +56 -0
  58. package/lib/api/orphan/private/helpers.js +219 -0
  59. package/lib/api/orphan/private/index.d.ts +2 -0
  60. package/lib/api/orphan/private/index.js +18 -0
  61. package/lib/api/resource-import/importer.d.ts +5 -1
  62. package/lib/api/resource-import/importer.js +26 -6
  63. package/lib/api/settings.d.ts +3 -1
  64. package/lib/api/settings.js +16 -3
  65. package/lib/api/source-tracing/index.d.ts +2 -0
  66. package/lib/api/source-tracing/index.js +18 -0
  67. package/lib/api/source-tracing/private/source-tracing.d.ts +16 -0
  68. package/lib/api/source-tracing/private/source-tracing.js +8 -0
  69. package/lib/api/source-tracing/private/stack-source-tracing.d.ts +32 -0
  70. package/lib/api/source-tracing/private/stack-source-tracing.js +134 -0
  71. package/lib/api/source-tracing/types.d.ts +9 -0
  72. package/lib/api/source-tracing/types.js +3 -0
  73. package/lib/api/stack-events/resource-errors.d.ts +82 -0
  74. package/lib/api/stack-events/resource-errors.js +129 -0
  75. package/lib/api/stack-events/stack-activity-monitor.d.ts +2 -29
  76. package/lib/api/stack-events/stack-activity-monitor.js +6 -95
  77. package/lib/api/stack-events/stack-event-poller.d.ts +71 -8
  78. package/lib/api/stack-events/stack-event-poller.js +107 -13
  79. package/lib/api/stack-events/stack-progress-monitor.d.ts +2 -2
  80. package/lib/api/stack-events/stack-progress-monitor.js +8 -2
  81. package/lib/api/work-graph/work-graph.d.ts +4 -0
  82. package/lib/api/work-graph/work-graph.js +6 -1
  83. package/lib/index.d.ts +1 -0
  84. package/lib/index.js +2 -1
  85. package/lib/index_bg.wasm +0 -0
  86. package/lib/toolkit/toolkit.d.ts +17 -1
  87. package/lib/toolkit/toolkit.js +194 -57
  88. package/lib/util/arrays.d.ts +1 -0
  89. package/lib/util/arrays.js +23 -1
  90. package/lib/util/type-brands.d.ts +1 -1
  91. package/lib/util/type-brands.js +1 -1
  92. package/package.json +13 -13
  93. package/lib/api/deployments/early-validation.d.ts +0 -19
  94. package/lib/api/deployments/early-validation.js +0 -57
@@ -0,0 +1,354 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CloudFormationStackDiagnoser = void 0;
4
+ exports.changeSetHasNoChanges = changeSetHasNoChanges;
5
+ const client_cloudformation_1 = require("@aws-sdk/client-cloudformation");
6
+ const changeset_error_fetcher_1 = require("./changeset-error-fetcher");
7
+ const stack_events_1 = require("../stack-events");
8
+ const stack_status_1 = require("../stack-events/stack-status");
9
+ /**
10
+ * Diagnose a stack's failed state
11
+ *
12
+ * - First, determine the stack's state.
13
+ * - If it is in a failed state, we started a deployment that failed. Describe the stack
14
+ * events, and try to determine the root cause from that.
15
+ * - If it is in a normal state, see if there are any failed change sets. Either
16
+ * get the failure message from the change set, or get the failure events from
17
+ * the change set (early validation).
18
+ *
19
+ * This class works at the CloudFormation level, and does not deal with tracing
20
+ * CloudFormation errors to construct code sources yet.
21
+ */
22
+ class CloudFormationStackDiagnoser {
23
+ props;
24
+ cfn;
25
+ parentStackLogicalIds;
26
+ constructor(props) {
27
+ this.props = props;
28
+ this.cfn = this.props.sdk.cloudFormation();
29
+ this.parentStackLogicalIds = [];
30
+ }
31
+ /**
32
+ * Diagnose a stack's root cause given no pre-existing state
33
+ */
34
+ async diagnoseFromFresh(stackName) {
35
+ try {
36
+ const response = await this.cfn.describeStacks({ StackName: stackName });
37
+ const stack = response.Stacks?.[0];
38
+ if (!stack) {
39
+ return {
40
+ type: 'error-diagnosing',
41
+ message: `Stack with name ${stackName} not found`,
42
+ };
43
+ }
44
+ const status = stack_status_1.StackStatus.fromStackDescription(stack);
45
+ if (status.isInProgress) {
46
+ return {
47
+ type: 'error-diagnosing',
48
+ message: `Stack with name ${stackName} is currently being updated (${status.name}). Try again when it's finished.`,
49
+ };
50
+ }
51
+ if (status.isFailure) {
52
+ return await this._diagnoseViaStackEvents(stackName, stack);
53
+ }
54
+ return await this._diagnoseChangeSetFailureFromStackName(stackName);
55
+ }
56
+ catch (e) {
57
+ return { type: 'error-diagnosing', message: e.message };
58
+ }
59
+ }
60
+ /**
61
+ * Diagnose potential problems with the change set
62
+ */
63
+ async diagnoseChangeSet(changeSet) {
64
+ try {
65
+ return await this._diagnoseChangeSetFailure(changeSet);
66
+ }
67
+ catch (e) {
68
+ return { type: 'error-diagnosing', message: e.message };
69
+ }
70
+ }
71
+ /**
72
+ * Diagnose potential problems with the change set
73
+ */
74
+ async diagnoseFromErrorCollection(errors, stack) {
75
+ if (errors.isEmpty()) {
76
+ return { type: 'no-problem' };
77
+ }
78
+ return {
79
+ type: 'problem',
80
+ detectedBy: {
81
+ type: 'deployment',
82
+ stackStatus: stack.StackStatus ?? '',
83
+ statusReason: stack.StackStatusReason ?? '',
84
+ },
85
+ problems: await this.addErrorTraces(errors.all),
86
+ };
87
+ }
88
+ /**
89
+ * Diagnose a deployment failure via stack events
90
+ *
91
+ * This is the same logic that the deployment monitor uses.
92
+ */
93
+ async _diagnoseViaStackEvents(stackName, stack) {
94
+ const poller = new stack_events_1.StackEventPoller(this.cfn, {
95
+ stackName,
96
+ initialPollRange: stack_events_1.PollRange.mostRecentOperation(),
97
+ });
98
+ // We don't need the resulting events of polling. Polling will automatically update the error collection,
99
+ // which is the thing we care about.
100
+ await poller.poll();
101
+ return this.diagnoseFromErrorCollection(poller.errors, stack);
102
+ }
103
+ async _diagnoseChangeSetFailureFromStackName(stackName) {
104
+ const cs = (await this.cfn.listChangeSets({
105
+ StackName: stackName,
106
+ })).Summaries ?? [];
107
+ const pending = cs.filter(x => x.Status === client_cloudformation_1.ChangeSetStatus.CREATE_IN_PROGRESS || x.Status === client_cloudformation_1.ChangeSetStatus.CREATE_PENDING);
108
+ if (pending.length > 0) {
109
+ return {
110
+ type: 'error-diagnosing',
111
+ message: `Stack with name ${stackName} has change sets currently being created (${pending[0].ChangeSetName}). Try again when it's finished.`,
112
+ };
113
+ }
114
+ const failed = cs.filter(x => x.Status === client_cloudformation_1.ChangeSetStatus.FAILED);
115
+ if (failed.length === 0) {
116
+ return { type: 'no-problem' };
117
+ }
118
+ return this._diagnoseChangeSetFailure(failed[0]);
119
+ }
120
+ /**
121
+ * Try to diagnose the reason that caused a changeset to fail to create
122
+ *
123
+ * There are a couple of different reasons this can happen, and we go through each of them in order.
124
+ *
125
+ * Usually this starts from trying to detect an error message pattern in the change set status reason,
126
+ * and then potentially going to fetch additional information using additional API calls.
127
+ */
128
+ async _diagnoseChangeSetFailure(changeSet) {
129
+ if (changeSet.Status !== client_cloudformation_1.ChangeSetStatus.FAILED) {
130
+ return { type: 'no-problem' };
131
+ }
132
+ if (changeSetHasNoChanges(changeSet)) {
133
+ // This will lead to a change set that is FAILED but it's not actually a problem
134
+ return { type: 'no-problem' };
135
+ }
136
+ // We report early validation errors differently than generic changeset errors. Mostly
137
+ // for historical reasons.
138
+ const isEarlyValidationError = changeSet.StatusReason?.includes('AWS::EarlyValidation');
139
+ if (isEarlyValidationError) {
140
+ return this._reportChangeSetFailureFromEvents(changeSet, {
141
+ type: 'early-validation',
142
+ changeSetName: changeSet.ChangeSetName ?? '',
143
+ });
144
+ }
145
+ // We will recurse into nested change sets if necessary.
146
+ if (changeSet.StatusReason?.includes('Nested change set')) {
147
+ return this._diagnoseNestedChangeSetFailure(changeSet);
148
+ }
149
+ // We special-case failed automatic imports. We know all the meat of the error details are in the
150
+ // status reason, and nowhere else. We parse it specifically.
151
+ const failedAutoErrors = this._tryDetectFailedAutoImport(changeSet);
152
+ if (failedAutoErrors) {
153
+ return {
154
+ type: 'problem',
155
+ detectedBy: {
156
+ type: 'change-set',
157
+ changeSetStatus: changeSet.Status ?? '',
158
+ changeSetName: changeSet.ChangeSetName ?? '',
159
+ statusReason: changeSet.StatusReason ?? '',
160
+ },
161
+ problems: await this.addErrorTraces(failedAutoErrors),
162
+ };
163
+ }
164
+ // Otherwise, a generic change set creation error where `DescribeEvents`
165
+ // might or might not give additional information.
166
+ return this._reportChangeSetFailureFromEvents(changeSet, {
167
+ type: 'change-set',
168
+ changeSetStatus: changeSet.Status ?? '',
169
+ changeSetName: changeSet.ChangeSetName ?? '',
170
+ statusReason: changeSet.StatusReason ?? '',
171
+ });
172
+ }
173
+ /**
174
+ * Try to read the resource-specific reasons for a changeset failure from `DescribeEvents`.
175
+ *
176
+ * If we couldn't read the events or there are 0 errors returned by that API, return a generic
177
+ * error.
178
+ */
179
+ async _reportChangeSetFailureFromEvents(changeSet, detectedBy) {
180
+ const ev = await new changeset_error_fetcher_1.ChangeSetResourceErrorFetcher(this.props.sdk, this.props.envResources)
181
+ .fetchDetailsStructured(changeSet.ChangeSetName, changeSet.StackName);
182
+ // If we have errors to return, return them
183
+ if (ev.type === 'resource-errors' && ev.errors.length > 0) {
184
+ return {
185
+ type: 'problem',
186
+ detectedBy,
187
+ problems: await this.addErrorTraces(ev.errors.map((e) => resourceErrorFromEarlyValidationError(changeSet.StackId ?? '', this.parentStackLogicalIds, e))),
188
+ };
189
+ }
190
+ // Otherwise, we will return a generic changeset error message. If there was a problem
191
+ // checking, we log that for good measure but the result is the same.
192
+ if (ev.type === 'could-not-check') {
193
+ await this.props.ioHelper.defaults.warn(ev.message);
194
+ }
195
+ return this._nonSpecificChangeSetError(changeSet, detectedBy);
196
+ }
197
+ async addErrorTraces(errs) {
198
+ // eslint-disable-next-line @cdklabs/promiseall-no-unbounded-parallelism
199
+ return Promise.all(errs.map((e) => this.addErrorTrace(e)));
200
+ }
201
+ async addErrorTrace(err) {
202
+ let sourceTrace;
203
+ if (err.logicalId) {
204
+ sourceTrace = await this.props.sourceTracer.traceResource(err.stackArn, err.parentStackLogicalIds, err.logicalId);
205
+ }
206
+ else {
207
+ sourceTrace = await this.props.sourceTracer.traceStack(err.stackArn, err.parentStackLogicalIds);
208
+ }
209
+ return { ...err, sourceTrace, topLevelStackHierarchicalId: this.props.topLevelStackHierarchicalId };
210
+ }
211
+ /**
212
+ * Build a generic stack error from the given change set information
213
+ *
214
+ * We can't point to a specific resource.
215
+ */
216
+ async _nonSpecificChangeSetError(changeSet, detectedBy) {
217
+ return {
218
+ type: 'problem',
219
+ detectedBy,
220
+ problems: [
221
+ await this.addErrorTrace({
222
+ // It's about a stack
223
+ logicalId: undefined,
224
+ message: changeSet.StatusReason ?? '',
225
+ parentStackLogicalIds: this.parentStackLogicalIds,
226
+ stackArn: changeSet.StackId ?? '',
227
+ physicalId: changeSet.StackId,
228
+ resourceType: 'AWS::CloudFormation::Stack',
229
+ }),
230
+ ],
231
+ };
232
+ }
233
+ /**
234
+ * Look for nested change sets that have failed, and diagnose those.
235
+ */
236
+ async _diagnoseNestedChangeSetFailure(changeSet) {
237
+ const nested = await this._findFailedNestedStack(changeSet);
238
+ if (!nested) {
239
+ // That's weird. Let's return the change set's status reason as a non-specific error
240
+ return this._nonSpecificChangeSetError(changeSet, {
241
+ type: 'change-set',
242
+ changeSetName: changeSet.ChangeSetName ?? '',
243
+ changeSetStatus: changeSet.Status ?? '',
244
+ statusReason: changeSet.StatusReason ?? '',
245
+ });
246
+ }
247
+ const nestedCs = await this.cfn.describeChangeSet({
248
+ ChangeSetName: nested.changeSetName,
249
+ StackName: nested.stackName,
250
+ });
251
+ const nestedDiag = new CloudFormationStackDiagnoser(this.props);
252
+ nestedDiag.parentStackLogicalIds = [...this.parentStackLogicalIds, nested.logicalId];
253
+ return nestedDiag._diagnoseChangeSetFailure(nestedCs);
254
+ }
255
+ async _findFailedNestedStack(changeSet) {
256
+ // The status reason only includes the change set ID, but we also need the stack name. The way to get this is
257
+ // describe the current change set, then from the Changes find the stack whose ChangeSetId is mentioned in the
258
+ // status reason, then look up that change set and recurse into a regular change set diagnosis.
259
+ let nextToken = undefined;
260
+ do {
261
+ // Changes in this response might be paginated
262
+ const resp = await this.cfn.describeChangeSet({
263
+ StackName: changeSet.StackName,
264
+ ChangeSetName: changeSet.ChangeSetName,
265
+ ...nextToken ? { NextToken: nextToken } : {},
266
+ });
267
+ for (const change of resp.Changes ?? []) {
268
+ if (change.Type === client_cloudformation_1.ChangeType.Resource && change.ResourceChange?.ResourceType === 'AWS::CloudFormation::Stack' && change.ResourceChange?.ChangeSetId && changeSet.StatusReason?.includes(change.ResourceChange?.ChangeSetId)) {
269
+ return {
270
+ changeSetName: change.ResourceChange.ChangeSetId,
271
+ stackName: change.ResourceChange.PhysicalResourceId ?? '',
272
+ logicalId: change.ResourceChange.LogicalResourceId ?? '',
273
+ };
274
+ }
275
+ }
276
+ nextToken = resp.NextToken;
277
+ } while (nextToken);
278
+ return undefined;
279
+ }
280
+ /**
281
+ * Try to parse failed auto-imports out from a change set status
282
+ *
283
+ * The pattern looks like this:
284
+ *
285
+ * ```
286
+ * CloudFormation is attempting to import some resources because they already exist in your account. The resources must have the DeletionPolicy attribute set to 'Retain' or 'RetainExceptOnCreate' in the template for successful import. The affected resources are SomeBucketD5B70704 ({BucketName=zomaareenbucket})
287
+ * ```
288
+ *
289
+ * Followed by
290
+ *
291
+ * ```
292
+ * LogicalID ({Prop=Value,Prop=Value}), LogicalID ({Prop=Value}), ...
293
+ * ```
294
+ */
295
+ _tryDetectFailedAutoImport(changeSet) {
296
+ const message = changeSet.StatusReason;
297
+ // Only enhance the specific CFN error about importing existing resources
298
+ if (!message?.includes('CloudFormation is attempting to import some resources because they already exist in your account')) {
299
+ return undefined;
300
+ }
301
+ const marker = 'The affected resources are ';
302
+ const markerIndex = message.indexOf(marker);
303
+ if (markerIndex === -1) {
304
+ return undefined;
305
+ }
306
+ const ret = [];
307
+ let remaining = message.slice(markerIndex + marker.length);
308
+ while (remaining) {
309
+ const endIx = remaining.indexOf('), ');
310
+ const thisResource = endIx > -1 ? remaining.slice(0, endIx + 1) : remaining;
311
+ remaining = remaining.slice(thisResource.length + 2);
312
+ // thisResource = "LogicalId ({Prop=Value, Prop=Value})"
313
+ const openParen = thisResource.indexOf('(');
314
+ const logicalId = openParen > -1 ? thisResource.slice(0, openParen).trim() : undefined;
315
+ ret.push({
316
+ message: `Automatic import of existing resource ${thisResource} needs a DeletionPolicy of \'Retain\' or \'RetainExceptOnCreate\'. Set the removal policy to \'RemovalPolicy.RETAIN\' or \'RemovalPolicy.RETAIN_ON_UPDATE_OR_DELETE\' (See https://docs.aws.amazon.com/cdk/v2/guide/resources.html#resources-removal)`,
317
+ parentStackLogicalIds: this.parentStackLogicalIds,
318
+ stackArn: changeSet.StackId ?? '',
319
+ errorCode: 'AutomaticImportNeedsRetain',
320
+ logicalId,
321
+ });
322
+ }
323
+ return ret;
324
+ }
325
+ }
326
+ exports.CloudFormationStackDiagnoser = CloudFormationStackDiagnoser;
327
+ /**
328
+ * Return true if the given change set has no changes
329
+ *
330
+ * This must be determined from the status, not the 'Changes' array on the
331
+ * object; the latter can be empty because no resources were changed, but if
332
+ * there are changes to Outputs, the change set can still be executed.
333
+ */
334
+ function changeSetHasNoChanges(description) {
335
+ const noChangeErrorPrefixes = [
336
+ // Error message for a regular template
337
+ "The submitted information didn't contain changes.",
338
+ // Error message when a Transform is involved (see #10650)
339
+ 'No updates are to be performed.',
340
+ ];
341
+ return (description.Status === 'FAILED' && noChangeErrorPrefixes.some((p) => (description.StatusReason ?? '').startsWith(p)));
342
+ }
343
+ function resourceErrorFromEarlyValidationError(stackId, parentStackLogicalIds, ev) {
344
+ return {
345
+ logicalId: ev.logicalId,
346
+ physicalId: ev.physicalId,
347
+ resourceType: ev.resourceType,
348
+ message: `${ev.message} (at ${ev.documentPath})`,
349
+ errorCode: `${ev.validationName}_${ev.eventType}`,
350
+ parentStackLogicalIds,
351
+ stackArn: stackId,
352
+ };
353
+ }
354
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhY2stZGlhZ25vc2VyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3RhY2stZGlhZ25vc2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQWtZQSxzREFXQztBQTVZRCwwRUFBNkU7QUFFN0UsdUVBQTBFO0FBTTFFLGtEQUE4RDtBQUU5RCwrREFBMkQ7QUFVM0Q7Ozs7Ozs7Ozs7OztHQVlHO0FBQ0gsTUFBYSw0QkFBNEI7SUFJVjtJQUhaLEdBQUcsQ0FBd0I7SUFDcEMscUJBQXFCLENBQVc7SUFFeEMsWUFBNkIsS0FBd0M7UUFBeEMsVUFBSyxHQUFMLEtBQUssQ0FBbUM7UUFDbkUsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUMzQyxJQUFJLENBQUMscUJBQXFCLEdBQUcsRUFBRSxDQUFDO0lBQ2xDLENBQUM7SUFFRDs7T0FFRztJQUNJLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxTQUFpQjtRQUM5QyxJQUFJLENBQUM7WUFDSCxNQUFNLFFBQVEsR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUM7WUFDekUsTUFBTSxLQUFLLEdBQUcsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ25DLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztnQkFDWCxPQUFPO29CQUNMLElBQUksRUFBRSxrQkFBa0I7b0JBQ3hCLE9BQU8sRUFBRSxtQkFBbUIsU0FBUyxZQUFZO2lCQUNsRCxDQUFDO1lBQ0osQ0FBQztZQUVELE1BQU0sTUFBTSxHQUFHLDBCQUFXLENBQUMsb0JBQW9CLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDdkQsSUFBSSxNQUFNLENBQUMsWUFBWSxFQUFFLENBQUM7Z0JBQ3hCLE9BQU87b0JBQ0wsSUFBSSxFQUFFLGtCQUFrQjtvQkFDeEIsT0FBTyxFQUFF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RUYsT0FBTyxDQUNMLFdBQVcsQ0FBQyxNQUFNLEtBQUssUUFBUSxJQUFJLHFCQUFxQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxXQUFXLENBQUMsWUFBWSxJQUFJLEVBQUUsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUNySCxDQUFDO0FBQ0osQ0FBQztBQUVELFNBQVMscUNBQXFDLENBQUMsT0FBZSxFQUFFLHFCQUErQixFQUFFLEVBQTBCO0lBQ3pILE9BQU87UUFDTCxTQUFTLEVBQUUsRUFBRSxDQUFDLFNBQVM7UUFDdkIsVUFBVSxFQUFFLEVBQUUsQ0FBQyxVQUFVO1FBQ3pCLFlBQVksRUFBRSxFQUFFLENBQUMsWUFBWTtRQUM3QixPQUFPLEVBQUUsR0FBRyxFQUFFLENBQUMsT0FBTyxRQUFRLEVBQUUsQ0FBQyxZQUFZLEdBQUc7UUFDaEQsU0FBUyxFQUFFLEdBQUcsRUFBRSxDQUFDLGNBQWMsSUFBSSxFQUFFLENBQUMsU0FBUyxFQUFFO1FBQ2pELHFCQUFxQjtRQUNyQixRQUFRLEVBQUUsT0FBTztLQUNsQixDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgQ2hhbmdlU2V0U3VtbWFyeSwgU3RhY2sgfSBmcm9tICdAYXdzLXNkay9jbGllbnQtY2xvdWRmb3JtYXRpb24nO1xuaW1wb3J0IHsgQ2hhbmdlU2V0U3RhdHVzLCBDaGFuZ2VUeXBlIH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LWNsb3VkZm9ybWF0aW9uJztcbmltcG9ydCB0eXBlIHsgQ2hhbmdlU2V0UmVzb3VyY2VFcnJvciB9IGZyb20gJy4vY2hhbmdlc2V0LWVycm9yLWZldGNoZXInO1xuaW1wb3J0IHsgQ2hhbmdlU2V0UmVzb3VyY2VFcnJvckZldGNoZXIgfSBmcm9tICcuL2NoYW5nZXNldC1lcnJvci1mZXRjaGVyJztcbmltcG9ydCB0eXBlIHsgU3RhY2tEaWFnbm9zaXMsIFN0YWNrUHJvYmxlbVNvdXJjZSwgVHJhY2VkUmVzb3VyY2VFcnJvciB9IGZyb20gJy4uLy4uL2FjdGlvbnMvZGlhZ25vc2UnO1xuaW1wb3J0IHR5cGUgeyBJQ2xvdWRGb3JtYXRpb25DbGllbnQsIFNESyB9IGZyb20gJy4uL2F3cy1hdXRoL3Nkayc7XG5pbXBvcnQgdHlwZSB7IEVudmlyb25tZW50UmVzb3VyY2VzIH0gZnJvbSAnLi4vZW52aXJvbm1lbnQnO1xuaW1wb3J0IHR5cGUgeyBJb0hlbHBlciB9IGZyb20gJy4uL2lvL3ByaXZhdGUvaW8taGVscGVyJztcbmltcG9ydCB0eXBlIHsgSVNvdXJjZVRyYWNlciB9IGZyb20gJy4uL3NvdXJjZS10cmFjaW5nL3ByaXZhdGUvc291cmNlLXRyYWNpbmcnO1xuaW1wb3J0IHsgUG9sbFJhbmdlLCBTdGFja0V2ZW50UG9sbGVyIH0gZnJvbSAnLi4vc3RhY2stZXZlbnRzJztcbmltcG9ydCB0eXBlIHsgUmVzb3VyY2VFcnJvciwgUmVzb3VyY2VFcnJvcnMgfSBmcm9tICcuLi9zdGFjay1ldmVudHMvcmVzb3VyY2UtZXJyb3JzJztcbmltcG9ydCB7IFN0YWNrU3RhdHVzIH0gZnJvbSAnLi4vc3RhY2stZXZlbnRzL3N0YWNrLXN0YXR1cyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2xvdWRGb3JtYXRpb25TdGFja0RpYWdub3NlclByb3BzIHtcbiAgcmVhZG9ubHkgc2RrOiBTREs7XG4gIHJlYWRvbmx5IGVudlJlc291cmNlcz86IEVudmlyb25tZW50UmVzb3VyY2VzO1xuICByZWFkb25seSBzb3VyY2VUcmFjZXI6IElTb3VyY2VUcmFjZXI7XG4gIHJlYWRvbmx5IGlvSGVscGVyOiBJb0hlbHBlcjtcbiAgcmVhZG9ubHkgdG9wTGV2ZWxTdGFja0hpZXJhcmNoaWNhbElkOiBzdHJpbmc7XG59XG5cbi8qKlxuICogRGlhZ25vc2UgYSBzdGFjaydzIGZhaWxlZCBzdGF0ZVxuICpcbiAqIC0gRmlyc3QsIGRldGVybWluZSB0aGUgc3RhY2sncyBzdGF0ZS5cbiAqIC0gSWYgaXQgaXMgaW4gYSBmYWlsZWQgc3RhdGUsIHdlIHN0YXJ0ZWQgYSBkZXBsb3ltZW50IHRoYXQgZmFpbGVkLiBEZXNjcmliZSB0aGUgc3RhY2tcbiAqICAgZXZlbnRzLCBhbmQgdHJ5IHRvIGRldGVybWluZSB0aGUgcm9vdCBjYXVzZSBmcm9tIHRoYXQuXG4gKiAtIElmIGl0IGlzIGluIGEgbm9ybWFsIHN0YXRlLCBzZWUgaWYgdGhlcmUgYXJlIGFueSBmYWlsZWQgY2hhbmdlIHNldHMuIEVpdGhlclxuICogICBnZXQgdGhlIGZhaWx1cmUgbWVzc2FnZSBmcm9tIHRoZSBjaGFuZ2Ugc2V0LCBvciBnZXQgdGhlIGZhaWx1cmUgZXZlbnRzIGZyb21cbiAqICAgdGhlIGNoYW5nZSBzZXQgKGVhcmx5IHZhbGlkYXRpb24pLlxuICpcbiAqIFRoaXMgY2xhc3Mgd29ya3MgYXQgdGhlIENsb3VkRm9ybWF0aW9uIGxldmVsLCBhbmQgZG9lcyBub3QgZGVhbCB3aXRoIHRyYWNpbmdcbiAqIENsb3VkRm9ybWF0aW9uIGVycm9ycyB0byBjb25zdHJ1Y3QgY29kZSBzb3VyY2VzIHlldC5cbiAqL1xuZXhwb3J0IGNsYXNzIENsb3VkRm9ybWF0aW9uU3RhY2tEaWFnbm9zZXIge1xuICBwcml2YXRlIHJlYWRvbmx5IGNmbjogSUNsb3VkRm9ybWF0aW9uQ2xpZW50O1xuICBwcml2YXRlIHBhcmVudFN0YWNrTG9naWNhbElkczogc3RyaW5nW107XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBwcm9wczogQ2xvdWRGb3JtYXRpb25TdGFja0RpYWdub3NlclByb3BzKSB7XG4gICAgdGhpcy5jZm4gPSB0aGlzLnByb3BzLnNkay5jbG91ZEZvcm1hdGlvbigpO1xuICAgIHRoaXMucGFyZW50U3RhY2tMb2dpY2FsSWRzID0gW107XG4gIH1cblxuICAvKipcbiAgICogRGlhZ25vc2UgYSBzdGFjaydzIHJvb3QgY2F1c2UgZ2l2ZW4gbm8gcHJlLWV4aXN0aW5nIHN0YXRlXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgZGlhZ25vc2VGcm9tRnJlc2goc3RhY2tOYW1lOiBzdHJpbmcpOiBQcm9taXNlPFN0YWNrRGlhZ25vc2lzPiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5jZm4uZGVzY3JpYmVTdGFja3MoeyBTdGFja05hbWU6IHN0YWNrTmFtZSB9KTtcbiAgICAgIGNvbnN0IHN0YWNrID0gcmVzcG9uc2UuU3RhY2tzPy5bMF07XG4gICAgICBpZiAoIXN0YWNrKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdHlwZTogJ2Vycm9yLWRpYWdub3NpbmcnLFxuICAgICAgICAgIG1lc3NhZ2U6IGBTdGFjayB3aXRoIG5hbWUgJHtzdGFja05hbWV9IG5vdCBmb3VuZGAsXG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHN0YXR1cyA9IFN0YWNrU3RhdHVzLmZyb21TdGFja0Rlc2NyaXB0aW9uKHN0YWNrKTtcbiAgICAgIGlmIChzdGF0dXMuaXNJblByb2dyZXNzKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgdHlwZTogJ2Vycm9yLWRpYWdub3NpbmcnLFxuICAgICAgICAgIG1lc3NhZ2U6IGBTdGFjayB3aXRoIG5hbWUgJHtzdGFja05hbWV9IGlzIGN1cnJlbnRseSBiZWluZyB1cGRhdGVkICgke3N0YXR1cy5uYW1lfSkuIFRyeSBhZ2FpbiB3aGVuIGl0J3MgZmluaXNoZWQuYCxcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgaWYgKHN0YXR1cy5pc0ZhaWx1cmUpIHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuX2RpYWdub3NlVmlhU3RhY2tFdmVudHMoc3RhY2tOYW1lLCBzdGFjayk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLl9kaWFnbm9zZUNoYW5nZVNldEZhaWx1cmVGcm9tU3RhY2tOYW1lKHN0YWNrTmFtZSk7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICByZXR1cm4geyB0eXBlOiAnZXJyb3ItZGlhZ25vc2luZycsIG1lc3NhZ2U6IGUubWVzc2FnZSB9O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEaWFnbm9zZSBwb3RlbnRpYWwgcHJvYmxlbXMgd2l0aCB0aGUgY2hhbmdlIHNldFxuICAgKi9cbiAgcHVibGljIGFzeW5jIGRpYWdub3NlQ2hhbmdlU2V0KGNoYW5nZVNldDogQ2hhbmdlU2V0U3VtbWFyeSk6IFByb21pc2U8U3RhY2tEaWFnbm9zaXM+IHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGF3YWl0IHRoaXMuX2RpYWdub3NlQ2hhbmdlU2V0RmFpbHVyZShjaGFuZ2VTZXQpO1xuICAgIH0gY2F0Y2ggKGU6IGFueSkge1xuICAgICAgcmV0dXJuIHsgdHlwZTogJ2Vycm9yLWRpYWdub3NpbmcnLCBtZXNzYWdlOiBlLm1lc3NhZ2UgfTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGlhZ25vc2UgcG90ZW50aWFsIHByb2JsZW1zIHdpdGggdGhlIGNoYW5nZSBzZXRcbiAgICovXG4gIHB1YmxpYyBhc3luYyBkaWFnbm9zZUZyb21FcnJvckNvbGxlY3Rpb24oZXJyb3JzOiBSZXNvdXJjZUVycm9ycywgc3RhY2s6IFN0YWNrKTogUHJvbWlzZTxTdGFja0RpYWdub3Npcz4ge1xuICAgIGlmIChlcnJvcnMuaXNFbXB0eSgpKSB7XG4gICAgICByZXR1cm4geyB0eXBlOiAnbm8tcHJvYmxlbScgfTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgdHlwZTogJ3Byb2JsZW0nLFxuICAgICAgZGV0ZWN0ZWRCeToge1xuICAgICAgICB0eXBlOiAnZGVwbG95bWVudCcsXG4gICAgICAgIHN0YWNrU3RhdHVzOiBzdGFjay5TdGFja1N0YXR1cyA/PyAnJyxcbiAgICAgICAgc3RhdHVzUmVhc29uOiBzdGFjay5TdGFja1N0YXR1c1JlYXNvbiA/PyAnJyxcbiAgICAgIH0sXG4gICAgICBwcm9ibGVtczogYXdhaXQgdGhpcy5hZGRFcnJvclRyYWNlcyhlcnJvcnMuYWxsKSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIERpYWdub3NlIGEgZGVwbG95bWVudCBmYWlsdXJlIHZpYSBzdGFjayBldmVudHNcbiAgICpcbiAgICogVGhpcyBpcyB0aGUgc2FtZSBsb2dpYyB0aGF0IHRoZSBkZXBsb3ltZW50IG1vbml0b3IgdXNlcy5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgX2RpYWdub3NlVmlhU3RhY2tFdmVudHMoc3RhY2tOYW1lOiBzdHJpbmcsIHN0YWNrOiBTdGFjayk6IFByb21pc2U8U3RhY2tEaWFnbm9zaXM+IHtcbiAgICBjb25zdCBwb2xsZXIgPSBuZXcgU3RhY2tFdmVudFBvbGxlcih0aGlzLmNmbiwge1xuICAgICAgc3RhY2tOYW1lLFxuICAgICAgaW5pdGlhbFBvbGxSYW5nZTogUG9sbFJhbmdlLm1vc3RSZWNlbnRPcGVyYXRpb24oKSxcbiAgICB9KTtcblxuICAgIC8vIFdlIGRvbid0IG5lZWQgdGhlIHJlc3VsdGluZyBldmVudHMgb2YgcG9sbGluZy4gUG9sbGluZyB3aWxsIGF1dG9tYXRpY2FsbHkgdXBkYXRlIHRoZSBlcnJvciBjb2xsZWN0aW9uLFxuICAgIC8vIHdoaWNoIGlzIHRoZSB0aGluZyB3ZSBjYXJlIGFib3V0LlxuICAgIGF3YWl0IHBvbGxlci5wb2xsKCk7XG5cbiAgICByZXR1cm4gdGhpcy5kaWFnbm9zZUZyb21FcnJvckNvbGxlY3Rpb24ocG9sbGVyLmVycm9ycywgc3RhY2spO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBfZGlhZ25vc2VDaGFuZ2VTZXRGYWlsdXJlRnJvbVN0YWNrTmFtZShzdGFja05hbWU6IHN0cmluZyk6IFByb21pc2U8U3RhY2tEaWFnbm9zaXM+IHtcbiAgICBjb25zdCBjcyA9IChhd2FpdCB0aGlzLmNmbi5saXN0Q2hhbmdlU2V0cyh7XG4gICAgICBTdGFja05hbWU6IHN0YWNrTmFtZSxcbiAgICB9KSkuU3VtbWFyaWVzID8/IFtdO1xuXG4gICAgY29uc3QgcGVuZGluZyA9IGNzLmZpbHRlcih4ID0+IHguU3RhdHVzID09PSBDaGFuZ2VTZXRTdGF0dXMuQ1JFQVRFX0lOX1BST0dSRVNTIHx8IHguU3RhdHVzID09PSBDaGFuZ2VTZXRTdGF0dXMuQ1JFQVRFX1BFTkRJTkcpO1xuICAgIGlmIChwZW5kaW5nLmxlbmd0aCA+IDApIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHR5cGU6ICdlcnJvci1kaWFnbm9zaW5nJyxcbiAgICAgICAgbWVzc2FnZTogYFN0YWNrIHdpdGggbmFtZSAke3N0YWNrTmFtZX0gaGFzIGNoYW5nZSBzZXRzIGN1cnJlbnRseSBiZWluZyBjcmVhdGVkICgke3BlbmRpbmdbMF0uQ2hhbmdlU2V0TmFtZX0pLiBUcnkgYWdhaW4gd2hlbiBpdCdzIGZpbmlzaGVkLmAsXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IGZhaWxlZCA9IGNzLmZpbHRlcih4ID0+IHguU3RhdHVzID09PSBDaGFuZ2VTZXRTdGF0dXMuRkFJTEVEKTtcbiAgICBpZiAoZmFpbGVkLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIHsgdHlwZTogJ25vLXByb2JsZW0nIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuX2RpYWdub3NlQ2hhbmdlU2V0RmFpbHVyZShmYWlsZWRbMF0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRyeSB0byBkaWFnbm9zZSB0aGUgcmVhc29uIHRoYXQgY2F1c2VkIGEgY2hhbmdlc2V0IHRvIGZhaWwgdG8gY3JlYXRlXG4gICAqXG4gICAqIFRoZXJlIGFyZSBhIGNvdXBsZSBvZiBkaWZmZXJlbnQgcmVhc29ucyB0aGlzIGNhbiBoYXBwZW4sIGFuZCB3ZSBnbyB0aHJvdWdoIGVhY2ggb2YgdGhlbSBpbiBvcmRlci5cbiAgICpcbiAgICogVXN1YWxseSB0aGlzIHN0YXJ0cyBmcm9tIHRyeWluZyB0byBkZXRlY3QgYW4gZXJyb3IgbWVzc2FnZSBwYXR0ZXJuIGluIHRoZSBjaGFuZ2Ugc2V0IHN0YXR1cyByZWFzb24sXG4gICAqIGFuZCB0aGVuIHBvdGVudGlhbGx5IGdvaW5nIHRvIGZldGNoIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gdXNpbmcgYWRkaXRpb25hbCBBUEkgY2FsbHMuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIF9kaWFnbm9zZUNoYW5nZVNldEZhaWx1cmUoY2hhbmdlU2V0OiBDaGFuZ2VTZXRTdW1tYXJ5KTogUHJvbWlzZTxTdGFja0RpYWdub3Npcz4ge1xuICAgIGlmIChjaGFuZ2VTZXQuU3RhdHVzICE9PSBDaGFuZ2VTZXRTdGF0dXMuRkFJTEVEKSB7XG4gICAgICByZXR1cm4geyB0eXBlOiAnbm8tcHJvYmxlbScgfTtcbiAgICB9XG5cbiAgICBpZiAoY2hhbmdlU2V0SGFzTm9DaGFuZ2VzKGNoYW5nZVNldCkpIHtcbiAgICAgIC8vIFRoaXMgd2lsbCBsZWFkIHRvIGEgY2hhbmdlIHNldCB0aGF0IGlzIEZBSUxFRCBidXQgaXQncyBub3QgYWN0dWFsbHkgYSBwcm9ibGVtXG4gICAgICByZXR1cm4geyB0eXBlOiAnbm8tcHJvYmxlbScgfTtcbiAgICB9XG5cbiAgICAvLyBXZSByZXBvcnQgZWFybHkgdmFsaWRhdGlvbiBlcnJvcnMgZGlmZmVyZW50bHkgdGhhbiBnZW5lcmljIGNoYW5nZXNldCBlcnJvcnMuIE1vc3RseVxuICAgIC8vIGZvciBoaXN0b3JpY2FsIHJlYXNvbnMuXG4gICAgY29uc3QgaXNFYXJseVZhbGlkYXRpb25FcnJvciA9IGNoYW5nZVNldC5TdGF0dXNSZWFzb24/LmluY2x1ZGVzKCdBV1M6OkVhcmx5VmFsaWRhdGlvbicpO1xuICAgIGlmIChpc0Vhcmx5VmFsaWRhdGlvbkVycm9yKSB7XG4gICAgICByZXR1cm4gdGhpcy5fcmVwb3J0Q2hhbmdlU2V0RmFpbHVyZUZyb21FdmVudHMoY2hhbmdlU2V0LCB7XG4gICAgICAgIHR5cGU6ICdlYXJseS12YWxpZGF0aW9uJyxcbiAgICAgICAgY2hhbmdlU2V0TmFtZTogY2hhbmdlU2V0LkNoYW5nZVNldE5hbWUgPz8gJycsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBXZSB3aWxsIHJlY3Vyc2UgaW50byBuZXN0ZWQgY2hhbmdlIHNldHMgaWYgbmVjZXNzYXJ5LlxuICAgIGlmIChjaGFuZ2VTZXQuU3RhdHVzUmVhc29uPy5pbmNsdWRlcygnTmVzdGVkIGNoYW5nZSBzZXQnKSkge1xuICAgICAgcmV0dXJuIHRoaXMuX2RpYWdub3NlTmVzdGVkQ2hhbmdlU2V0RmFpbHVyZShjaGFuZ2VTZXQpO1xuICAgIH1cblxuICAgIC8vIFdlIHNwZWNpYWwtY2FzZSBmYWlsZWQgYXV0b21hdGljIGltcG9ydHMuIFdlIGtub3cgYWxsIHRoZSBtZWF0IG9mIHRoZSBlcnJvciBkZXRhaWxzIGFyZSBpbiB0aGVcbiAgICAvLyBzdGF0dXMgcmVhc29uLCBhbmQgbm93aGVyZSBlbHNlLiBXZSBwYXJzZSBpdCBzcGVjaWZpY2FsbHkuXG4gICAgY29uc3QgZmFpbGVkQXV0b0Vycm9ycyA9IHRoaXMuX3RyeURldGVjdEZhaWxlZEF1dG9JbXBvcnQoY2hhbmdlU2V0KTtcbiAgICBpZiAoZmFpbGVkQXV0b0Vycm9ycykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogJ3Byb2JsZW0nLFxuICAgICAgICBkZXRlY3RlZEJ5OiB7XG4gICAgICAgICAgdHlwZTogJ2NoYW5nZS1zZXQnLFxuICAgICAgICAgIGNoYW5nZVNldFN0YXR1czogY2hhbmdlU2V0LlN0YXR1cyA/PyAnJyxcbiAgICAgICAgICBjaGFuZ2VTZXROYW1lOiBjaGFuZ2VTZXQuQ2hhbmdlU2V0TmFtZSA/PyAnJyxcbiAgICAgICAgICBzdGF0dXNSZWFzb246IGNoYW5nZVNldC5TdGF0dXNSZWFzb24gPz8gJycsXG4gICAgICAgIH0sXG4gICAgICAgIHByb2JsZW1zOiBhd2FpdCB0aGlzLmFkZEVycm9yVHJhY2VzKGZhaWxlZEF1dG9FcnJvcnMpLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBPdGhlcndpc2UsIGEgZ2VuZXJpYyBjaGFuZ2Ugc2V0IGNyZWF0aW9uIGVycm9yIHdoZXJlIGBEZXNjcmliZUV2ZW50c2BcbiAgICAvLyBtaWdodCBvciBtaWdodCBub3QgZ2l2ZSBhZGRpdGlvbmFsIGluZm9ybWF0aW9uLlxuICAgIHJldHVybiB0aGlzLl9yZXBvcnRDaGFuZ2VTZXRGYWlsdXJlRnJvbUV2ZW50cyhjaGFuZ2VTZXQsIHtcbiAgICAgIHR5cGU6ICdjaGFuZ2Utc2V0JyxcbiAgICAgIGNoYW5nZVNldFN0YXR1czogY2hhbmdlU2V0LlN0YXR1cyA/PyAnJyxcbiAgICAgIGNoYW5nZVNldE5hbWU6IGNoYW5nZVNldC5DaGFuZ2VTZXROYW1lID8/ICcnLFxuICAgICAgc3RhdHVzUmVhc29uOiBjaGFuZ2VTZXQuU3RhdHVzUmVhc29uID8/ICcnLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRyeSB0byByZWFkIHRoZSByZXNvdXJjZS1zcGVjaWZpYyByZWFzb25zIGZvciBhIGNoYW5nZXNldCBmYWlsdXJlIGZyb20gYERlc2NyaWJlRXZlbnRzYC5cbiAgICpcbiAgICogSWYgd2UgY291bGRuJ3QgcmVhZCB0aGUgZXZlbnRzIG9yIHRoZXJlIGFyZSAwIGVycm9ycyByZXR1cm5lZCBieSB0aGF0IEFQSSwgcmV0dXJuIGEgZ2VuZXJpY1xuICAgKiBlcnJvci5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgX3JlcG9ydENoYW5nZVNldEZhaWx1cmVGcm9tRXZlbnRzKGNoYW5nZVNldDogQ2hhbmdlU2V0U3VtbWFyeSwgZGV0ZWN0ZWRCeTogU3RhY2tQcm9ibGVtU291cmNlKTogUHJvbWlzZTxTdGFja0RpYWdub3Npcz4ge1xuICAgIGNvbnN0IGV2ID0gYXdhaXQgbmV3IENoYW5nZVNldFJlc291cmNlRXJyb3JGZXRjaGVyKHRoaXMucHJvcHMuc2RrLCB0aGlzLnByb3BzLmVudlJlc291cmNlcylcbiAgICAgIC5mZXRjaERldGFpbHNTdHJ1Y3R1cmVkKGNoYW5nZVNldC5DaGFuZ2VTZXROYW1lISwgY2hhbmdlU2V0LlN0YWNrTmFtZSEpO1xuXG4gICAgLy8gSWYgd2UgaGF2ZSBlcnJvcnMgdG8gcmV0dXJuLCByZXR1cm4gdGhlbVxuICAgIGlmIChldi50eXBlID09PSAncmVzb3VyY2UtZXJyb3JzJyAmJiBldi5lcnJvcnMubGVuZ3RoID4gMCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdHlwZTogJ3Byb2JsZW0nLFxuICAgICAgICBkZXRlY3RlZEJ5LFxuICAgICAgICBwcm9ibGVtczogYXdhaXQgdGhpcy5hZGRFcnJvclRyYWNlcyhldi5lcnJvcnMubWFwKChlKSA9PiByZXNvdXJjZUVycm9yRnJvbUVhcmx5VmFsaWRhdGlvbkVycm9yKGNoYW5nZVNldC5TdGFja0lkID8/ICcnLCB0aGlzLnBhcmVudFN0YWNrTG9naWNhbElkcywgZSkpKSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gT3RoZXJ3aXNlLCB3ZSB3aWxsIHJldHVybiBhIGdlbmVyaWMgY2hhbmdlc2V0IGVycm9yIG1lc3NhZ2UuIElmIHRoZXJlIHdhcyBhIHByb2JsZW1cbiAgICAvLyBjaGVja2luZywgd2UgbG9nIHRoYXQgZm9yIGdvb2QgbWVhc3VyZSBidXQgdGhlIHJlc3VsdCBpcyB0aGUgc2FtZS5cbiAgICBpZiAoZXYudHlwZSA9PT0gJ2NvdWxkLW5vdC1jaGVjaycpIHtcbiAgICAgIGF3YWl0IHRoaXMucHJvcHMuaW9IZWxwZXIuZGVmYXVsdHMud2Fybihldi5tZXNzYWdlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5fbm9uU3BlY2lmaWNDaGFuZ2VTZXRFcnJvcihjaGFuZ2VTZXQsIGRldGVjdGVkQnkpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBhZGRFcnJvclRyYWNlcyhlcnJzOiByZWFkb25seSBSZXNvdXJjZUVycm9yW10pOiBQcm9taXNlPFRyYWNlZFJlc291cmNlRXJyb3JbXT4ge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAY2RrbGFicy9wcm9taXNlYWxsLW5vLXVuYm91bmRlZC1wYXJhbGxlbGlzbVxuICAgIHJldHVybiBQcm9taXNlLmFsbChlcnJzLm1hcCgoZSkgPT4gdGhpcy5hZGRFcnJvclRyYWNlKGUpKSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGFkZEVycm9yVHJhY2UoZXJyOiBSZXNvdXJjZUVycm9yKTogUHJvbWlzZTxUcmFjZWRSZXNvdXJjZUVycm9yPiB7XG4gICAgbGV0IHNvdXJjZVRyYWNlO1xuICAgIGlmIChlcnIubG9naWNhbElkKSB7XG4gICAgICBzb3VyY2VUcmFjZSA9IGF3YWl0IHRoaXMucHJvcHMuc291cmNlVHJhY2VyLnRyYWNlUmVzb3VyY2UoZXJyLnN0YWNrQXJuLCBlcnIucGFyZW50U3RhY2tMb2dpY2FsSWRzLCBlcnIubG9naWNhbElkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc291cmNlVHJhY2UgPSBhd2FpdCB0aGlzLnByb3BzLnNvdXJjZVRyYWNlci50cmFjZVN0YWNrKGVyci5zdGFja0FybiwgZXJyLnBhcmVudFN0YWNrTG9naWNhbElkcyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHsgLi4uZXJyLCBzb3VyY2VUcmFjZSwgdG9wTGV2ZWxTdGFja0hpZXJhcmNoaWNhbElkOiB0aGlzLnByb3BzLnRvcExldmVsU3RhY2tIaWVyYXJjaGljYWxJZCB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkIGEgZ2VuZXJpYyBzdGFjayBlcnJvciBmcm9tIHRoZSBnaXZlbiBjaGFuZ2Ugc2V0IGluZm9ybWF0aW9uXG4gICAqXG4gICAqIFdlIGNhbid0IHBvaW50IHRvIGEgc3BlY2lmaWMgcmVzb3VyY2UuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIF9ub25TcGVjaWZpY0NoYW5nZVNldEVycm9yKGNoYW5nZVNldDogQ2hhbmdlU2V0U3VtbWFyeSwgZGV0ZWN0ZWRCeTogU3RhY2tQcm9ibGVtU291cmNlKTogUHJvbWlzZTxTdGFja0RpYWdub3Npcz4ge1xuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiAncHJvYmxlbScsXG4gICAgICBkZXRlY3RlZEJ5LFxuICAgICAgcHJvYmxlbXM6IFtcbiAgICAgICAgYXdhaXQgdGhpcy5hZGRFcnJvclRyYWNlKHtcbiAgICAgICAgICAvLyBJdCdzIGFib3V0IGEgc3RhY2tcbiAgICAgICAgICBsb2dpY2FsSWQ6IHVuZGVmaW5lZCxcbiAgICAgICAgICBtZXNzYWdlOiBjaGFuZ2VTZXQuU3RhdHVzUmVhc29uID8/ICcnLFxuICAgICAgICAgIHBhcmVudFN0YWNrTG9naWNhbElkczogdGhpcy5wYXJlbnRTdGFja0xvZ2ljYWxJZHMsXG4gICAgICAgICAgc3RhY2tBcm46IGNoYW5nZVNldC5TdGFja0lkID8/ICcnLFxuICAgICAgICAgIHBoeXNpY2FsSWQ6IGNoYW5nZVNldC5TdGFja0lkLFxuICAgICAgICAgIHJlc291cmNlVHlwZTogJ0FXUzo6Q2xvdWRGb3JtYXRpb246OlN0YWNrJyxcbiAgICAgICAgfSksXG4gICAgICBdLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogTG9vayBmb3IgbmVzdGVkIGNoYW5nZSBzZXRzIHRoYXQgaGF2ZSBmYWlsZWQsIGFuZCBkaWFnbm9zZSB0aG9zZS5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgX2RpYWdub3NlTmVzdGVkQ2hhbmdlU2V0RmFpbHVyZShjaGFuZ2VTZXQ6IENoYW5nZVNldFN1bW1hcnkpOiBQcm9taXNlPFN0YWNrRGlhZ25vc2lzPiB7XG4gICAgY29uc3QgbmVzdGVkID0gYXdhaXQgdGhpcy5fZmluZEZhaWxlZE5lc3RlZFN0YWNrKGNoYW5nZVNldCk7XG4gICAgaWYgKCFuZXN0ZWQpIHtcbiAgICAgIC8vIFRoYXQncyB3ZWlyZC4gTGV0J3MgcmV0dXJuIHRoZSBjaGFuZ2Ugc2V0J3Mgc3RhdHVzIHJlYXNvbiBhcyBhIG5vbi1zcGVjaWZpYyBlcnJvclxuICAgICAgcmV0dXJuIHRoaXMuX25vblNwZWNpZmljQ2hhbmdlU2V0RXJyb3IoY2hhbmdlU2V0LCB7XG4gICAgICAgIHR5cGU6ICdjaGFuZ2Utc2V0JyxcbiAgICAgICAgY2hhbmdlU2V0TmFtZTogY2hhbmdlU2V0LkNoYW5nZVNldE5hbWUgPz8gJycsXG4gICAgICAgIGNoYW5nZVNldFN0YXR1czogY2hhbmdlU2V0LlN0YXR1cyA/PyAnJyxcbiAgICAgICAgc3RhdHVzUmVhc29uOiBjaGFuZ2VTZXQuU3RhdHVzUmVhc29uID8/ICcnLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgY29uc3QgbmVzdGVkQ3MgPSBhd2FpdCB0aGlzLmNmbi5kZXNjcmliZUNoYW5nZVNldCh7XG4gICAgICBDaGFuZ2VTZXROYW1lOiBuZXN0ZWQuY2hhbmdlU2V0TmFtZSxcbiAgICAgIFN0YWNrTmFtZTogbmVzdGVkLnN0YWNrTmFtZSxcbiAgICB9KTtcblxuICAgIGNvbnN0IG5lc3RlZERpYWcgPSBuZXcgQ2xvdWRGb3JtYXRpb25TdGFja0RpYWdub3Nlcih0aGlzLnByb3BzKTtcbiAgICBuZXN0ZWREaWFnLnBhcmVudFN0YWNrTG9naWNhbElkcyA9IFsuLi50aGlzLnBhcmVudFN0YWNrTG9naWNhbElkcywgbmVzdGVkLmxvZ2ljYWxJZF07XG4gICAgcmV0dXJuIG5lc3RlZERpYWcuX2RpYWdub3NlQ2hhbmdlU2V0RmFpbHVyZShuZXN0ZWRDcyk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIF9maW5kRmFpbGVkTmVzdGVkU3RhY2soY2hhbmdlU2V0OiBDaGFuZ2VTZXRTdW1tYXJ5KTogUHJvbWlzZTx7XG4gICAgc3RhY2tOYW1lOiBzdHJpbmc7XG4gICAgY2hhbmdlU2V0TmFtZTogc3RyaW5nO1xuICAgIGxvZ2ljYWxJZDogc3RyaW5nO1xuICB9IHwgdW5kZWZpbmVkPiB7XG4gICAgLy8gVGhlIHN0YXR1cyByZWFzb24gb25seSBpbmNsdWRlcyB0aGUgY2hhbmdlIHNldCBJRCwgYnV0IHdlIGFsc28gbmVlZCB0aGUgc3RhY2sgbmFtZS4gVGhlIHdheSB0byBnZXQgdGhpcyBpc1xuICAgIC8vIGRlc2NyaWJlIHRoZSBjdXJyZW50IGNoYW5nZSBzZXQsIHRoZW4gZnJvbSB0aGUgQ2hhbmdlcyBmaW5kIHRoZSBzdGFjayB3aG9zZSBDaGFuZ2VTZXRJZCBpcyBtZW50aW9uZWQgaW4gdGhlXG4gICAgLy8gc3RhdHVzIHJlYXNvbiwgdGhlbiBsb29rIHVwIHRoYXQgY2hhbmdlIHNldCBhbmQgcmVjdXJzZSBpbnRvIGEgcmVndWxhciBjaGFuZ2Ugc2V0IGRpYWdub3Npcy5cbiAgICBsZXQgbmV4dFRva2VuID0gdW5kZWZpbmVkO1xuICAgIGRvIHtcbiAgICAgIC8vIENoYW5nZXMgaW4gdGhpcyByZXNwb25zZSBtaWdodCBiZSBwYWdpbmF0ZWRcbiAgICAgIGNvbnN0IHJlc3AgPSBhd2FpdCB0aGlzLmNmbi5kZXNjcmliZUNoYW5nZVNldCh7XG4gICAgICAgIFN0YWNrTmFtZTogY2hhbmdlU2V0LlN0YWNrTmFtZSxcbiAgICAgICAgQ2hhbmdlU2V0TmFtZTogY2hhbmdlU2V0LkNoYW5nZVNldE5hbWUsXG4gICAgICAgIC4uLm5leHRUb2tlbiA/IHsgTmV4dFRva2VuOiBuZXh0VG9rZW4gfSA6IHt9LFxuICAgICAgfSk7XG5cbiAgICAgIGZvciAoY29uc3QgY2hhbmdlIG9mIHJlc3AuQ2hhbmdlcyA/PyBbXSkge1xuICAgICAgICBpZiAoY2hhbmdlLlR5cGUgPT09IENoYW5nZVR5cGUuUmVzb3VyY2UgJiYgY2hhbmdlLlJlc291cmNlQ2hhbmdlPy5SZXNvdXJjZVR5cGUgPT09ICdBV1M6OkNsb3VkRm9ybWF0aW9uOjpTdGFjaycgJiYgY2hhbmdlLlJlc291cmNlQ2hhbmdlPy5DaGFuZ2VTZXRJZCAmJiBjaGFuZ2VTZXQuU3RhdHVzUmVhc29uPy5pbmNsdWRlcyhjaGFuZ2UuUmVzb3VyY2VDaGFuZ2U/LkNoYW5nZVNldElkKSkge1xuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBjaGFuZ2VTZXROYW1lOiBjaGFuZ2UuUmVzb3VyY2VDaGFuZ2UuQ2hhbmdlU2V0SWQsXG4gICAgICAgICAgICBzdGFja05hbWU6IGNoYW5nZS5SZXNvdXJjZUNoYW5nZS5QaHlzaWNhbFJlc291cmNlSWQgPz8gJycsXG4gICAgICAgICAgICBsb2dpY2FsSWQ6IGNoYW5nZS5SZXNvdXJjZUNoYW5nZS5Mb2dpY2FsUmVzb3VyY2VJZCA/PyAnJyxcbiAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIG5leHRUb2tlbiA9IHJlc3AuTmV4dFRva2VuO1xuICAgIH0gd2hpbGUgKG5leHRUb2tlbik7XG5cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIFRyeSB0byBwYXJzZSBmYWlsZWQgYXV0by1pbXBvcnRzIG91dCBmcm9tIGEgY2hhbmdlIHNldCBzdGF0dXNcbiAgICpcbiAgICogVGhlIHBhdHRlcm4gbG9va3MgbGlrZSB0aGlzOlxuICAgKlxuICAgKiBgYGBcbiAgICogQ2xvdWRGb3JtYXRpb24gaXMgYXR0ZW1wdGluZyB0byBpbXBvcnQgc29tZSByZXNvdXJjZXMgYmVjYXVzZSB0aGV5IGFscmVhZHkgZXhpc3QgaW4geW91ciBhY2NvdW50LiBUaGUgcmVzb3VyY2VzIG11c3QgaGF2ZSB0aGUgRGVsZXRpb25Qb2xpY3kgYXR0cmlidXRlIHNldCB0byAnUmV0YWluJyBvciAnUmV0YWluRXhjZXB0T25DcmVhdGUnIGluIHRoZSB0ZW1wbGF0ZSBmb3Igc3VjY2Vzc2Z1bCBpbXBvcnQuIFRoZSBhZmZlY3RlZCByZXNvdXJjZXMgYXJlIFNvbWVCdWNrZXRENUI3MDcwNCAoe0J1Y2tldE5hbWU9em9tYWFyZWVuYnVja2V0fSlcbiAgICogYGBgXG4gICAqXG4gICAqIEZvbGxvd2VkIGJ5XG4gICAqXG4gICAqIGBgYFxuICAgKiBMb2dpY2FsSUQgKHtQcm9wPVZhbHVlLFByb3A9VmFsdWV9KSwgTG9naWNhbElEICh7UHJvcD1WYWx1ZX0pLCAuLi5cbiAgICogYGBgXG4gICAqL1xuICBwcml2YXRlIF90cnlEZXRlY3RGYWlsZWRBdXRvSW1wb3J0KGNoYW5nZVNldDogQ2hhbmdlU2V0U3VtbWFyeSk6IFJlc291cmNlRXJyb3JbXSB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgbWVzc2FnZSA9IGNoYW5nZVNldC5TdGF0dXNSZWFzb247XG4gICAgLy8gT25seSBlbmhhbmNlIHRoZSBzcGVjaWZpYyBDRk4gZXJyb3IgYWJvdXQgaW1wb3J0aW5nIGV4aXN0aW5nIHJlc291cmNlc1xuICAgIGlmICghbWVzc2FnZT8uaW5jbHVkZXMoJ0Nsb3VkRm9ybWF0aW9uIGlzIGF0dGVtcHRpbmcgdG8gaW1wb3J0IHNvbWUgcmVzb3VyY2VzIGJlY2F1c2UgdGhleSBhbHJlYWR5IGV4aXN0IGluIHlvdXIgYWNjb3VudCcpKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGNvbnN0IG1hcmtlciA9ICdUaGUgYWZmZWN0ZWQgcmVzb3VyY2VzIGFyZSAnO1xuICAgIGNvbnN0IG1hcmtlckluZGV4ID0gbWVzc2FnZS5pbmRleE9mKG1hcmtlcik7XG4gICAgaWYgKG1hcmtlckluZGV4ID09PSAtMSkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBjb25zdCByZXQ6IFJlc291cmNlRXJyb3JbXSA9IFtdO1xuICAgIGxldCByZW1haW5pbmcgPSBtZXNzYWdlLnNsaWNlKG1hcmtlckluZGV4ICsgbWFya2VyLmxlbmd0aCk7XG4gICAgd2hpbGUgKHJlbWFpbmluZykge1xuICAgICAgY29uc3QgZW5kSXggPSByZW1haW5pbmcuaW5kZXhPZignKSwgJyk7XG4gICAgICBjb25zdCB0aGlzUmVzb3VyY2UgPSBlbmRJeCA+IC0xID8gcmVtYWluaW5nLnNsaWNlKDAsIGVuZEl4ICsgMSkgOiByZW1haW5pbmc7XG4gICAgICByZW1haW5pbmcgPSByZW1haW5pbmcuc2xpY2UodGhpc1Jlc291cmNlLmxlbmd0aCArIDIpO1xuXG4gICAgICAvLyB0aGlzUmVzb3VyY2UgPSBcIkxvZ2ljYWxJZCAoe1Byb3A9VmFsdWUsIFByb3A9VmFsdWV9KVwiXG4gICAgICBjb25zdCBvcGVuUGFyZW4gPSB0aGlzUmVzb3VyY2UuaW5kZXhPZignKCcpO1xuICAgICAgY29uc3QgbG9naWNhbElkID0gb3BlblBhcmVuID4gLTEgPyB0aGlzUmVzb3VyY2Uuc2xpY2UoMCwgb3BlblBhcmVuKS50cmltKCkgOiB1bmRlZmluZWQ7XG5cbiAgICAgIHJldC5wdXNoKHtcbiAgICAgICAgbWVzc2FnZTogYEF1dG9tYXRpYyBpbXBvcnQgb2YgZXhpc3RpbmcgcmVzb3VyY2UgJHt0aGlzUmVzb3VyY2V9IG5lZWRzIGEgRGVsZXRpb25Qb2xpY3kgb2YgXFwnUmV0YWluXFwnIG9yIFxcJ1JldGFpbkV4Y2VwdE9uQ3JlYXRlXFwnLiBTZXQgdGhlIHJlbW92YWwgcG9saWN5IHRvIFxcJ1JlbW92YWxQb2xpY3kuUkVUQUlOXFwnIG9yIFxcJ1JlbW92YWxQb2xpY3kuUkVUQUlOX09OX1VQREFURV9PUl9ERUxFVEVcXCcgKFNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vY2RrL3YyL2d1aWRlL3Jlc291cmNlcy5odG1sI3Jlc291cmNlcy1yZW1vdmFsKWAsXG4gICAgICAgIHBhcmVudFN0YWNrTG9naWNhbElkczogdGhpcy5wYXJlbnRTdGFja0xvZ2ljYWxJZHMsXG4gICAgICAgIHN0YWNrQXJuOiBjaGFuZ2VTZXQuU3RhY2tJZCA/PyAnJyxcbiAgICAgICAgZXJyb3JDb2RlOiAnQXV0b21hdGljSW1wb3J0TmVlZHNSZXRhaW4nLFxuICAgICAgICBsb2dpY2FsSWQsXG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHJldDtcbiAgfVxufVxuXG4vKipcbiAqIFJldHVybiB0cnVlIGlmIHRoZSBnaXZlbiBjaGFuZ2Ugc2V0IGhhcyBubyBjaGFuZ2VzXG4gKlxuICogVGhpcyBtdXN0IGJlIGRldGVybWluZWQgZnJvbSB0aGUgc3RhdHVzLCBub3QgdGhlICdDaGFuZ2VzJyBhcnJheSBvbiB0aGVcbiAqIG9iamVjdDsgdGhlIGxhdHRlciBjYW4gYmUgZW1wdHkgYmVjYXVzZSBubyByZXNvdXJjZXMgd2VyZSBjaGFuZ2VkLCBidXQgaWZcbiAqIHRoZXJlIGFyZSBjaGFuZ2VzIHRvIE91dHB1dHMsIHRoZSBjaGFuZ2Ugc2V0IGNhbiBzdGlsbCBiZSBleGVjdXRlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNoYW5nZVNldEhhc05vQ2hhbmdlcyhkZXNjcmlwdGlvbjogQ2hhbmdlU2V0U3VtbWFyeSkge1xuICBjb25zdCBub0NoYW5nZUVycm9yUHJlZml4ZXMgPSBbXG4gICAgLy8gRXJyb3IgbWVzc2FnZSBmb3IgYSByZWd1bGFyIHRlbXBsYXRlXG4gICAgXCJUaGUgc3VibWl0dGVkIGluZm9ybWF0aW9uIGRpZG4ndCBjb250YWluIGNoYW5nZXMuXCIsXG4gICAgLy8gRXJyb3IgbWVzc2FnZSB3aGVuIGEgVHJhbnNmb3JtIGlzIGludm9sdmVkIChzZWUgIzEwNjUwKVxuICAgICdObyB1cGRhdGVzIGFyZSB0byBiZSBwZXJmb3JtZWQuJyxcbiAgXTtcblxuICByZXR1cm4gKFxuICAgIGRlc2NyaXB0aW9uLlN0YXR1cyA9PT0gJ0ZBSUxFRCcgJiYgbm9DaGFuZ2VFcnJvclByZWZpeGVzLnNvbWUoKHApID0+IChkZXNjcmlwdGlvbi5TdGF0dXNSZWFzb24gPz8gJycpLnN0YXJ0c1dpdGgocCkpXG4gICk7XG59XG5cbmZ1bmN0aW9uIHJlc291cmNlRXJyb3JGcm9tRWFybHlWYWxpZGF0aW9uRXJyb3Ioc3RhY2tJZDogc3RyaW5nLCBwYXJlbnRTdGFja0xvZ2ljYWxJZHM6IHN0cmluZ1tdLCBldjogQ2hhbmdlU2V0UmVzb3VyY2VFcnJvcik6IFJlc291cmNlRXJyb3Ige1xuICByZXR1cm4ge1xuICAgIGxvZ2ljYWxJZDogZXYubG9naWNhbElkLFxuICAgIHBoeXNpY2FsSWQ6IGV2LnBoeXNpY2FsSWQsXG4gICAgcmVzb3VyY2VUeXBlOiBldi5yZXNvdXJjZVR5cGUsXG4gICAgbWVzc2FnZTogYCR7ZXYubWVzc2FnZX0gKGF0ICR7ZXYuZG9jdW1lbnRQYXRofSlgLFxuICAgIGVycm9yQ29kZTogYCR7ZXYudmFsaWRhdGlvbk5hbWV9XyR7ZXYuZXZlbnRUeXBlfWAsXG4gICAgcGFyZW50U3RhY2tMb2dpY2FsSWRzLFxuICAgIHN0YWNrQXJuOiBzdGFja0lkLFxuICB9O1xufVxuIl19
@@ -0,0 +1,13 @@
1
+ import { TreeText } from './tree';
2
+ export declare class TreeBuilder {
3
+ private readonly rootText;
4
+ private readonly root;
5
+ constructor(rootText: string);
6
+ nodeText(constructPath: string): TreeText;
7
+ render(): string;
8
+ toString(): string;
9
+ private obtainNode;
10
+ }
11
+ export declare function sideBySide(left: string[], sep: string, right: string[]): string[];
12
+ export declare function wrapText(n: number, text: string): string[];
13
+ //# sourceMappingURL=tree-builder.d.ts.map
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TreeBuilder = void 0;
4
+ exports.sideBySide = sideBySide;
5
+ exports.wrapText = wrapText;
6
+ const tree_1 = require("./tree");
7
+ class TreeBuilder {
8
+ rootText;
9
+ root;
10
+ constructor(rootText) {
11
+ this.rootText = rootText;
12
+ this.root = {
13
+ tree: new tree_1.Tree(new tree_1.TreeText([rootText])),
14
+ children: {},
15
+ };
16
+ }
17
+ nodeText(constructPath) {
18
+ return this.obtainNode(constructPath).text;
19
+ }
20
+ render() {
21
+ const out = this.root.tree.render();
22
+ if (this.rootText) {
23
+ return out;
24
+ }
25
+ // RootText is empty, hide the entire node (slice off the initial newline)
26
+ return out.slice(1);
27
+ }
28
+ toString() {
29
+ return this.render();
30
+ }
31
+ obtainNode(constructPath) {
32
+ const parts = constructPath.split('/');
33
+ let cur = this.root;
34
+ while (true) {
35
+ const next = parts.shift();
36
+ if (next === undefined) {
37
+ return cur.tree;
38
+ }
39
+ const child = cur.children[next];
40
+ if (child) {
41
+ cur = child;
42
+ }
43
+ else {
44
+ const tree = new tree_1.Tree(new tree_1.TreeText([next]));
45
+ cur.tree.addChild(tree);
46
+ cur = cur.children[next] = {
47
+ tree,
48
+ children: {},
49
+ };
50
+ }
51
+ }
52
+ }
53
+ }
54
+ exports.TreeBuilder = TreeBuilder;
55
+ function sideBySide(left, sep, right) {
56
+ const width = left.map(x => x.length).reduce((acc, n) => Math.max(acc, n), 0);
57
+ const ret = [];
58
+ for (let i = 0; i < left.length || i < right.length; i++) {
59
+ const l = i < left.length ? left[i] : ' '.repeat(width);
60
+ const r = i < right.length ? right[i] : '';
61
+ ret.push(`${l}${sep}${r}`);
62
+ }
63
+ return ret;
64
+ }
65
+ function wrapText(n, text) {
66
+ const breakers = [' ', '\n'];
67
+ const ret = [];
68
+ let lineStart = 0;
69
+ while (lineStart < text.length) {
70
+ let lineEnd = lineStart + n;
71
+ while (lineEnd > lineStart && lineEnd < text.length && !breakers.includes(text[lineEnd])) {
72
+ lineEnd -= 1;
73
+ }
74
+ if (lineEnd === lineStart) {
75
+ // Could not find a space in this line. Seek forward to the first space to get the smallest line overflow
76
+ lineEnd = lineStart + n;
77
+ while (lineEnd < text.length && !breakers.includes(text[lineEnd])) {
78
+ lineEnd += 1;
79
+ }
80
+ }
81
+ ret.push(text.slice(lineStart, lineEnd));
82
+ lineStart = lineEnd + 1;
83
+ }
84
+ return ret;
85
+ }
86
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJlZS1idWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsidHJlZS1idWlsZGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQTBEQSxnQ0FVQztBQUVELDRCQXNCQztBQTVGRCxpQ0FBd0M7QUFFeEMsTUFBYSxXQUFXO0lBR087SUFGWixJQUFJLENBQWtCO0lBRXZDLFlBQTZCLFFBQWdCO1FBQWhCLGFBQVEsR0FBUixRQUFRLENBQVE7UUFDM0MsSUFBSSxDQUFDLElBQUksR0FBRztZQUNWLElBQUksRUFBRSxJQUFJLFdBQUksQ0FBQyxJQUFJLGVBQVEsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7WUFDeEMsUUFBUSxFQUFFLEVBQUU7U0FDYixDQUFDO0lBQ0osQ0FBQztJQUVNLFFBQVEsQ0FBQyxhQUFxQjtRQUNuQyxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLENBQUMsSUFBSSxDQUFDO0lBQzdDLENBQUM7SUFFTSxNQUFNO1FBQ1gsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDcEMsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7WUFDbEIsT0FBTyxHQUFHLENBQUM7UUFDYixDQUFDO1FBQ0QsMEVBQTBFO1FBQzFFLE9BQU8sR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN0QixDQUFDO0lBRU0sUUFBUTtRQUNiLE9BQU8sSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQ3ZCLENBQUM7SUFFTyxVQUFVLENBQUMsYUFBcUI7UUFDdEMsTUFBTSxLQUFLLEdBQUcsYUFBYSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN2QyxJQUFJLEdBQUcsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO1FBQ3BCLE9BQU8sSUFBSSxFQUFFLENBQUM7WUFDWixNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsS0FBSyxF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QUFDO2dCQUNsRSxPQUFPLElBQUksQ0FBQyxDQUFDO1lBQ2YsQ0FBQztRQUNILENBQUM7UUFFRCxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7UUFDekMsU0FBUyxHQUFHLE9BQU8sR0FBRyxDQUFDLENBQUM7SUFDMUIsQ0FBQztJQUNELE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFRyZWUsIFRyZWVUZXh0IH0gZnJvbSAnLi90cmVlJztcblxuZXhwb3J0IGNsYXNzIFRyZWVCdWlsZGVyIHtcbiAgcHJpdmF0ZSByZWFkb25seSByb290OiBUcmVlQnVpbGRlck5vZGU7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSByb290VGV4dDogc3RyaW5nKSB7XG4gICAgdGhpcy5yb290ID0ge1xuICAgICAgdHJlZTogbmV3IFRyZWUobmV3IFRyZWVUZXh0KFtyb290VGV4dF0pKSxcbiAgICAgIGNoaWxkcmVuOiB7fSxcbiAgICB9O1xuICB9XG5cbiAgcHVibGljIG5vZGVUZXh0KGNvbnN0cnVjdFBhdGg6IHN0cmluZyk6IFRyZWVUZXh0IHtcbiAgICByZXR1cm4gdGhpcy5vYnRhaW5Ob2RlKGNvbnN0cnVjdFBhdGgpLnRleHQ7XG4gIH1cblxuICBwdWJsaWMgcmVuZGVyKCkge1xuICAgIGNvbnN0IG91dCA9IHRoaXMucm9vdC50cmVlLnJlbmRlcigpO1xuICAgIGlmICh0aGlzLnJvb3RUZXh0KSB7XG4gICAgICByZXR1cm4gb3V0O1xuICAgIH1cbiAgICAvLyBSb290VGV4dCBpcyBlbXB0eSwgaGlkZSB0aGUgZW50aXJlIG5vZGUgKHNsaWNlIG9mZiB0aGUgaW5pdGlhbCBuZXdsaW5lKVxuICAgIHJldHVybiBvdXQuc2xpY2UoMSk7XG4gIH1cblxuICBwdWJsaWMgdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIHRoaXMucmVuZGVyKCk7XG4gIH1cblxuICBwcml2YXRlIG9idGFpbk5vZGUoY29uc3RydWN0UGF0aDogc3RyaW5nKTogVHJlZSB7XG4gICAgY29uc3QgcGFydHMgPSBjb25zdHJ1Y3RQYXRoLnNwbGl0KCcvJyk7XG4gICAgbGV0IGN1ciA9IHRoaXMucm9vdDtcbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgY29uc3QgbmV4dCA9IHBhcnRzLnNoaWZ0KCk7XG4gICAgICBpZiAobmV4dCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBjdXIudHJlZTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgY2hpbGQgPSBjdXIuY2hpbGRyZW5bbmV4dF07XG4gICAgICBpZiAoY2hpbGQpIHtcbiAgICAgICAgY3VyID0gY2hpbGQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCB0cmVlID0gbmV3IFRyZWUobmV3IFRyZWVUZXh0KFtuZXh0XSkpO1xuICAgICAgICBjdXIudHJlZS5hZGRDaGlsZCh0cmVlKTtcbiAgICAgICAgY3VyID0gY3VyLmNoaWxkcmVuW25leHRdID0ge1xuICAgICAgICAgIHRyZWUsXG4gICAgICAgICAgY2hpbGRyZW46IHt9LFxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5pbnRlcmZhY2UgVHJlZUJ1aWxkZXJOb2RlIHtcbiAgdHJlZTogVHJlZTtcbiAgY2hpbGRyZW46IFJlY29yZDxzdHJpbmcsIFRyZWVCdWlsZGVyTm9kZT47XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzaWRlQnlTaWRlKGxlZnQ6IHN0cmluZ1tdLCBzZXA6IHN0cmluZywgcmlnaHQ6IHN0cmluZ1tdKSB7XG4gIGNvbnN0IHdpZHRoID0gbGVmdC5tYXAoeCA9PiB4Lmxlbmd0aCkucmVkdWNlKChhY2MsIG4pID0+IE1hdGgubWF4KGFjYywgbiksIDApO1xuXG4gIGNvbnN0IHJldDogc3RyaW5nW10gPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZWZ0Lmxlbmd0aCB8fCBpIDwgcmlnaHQubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBsID0gaSA8IGxlZnQubGVuZ3RoID8gbGVmdFtpXSA6ICcgJy5yZXBlYXQod2lkdGgpO1xuICAgIGNvbnN0IHIgPSBpIDwgcmlnaHQubGVuZ3RoID8gcmlnaHRbaV0gOiAnJztcbiAgICByZXQucHVzaChgJHtsfSR7c2VwfSR7cn1gKTtcbiAgfVxuICByZXR1cm4gcmV0O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gd3JhcFRleHQobjogbnVtYmVyLCB0ZXh0OiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gIGNvbnN0IGJyZWFrZXJzID0gWycgJywgJ1xcbiddO1xuXG4gIGNvbnN0IHJldDogc3RyaW5nW10gPSBbXTtcbiAgbGV0IGxpbmVTdGFydCA9IDA7XG4gIHdoaWxlIChsaW5lU3RhcnQgPCB0ZXh0Lmxlbmd0aCkge1xuICAgIGxldCBsaW5lRW5kID0gbGluZVN0YXJ0ICsgbjtcbiAgICB3aGlsZSAobGluZUVuZCA+IGxpbmVTdGFydCAmJiBsaW5lRW5kIDwgdGV4dC5sZW5ndGggJiYgIWJyZWFrZXJzLmluY2x1ZGVzKHRleHRbbGluZUVuZF0pKSB7XG4gICAgICBsaW5lRW5kIC09IDE7XG4gICAgfVxuICAgIGlmIChsaW5lRW5kID09PSBsaW5lU3RhcnQpIHtcbiAgICAgIC8vIENvdWxkIG5vdCBmaW5kIGEgc3BhY2UgaW4gdGhpcyBsaW5lLiBTZWVrIGZvcndhcmQgdG8gdGhlIGZpcnN0IHNwYWNlIHRvIGdldCB0aGUgc21hbGxlc3QgbGluZSBvdmVyZmxvd1xuICAgICAgbGluZUVuZCA9IGxpbmVTdGFydCArIG47XG4gICAgICB3aGlsZSAobGluZUVuZCA8IHRleHQubGVuZ3RoICYmICFicmVha2Vycy5pbmNsdWRlcyh0ZXh0W2xpbmVFbmRdKSkge1xuICAgICAgICBsaW5lRW5kICs9IDE7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0LnB1c2godGV4dC5zbGljZShsaW5lU3RhcnQsIGxpbmVFbmQpKTtcbiAgICBsaW5lU3RhcnQgPSBsaW5lRW5kICsgMTtcbiAgfVxuICByZXR1cm4gcmV0O1xufVxuIl19
@@ -0,0 +1,19 @@
1
+ export declare class Tree {
2
+ text: TreeText;
3
+ private readonly children;
4
+ constructor(text: TreeText, children?: Tree[]);
5
+ addChild(tree: Tree): void;
6
+ height(): number;
7
+ render(): string;
8
+ toString(): string;
9
+ private _render;
10
+ }
11
+ export declare class TreeText {
12
+ header: string[];
13
+ body: string[];
14
+ footer: string[];
15
+ constructor(header?: string[], body?: string[], footer?: string[]);
16
+ get lines(): string[];
17
+ lineCount(): number;
18
+ }
19
+ //# sourceMappingURL=tree.d.ts.map
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TreeText = exports.Tree = void 0;
4
+ class Tree {
5
+ text;
6
+ children;
7
+ constructor(text, children = []) {
8
+ this.text = text;
9
+ this.children = [...children];
10
+ }
11
+ addChild(tree) {
12
+ this.children.push(tree);
13
+ }
14
+ height() {
15
+ return this.text.lineCount() + sum(this.children.map(c => c.height()));
16
+ }
17
+ render() {
18
+ return this._render().join('\n');
19
+ }
20
+ toString() {
21
+ return this.render();
22
+ }
23
+ _render() {
24
+ const ret = [];
25
+ ret.push(...this.text.lines);
26
+ for (let i = 0; i < this.children.length; i++) {
27
+ const isLastChild = i === this.children.length - 1;
28
+ let bullet;
29
+ let hanger;
30
+ if (isLastChild) {
31
+ bullet = ' └─ ';
32
+ hanger = ' ';
33
+ }
34
+ else {
35
+ bullet = ' ├─ ';
36
+ hanger = ' │ ';
37
+ }
38
+ const childRender = this.children[i]._render();
39
+ for (let j = 0; j < childRender.length; j++) {
40
+ const isFirstLine = j === 0;
41
+ ret.push((isFirstLine ? bullet : hanger) + childRender[j]);
42
+ }
43
+ }
44
+ return ret;
45
+ }
46
+ }
47
+ exports.Tree = Tree;
48
+ class TreeText {
49
+ header;
50
+ body;
51
+ footer;
52
+ constructor(header = [], body = [], footer = []) {
53
+ this.header = header;
54
+ this.body = body;
55
+ this.footer = footer;
56
+ }
57
+ get lines() {
58
+ return [...this.header, ...this.body, ...this.footer];
59
+ }
60
+ lineCount() {
61
+ return this.header.length + this.body.length + this.footer.length;
62
+ }
63
+ }
64
+ exports.TreeText = TreeText;
65
+ function sum(xs) {
66
+ let ret = 0;
67
+ for (const x of xs) {
68
+ ret += x;
69
+ }
70
+ return ret;
71
+ }
72
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJlZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInRyZWUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsTUFBYSxJQUFJO0lBQ1IsSUFBSSxDQUFXO0lBQ0wsUUFBUSxDQUFTO0lBRWxDLFlBQVksSUFBYyxFQUFFLFdBQW1CLEVBQUU7UUFDL0MsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFDLFFBQVEsR0FBRyxDQUFDLEdBQUcsUUFBUSxDQUFDLENBQUM7SUFDaEMsQ0FBQztJQUVNLFFBQVEsQ0FBQyxJQUFVO1FBQ3hCLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzNCLENBQUM7SUFFTSxNQUFNO1FBQ1gsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDekUsQ0FBQztJQUVNLE1BQU07UUFDWCxPQUFPLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUVNLFFBQVE7UUFDYixPQUFPLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUN2QixDQUFDO0lBRU8sT0FBTztRQUNiLE1BQU0sR0FBRyxHQUFhLEVBQUUsQ0FBQztRQUN6QixHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM3QixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUM5QyxNQUFNLFdBQVcsR0FBRyxDQUFDLEtBQUssSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO1lBRW5ELElBQUksTUFBTSxDQUFDO1lBQ1gsSUFBSSxNQUFNLENBQUM7WUFDWCxJQUFJLFdBQVcsRUFBRSxDQUFDO2dCQUNoQixNQUFNLEdBQUcsTUFBTSxDQUFDO2dCQUNoQixNQUFNLEdBQUcsTUFBTSxDQUFDO1lBQ2xCLENBQUM7aUJBQU0sQ0FBQztnQkFDTixNQUFNLEdBQUcsTUFBTSxDQUFDO2dCQUNoQixNQUFNLEdBQUcsTUFBTSxDQUFDO1lBQ2xCLENBQUM7WUFFRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQy9DLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxXQUFXLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7Z0JBQzVDLE1BQU0sV0FBVyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBRTVCLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDN0QsQ0FBQztRQUNILENBQUM7UUFDRCxPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7Q0FDRjtBQWxERCxvQkFrREM7QUFFRCxNQUFhLFFBQVE7SUFFVjtJQUNBO0lBQ0E7SUFIVCxZQUNTLFNBQW1CLEVBQUUsRUFDckIsT0FBaUIsRUFBRSxFQUNuQixTQUFtQixFQUFFO1FBRnJCLFdBQU0sR0FBTixNQUFNLENBQWU7UUFDckIsU0FBSSxHQUFKLElBQUksQ0FBZTtRQUNuQixXQUFNLEdBQU4sTUFBTSxDQUFlO0lBRTlCLENBQUM7SUFFRCxJQUFXLEtBQUs7UUFDZCxPQUFPLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN4RCxDQUFDO0lBRU0sU0FBUztRQUNkLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUM7SUFDcEUsQ0FBQztDQUNGO0FBZkQsNEJBZUM7QUFFRCxTQUFTLEdBQUcsQ0FBQyxFQUFvQjtJQUMvQixJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUM7SUFDWixLQUFLLE1BQU0sQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDO1FBQ25CLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDWCxDQUFDO0lBQ0QsT0FBTyxHQUFHLENBQUM7QUFDYixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IGNsYXNzIFRyZWUge1xuICBwdWJsaWMgdGV4dDogVHJlZVRleHQ7XG4gIHByaXZhdGUgcmVhZG9ubHkgY2hpbGRyZW46IFRyZWVbXTtcblxuICBjb25zdHJ1Y3Rvcih0ZXh0OiBUcmVlVGV4dCwgY2hpbGRyZW46IFRyZWVbXSA9IFtdKSB7XG4gICAgdGhpcy50ZXh0ID0gdGV4dDtcbiAgICB0aGlzLmNoaWxkcmVuID0gWy4uLmNoaWxkcmVuXTtcbiAgfVxuXG4gIHB1YmxpYyBhZGRDaGlsZCh0cmVlOiBUcmVlKSB7XG4gICAgdGhpcy5jaGlsZHJlbi5wdXNoKHRyZWUpO1xuICB9XG5cbiAgcHVibGljIGhlaWdodCgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLnRleHQubGluZUNvdW50KCkgKyBzdW0odGhpcy5jaGlsZHJlbi5tYXAoYyA9PiBjLmhlaWdodCgpKSk7XG4gIH1cblxuICBwdWJsaWMgcmVuZGVyKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX3JlbmRlcigpLmpvaW4oJ1xcbicpO1xuICB9XG5cbiAgcHVibGljIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiB0aGlzLnJlbmRlcigpO1xuICB9XG5cbiAgcHJpdmF0ZSBfcmVuZGVyKCk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCByZXQ6IHN0cmluZ1tdID0gW107XG4gICAgcmV0LnB1c2goLi4udGhpcy50ZXh0LmxpbmVzKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGlzTGFzdENoaWxkID0gaSA9PT0gdGhpcy5jaGlsZHJlbi5sZW5ndGggLSAxO1xuXG4gICAgICBsZXQgYnVsbGV0O1xuICAgICAgbGV0IGhhbmdlcjtcbiAgICAgIGlmIChpc0xhc3RDaGlsZCkge1xuICAgICAgICBidWxsZXQgPSAnIOKUlOKUgCAnO1xuICAgICAgICBoYW5nZXIgPSAnICAgICc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBidWxsZXQgPSAnIOKUnOKUgCAnO1xuICAgICAgICBoYW5nZXIgPSAnIOKUgiAgJztcbiAgICAgIH1cblxuICAgICAgY29uc3QgY2hpbGRSZW5kZXIgPSB0aGlzLmNoaWxkcmVuW2ldLl9yZW5kZXIoKTtcbiAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgY2hpbGRSZW5kZXIubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgY29uc3QgaXNGaXJzdExpbmUgPSBqID09PSAwO1xuXG4gICAgICAgIHJldC5wdXNoKChpc0ZpcnN0TGluZSA/IGJ1bGxldCA6IGhhbmdlcikgKyBjaGlsZFJlbmRlcltqXSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXQ7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFRyZWVUZXh0IHtcbiAgY29uc3RydWN0b3IoXG4gICAgcHVibGljIGhlYWRlcjogc3RyaW5nW10gPSBbXSxcbiAgICBwdWJsaWMgYm9keTogc3RyaW5nW10gPSBbXSxcbiAgICBwdWJsaWMgZm9vdGVyOiBzdHJpbmdbXSA9IFtdLFxuICApIHtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgbGluZXMoKSB7XG4gICAgcmV0dXJuIFsuLi50aGlzLmhlYWRlciwgLi4udGhpcy5ib2R5LCAuLi50aGlzLmZvb3Rlcl07XG4gIH1cblxuICBwdWJsaWMgbGluZUNvdW50KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuaGVhZGVyLmxlbmd0aCArIHRoaXMuYm9keS5sZW5ndGggKyB0aGlzLmZvb3Rlci5sZW5ndGg7XG4gIH1cbn1cblxuZnVuY3Rpb24gc3VtKHhzOiBJdGVyYWJsZTxudW1iZXI+KTogbnVtYmVyIHtcbiAgbGV0IHJldCA9IDA7XG4gIGZvciAoY29uc3QgeCBvZiB4cykge1xuICAgIHJldCArPSB4O1xuICB9XG4gIHJldHVybiByZXQ7XG59XG4iXX0=