@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.
- package/build-info.json +2 -2
- package/db.json.gz +0 -0
- package/lib/actions/deploy/index.d.ts +15 -1
- package/lib/actions/deploy/index.js +1 -1
- package/lib/actions/deploy/private/deployment-method.d.ts +5 -9
- package/lib/actions/deploy/private/deployment-method.js +8 -1
- package/lib/actions/diagnose/index.d.ts +89 -0
- package/lib/actions/diagnose/index.js +3 -0
- package/lib/actions/diff/private/helpers.js +12 -15
- package/lib/actions/index.d.ts +2 -0
- package/lib/actions/index.js +3 -1
- package/lib/actions/orphan/index.d.ts +18 -0
- package/lib/actions/orphan/index.js +3 -0
- package/lib/api/aws-auth/sdk.d.ts +2 -1
- package/lib/api/aws-auth/sdk.js +2 -1
- package/lib/api/bootstrap/bootstrap-environment.js +4 -4
- package/lib/api/bootstrap/bootstrap-template.yaml +5 -16
- package/lib/api/bootstrap/deploy-bootstrap.js +9 -1
- package/lib/api/cloud-assembly/stack-selector.d.ts +1 -1
- package/lib/api/cloud-assembly/stack-selector.js +1 -1
- package/lib/api/cloudformation/index.d.ts +1 -0
- package/lib/api/cloudformation/index.js +2 -1
- package/lib/api/cloudformation/logical-id-map.d.ts +24 -0
- package/lib/api/cloudformation/logical-id-map.js +45 -0
- package/lib/api/cloudformation/stack-helpers.d.ts +6 -0
- package/lib/api/cloudformation/stack-helpers.js +12 -1
- package/lib/api/deployments/cfn-api.d.ts +8 -17
- package/lib/api/deployments/cfn-api.js +60 -71
- package/lib/api/deployments/deploy-stack.d.ts +6 -2
- package/lib/api/deployments/deploy-stack.js +43 -61
- package/lib/api/deployments/deployments.d.ts +3 -2
- package/lib/api/deployments/deployments.js +31 -7
- package/lib/api/diagnosing/changeset-error-fetcher.d.ts +51 -0
- package/lib/api/diagnosing/changeset-error-fetcher.js +83 -0
- package/lib/api/diagnosing/diagnosis-formatting.d.ts +13 -0
- package/lib/api/diagnosing/diagnosis-formatting.js +140 -0
- package/lib/api/diagnosing/stack-diagnoser.d.ts +106 -0
- package/lib/api/diagnosing/stack-diagnoser.js +354 -0
- package/lib/api/diagnosing/tree-builder.d.ts +13 -0
- package/lib/api/diagnosing/tree-builder.js +86 -0
- package/lib/api/diagnosing/tree.d.ts +19 -0
- package/lib/api/diagnosing/tree.js +72 -0
- package/lib/api/diff/diff-formatter.js +8 -12
- package/lib/api/drift/drift-formatter.d.ts +0 -1
- package/lib/api/drift/drift-formatter.js +3 -10
- package/lib/api/hotswap/hotswap-deployments.js +14 -2
- package/lib/api/hotswap/hotswap-template-cache.d.ts +19 -0
- package/lib/api/hotswap/hotswap-template-cache.js +96 -0
- package/lib/api/index.d.ts +1 -0
- package/lib/api/index.js +2 -1
- package/lib/api/io/private/messages.d.ts +5 -0
- package/lib/api/io/private/messages.js +23 -1
- package/lib/api/io/toolkit-action.d.ts +1 -1
- package/lib/api/io/toolkit-action.js +1 -1
- package/lib/api/orphan/orphaner.d.ts +75 -0
- package/lib/api/orphan/orphaner.js +246 -0
- package/lib/api/orphan/private/helpers.d.ts +56 -0
- package/lib/api/orphan/private/helpers.js +219 -0
- package/lib/api/orphan/private/index.d.ts +2 -0
- package/lib/api/orphan/private/index.js +18 -0
- package/lib/api/resource-import/importer.d.ts +5 -1
- package/lib/api/resource-import/importer.js +26 -6
- package/lib/api/settings.d.ts +3 -1
- package/lib/api/settings.js +16 -3
- package/lib/api/source-tracing/index.d.ts +2 -0
- package/lib/api/source-tracing/index.js +18 -0
- package/lib/api/source-tracing/private/source-tracing.d.ts +16 -0
- package/lib/api/source-tracing/private/source-tracing.js +8 -0
- package/lib/api/source-tracing/private/stack-source-tracing.d.ts +32 -0
- package/lib/api/source-tracing/private/stack-source-tracing.js +134 -0
- package/lib/api/source-tracing/types.d.ts +9 -0
- package/lib/api/source-tracing/types.js +3 -0
- package/lib/api/stack-events/resource-errors.d.ts +82 -0
- package/lib/api/stack-events/resource-errors.js +129 -0
- package/lib/api/stack-events/stack-activity-monitor.d.ts +2 -29
- package/lib/api/stack-events/stack-activity-monitor.js +6 -95
- package/lib/api/stack-events/stack-event-poller.d.ts +71 -8
- package/lib/api/stack-events/stack-event-poller.js +107 -13
- package/lib/api/stack-events/stack-progress-monitor.d.ts +2 -2
- package/lib/api/stack-events/stack-progress-monitor.js +8 -2
- package/lib/api/work-graph/work-graph.d.ts +4 -0
- package/lib/api/work-graph/work-graph.js +6 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +2 -1
- package/lib/index_bg.wasm +0 -0
- package/lib/toolkit/toolkit.d.ts +17 -1
- package/lib/toolkit/toolkit.js +194 -57
- package/lib/util/arrays.d.ts +1 -0
- package/lib/util/arrays.js +23 -1
- package/lib/util/type-brands.d.ts +1 -1
- package/lib/util/type-brands.js +1 -1
- package/package.json +13 -13
- package/lib/api/deployments/early-validation.d.ts +0 -19
- 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=
|