@jjrawlins/cfn-drift-remediate 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/cli.js ADDED
@@ -0,0 +1,391 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.remediate = remediate;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const cfn_client_1 = require("./lib/cfn-client");
40
+ const eligible_resources_1 = require("./lib/eligible-resources");
41
+ const interactive_1 = require("./lib/interactive");
42
+ const plan_1 = require("./lib/plan");
43
+ const resource_importer_1 = require("./lib/resource-importer");
44
+ const template_transformer_1 = require("./lib/template-transformer");
45
+ const utils_1 = require("./lib/utils");
46
+ const DEFAULT_CAPABILITIES = ['CAPABILITY_IAM', 'CAPABILITY_NAMED_IAM', 'CAPABILITY_AUTO_EXPAND'];
47
+ function packageVersion() {
48
+ try {
49
+ const pkgPath = path.join(__dirname, '..', 'package.json');
50
+ return JSON.parse(fs.readFileSync(pkgPath, 'utf-8')).version;
51
+ }
52
+ catch {
53
+ return 'unknown';
54
+ }
55
+ }
56
+ /**
57
+ * Main remediation function that orchestrates the drift remediation process
58
+ */
59
+ async function remediate(options, spinner) {
60
+ const client = new cfn_client_1.CfnClientWrapper({
61
+ region: options.region,
62
+ profile: options.profile,
63
+ });
64
+ const result = {
65
+ success: false,
66
+ remediatedResources: [],
67
+ skippedResources: [],
68
+ removedResources: [],
69
+ errors: [],
70
+ };
71
+ const log = (message) => {
72
+ if (spinner) {
73
+ spinner.text = message;
74
+ }
75
+ else if (options.verbose) {
76
+ console.log(message);
77
+ }
78
+ };
79
+ try {
80
+ // Step 1: Get stack info and original template
81
+ log('Fetching stack information...');
82
+ const stackInfo = await client.getStackInfo(options.stackName);
83
+ log('Fetching original template...');
84
+ const originalTemplateBody = await client.getTemplate(stackInfo.stackId, true);
85
+ const originalTemplate = (0, template_transformer_1.parseTemplate)(originalTemplateBody);
86
+ if (options.verbose) {
87
+ console.log(`Found stack: ${stackInfo.stackName} (${stackInfo.stackId})`);
88
+ }
89
+ // Steps 2-4: Detect drift and collect decisions (or load from plan)
90
+ let allDriftedResources;
91
+ let decisions;
92
+ if (options.applyPlan) {
93
+ // Apply a previously exported plan — skip drift detection and prompting
94
+ log('Loading remediation plan...');
95
+ const planJson = fs.readFileSync(path.resolve(options.applyPlan), 'utf-8');
96
+ const plan = (0, plan_1.loadPlan)(planJson, options.stackName);
97
+ const loaded = (0, plan_1.planToDecisions)(plan);
98
+ allDriftedResources = loaded.allDriftedResources;
99
+ decisions = loaded.decisions;
100
+ if (spinner)
101
+ spinner.start('Processing...');
102
+ }
103
+ else {
104
+ // Normal flow: detect drift and prompt interactively
105
+ // Step 2: Detect drift
106
+ log('Detecting stack drift...');
107
+ const detectionId = await client.detectDrift(stackInfo.stackId);
108
+ log('Waiting for drift detection to complete...');
109
+ const detectionResult = await client.waitForDriftDetection(detectionId);
110
+ if (detectionResult.status !== 'DETECTION_COMPLETE') {
111
+ result.errors.push(`Drift detection did not complete: ${detectionResult.status}`);
112
+ return result;
113
+ }
114
+ if (detectionResult.driftStatus === 'IN_SYNC') {
115
+ if (spinner)
116
+ spinner.succeed('Stack is in sync - no drift detected');
117
+ result.success = true;
118
+ return result;
119
+ }
120
+ // Step 3: Get drifted resources and separate by type
121
+ log('Analyzing drifted resources...');
122
+ allDriftedResources = await client.getDriftedResources(stackInfo.stackId);
123
+ if (allDriftedResources.length === 0) {
124
+ if (spinner)
125
+ spinner.succeed('No drifted resources found');
126
+ result.success = true;
127
+ return result;
128
+ }
129
+ // Filter to only importable resources
130
+ const modifiedResources = [];
131
+ const deletedResources = [];
132
+ for (const resource of allDriftedResources) {
133
+ if (!(0, eligible_resources_1.isResourceImportable)(resource.resourceType)) {
134
+ result.skippedResources.push(resource.logicalResourceId);
135
+ continue;
136
+ }
137
+ if (resource.stackResourceDriftStatus === 'DELETED') {
138
+ deletedResources.push(resource);
139
+ }
140
+ else {
141
+ modifiedResources.push(resource);
142
+ }
143
+ }
144
+ if (modifiedResources.length === 0 && deletedResources.length === 0) {
145
+ result.errors.push('All drifted resources are not eligible for import');
146
+ return result;
147
+ }
148
+ // Step 4: Interactive decisions
149
+ if (spinner)
150
+ spinner.stop();
151
+ decisions = await (0, interactive_1.promptForDecisions)(modifiedResources, deletedResources, options.yes ?? false);
152
+ if (spinner)
153
+ spinner.start('Processing...');
154
+ // Export plan if requested (exit without executing)
155
+ if (options.exportPlan) {
156
+ const planMetadata = {
157
+ stackName: stackInfo.stackName,
158
+ region: client.region,
159
+ createdAt: new Date().toISOString(),
160
+ toolVersion: packageVersion(),
161
+ driftDetectionId: detectionId,
162
+ };
163
+ const plan = (0, plan_1.buildPlan)(planMetadata, decisions);
164
+ const planPath = path.resolve(options.exportPlan);
165
+ fs.writeFileSync(planPath, (0, plan_1.serializePlan)(plan));
166
+ if (spinner)
167
+ spinner.succeed(`Plan exported to ${planPath}`);
168
+ result.success = true;
169
+ return result;
170
+ }
171
+ }
172
+ // Record skipped resources
173
+ for (const r of decisions.skip) {
174
+ result.skippedResources.push(r.logicalResourceId);
175
+ }
176
+ // If everything was skipped or cancelled, we're done
177
+ if (decisions.autofix.length === 0 && decisions.reimport.length === 0 && decisions.remove.length === 0) {
178
+ if (spinner)
179
+ spinner.succeed('No actions selected');
180
+ result.success = true;
181
+ return result;
182
+ }
183
+ // Step 5: Build resources to import from decisions
184
+ const resourceIdentifiers = await client.getResourceIdentifiers(originalTemplateBody);
185
+ // Autofix resources: use existing buildResourcesToImport
186
+ const { importable: autofixImportable, skipped: autofixSkipped } = (0, resource_importer_1.buildResourcesToImport)(decisions.autofix, resourceIdentifiers);
187
+ for (const s of autofixSkipped) {
188
+ if (!result.skippedResources.includes(s.logicalResourceId)) {
189
+ result.skippedResources.push(s.logicalResourceId);
190
+ }
191
+ }
192
+ // Reimport resources: build from user-provided physical IDs
193
+ const reimportImportable = [];
194
+ for (const { resource, physicalId } of decisions.reimport) {
195
+ const descriptor = (0, resource_importer_1.buildReimportDescriptor)(resource, physicalId, resourceIdentifiers);
196
+ if (descriptor) {
197
+ reimportImportable.push(descriptor);
198
+ }
199
+ else {
200
+ result.errors.push(`Could not determine import identifier for ${resource.logicalResourceId} from "${physicalId}"`);
201
+ result.skippedResources.push(resource.logicalResourceId);
202
+ }
203
+ }
204
+ // Combined importable list
205
+ const allImportable = [...autofixImportable, ...reimportImportable];
206
+ // If nothing to import AND nothing to remove, we're stuck
207
+ if (allImportable.length === 0 && decisions.remove.length === 0) {
208
+ result.errors.push('Could not determine import identifiers for any selected resources');
209
+ return result;
210
+ }
211
+ // Build the set of logical IDs that need removal from the template
212
+ // This includes everything being acted on (autofix, reimport, remove)
213
+ const logicalIdsToRemove = new Set([
214
+ ...autofixImportable.map((r) => r.LogicalResourceId),
215
+ ...reimportImportable.map((r) => r.LogicalResourceId),
216
+ ...decisions.remove.map((r) => r.logicalResourceId),
217
+ ]);
218
+ // Analyze cascade removals (resources with broken Ref/GetAtt to removed resources)
219
+ const cascadeRemovals = (0, template_transformer_1.analyzeCascadeRemovals)(originalTemplate, logicalIdsToRemove);
220
+ // Partition into permanent (depend on user-removed resources) vs temporary (depend on autofix/reimport)
221
+ const permanentlyRemovedIds = new Set(decisions.remove.map((r) => r.logicalResourceId));
222
+ const permanentCascade = cascadeRemovals.filter((c) => permanentlyRemovedIds.has(c.dependsOn));
223
+ const temporaryCascade = cascadeRemovals.filter((c) => !permanentlyRemovedIds.has(c.dependsOn));
224
+ if (cascadeRemovals.length > 0) {
225
+ if (spinner)
226
+ spinner.stop();
227
+ (0, interactive_1.displayCascadeWarning)(permanentCascade, temporaryCascade);
228
+ if (spinner)
229
+ spinner.start('Processing...');
230
+ }
231
+ // Dry run - show what would be done
232
+ if (options.dryRun) {
233
+ if (spinner)
234
+ spinner.info('Dry run - planned actions:');
235
+ if (allImportable.length > 0) {
236
+ console.log('\nResources to remediate:');
237
+ for (const resource of allImportable) {
238
+ console.log(` - ${resource.LogicalResourceId} (${resource.ResourceType})`);
239
+ console.log(` Identifier: ${JSON.stringify(resource.ResourceIdentifier)}`);
240
+ }
241
+ }
242
+ if (decisions.remove.length > 0) {
243
+ console.log('\nResources to remove from stack:');
244
+ for (const r of decisions.remove) {
245
+ console.log(` - ${r.logicalResourceId} (${r.resourceType})`);
246
+ }
247
+ }
248
+ if (permanentCascade.length > 0) {
249
+ console.log('\nResources permanently cascade-removed (broken references):');
250
+ for (const c of permanentCascade) {
251
+ console.log(` - ${c.logicalResourceId} (${c.resourceType}) -> depends on ${c.dependsOn}`);
252
+ }
253
+ }
254
+ if (temporaryCascade.length > 0) {
255
+ console.log('\nResources temporarily removed and recreated:');
256
+ for (const c of temporaryCascade) {
257
+ console.log(` - ${c.logicalResourceId} (${c.resourceType}) -> depends on ${c.dependsOn}`);
258
+ }
259
+ }
260
+ result.success = true;
261
+ result.remediatedResources = allImportable.map((r) => r.LogicalResourceId);
262
+ result.removedResources = [
263
+ ...decisions.remove.map((r) => r.logicalResourceId),
264
+ ...permanentCascade.map((c) => c.logicalResourceId),
265
+ ];
266
+ return result;
267
+ }
268
+ // Determine required capabilities
269
+ const resourceTypes = allImportable.map((r) => r.ResourceType);
270
+ const additionalCaps = (0, eligible_resources_1.getAllRequiredCapabilities)(resourceTypes);
271
+ const capabilities = [...new Set([...DEFAULT_CAPABILITIES, ...additionalCaps])];
272
+ // Save recovery checkpoint before any stack mutations
273
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
274
+ const backupFileName = `.cfn-drift-remediate-backup-${stackInfo.stackName}-${timestamp}.json`;
275
+ const backupPath = path.resolve(process.cwd(), backupFileName);
276
+ const checkpoint = {
277
+ stackName: stackInfo.stackName,
278
+ stackId: stackInfo.stackId,
279
+ originalTemplateBody,
280
+ parameters: stackInfo.parameters,
281
+ driftedResourceIds: Array.from(logicalIdsToRemove),
282
+ timestamp: new Date().toISOString(),
283
+ };
284
+ fs.writeFileSync(backupPath, JSON.stringify(checkpoint, null, 2));
285
+ log(`Recovery checkpoint saved to: ${backupPath}`);
286
+ if (options.verbose) {
287
+ console.log(`Recovery checkpoint: ${backupPath}`);
288
+ }
289
+ // Step 6: Set DeletionPolicy: Retain on all resources
290
+ // DELETED resources must be removed from the template first — CloudFormation
291
+ // cannot update metadata on resources that no longer exist in AWS.
292
+ log('Setting DeletionPolicy: Retain on all resources...');
293
+ const deletedLogicalIds = new Set(allDriftedResources
294
+ .filter((r) => r.stackResourceDriftStatus === 'DELETED' && logicalIdsToRemove.has(r.logicalResourceId))
295
+ .map((r) => r.logicalResourceId));
296
+ let retainTemplate = (0, template_transformer_1.setRetentionOnAllResources)(originalTemplate);
297
+ if (deletedLogicalIds.size > 0) {
298
+ // Remove deleted resources and clean up their dangling references
299
+ const { template: cleanedTemplate } = (0, template_transformer_1.transformTemplateForRemoval)(retainTemplate, deletedLogicalIds, new Map());
300
+ retainTemplate = cleanedTemplate;
301
+ }
302
+ await client.updateStack(stackInfo.stackId, (0, template_transformer_1.stringifyTemplate)(retainTemplate), retainTemplate.Parameters ? stackInfo.parameters : undefined, capabilities);
303
+ // Step 7: Resolve cross-references to MODIFIED resources being removed
304
+ // (DELETED resources are already removed from the template, so only MODIFIED refs remain)
305
+ const modifiedIdsToRemove = new Set([...logicalIdsToRemove].filter((id) => !deletedLogicalIds.has(id)));
306
+ const references = (0, template_transformer_1.collectReferences)(retainTemplate, modifiedIdsToRemove);
307
+ let resolvedValues = new Map();
308
+ if (references.size > 0) {
309
+ log('Resolving references to drifted resources...');
310
+ const outputTemplate = (0, template_transformer_1.addResolutionOutputs)(retainTemplate, references);
311
+ await client.updateStack(stackInfo.stackId, (0, template_transformer_1.stringifyTemplate)(outputTemplate), outputTemplate.Parameters ? stackInfo.parameters : undefined, capabilities);
312
+ const updatedStackInfo = await client.getStackInfo(stackInfo.stackId);
313
+ resolvedValues = (0, template_transformer_1.parseResolvedOutputs)(updatedStackInfo.outputs || [], references);
314
+ }
315
+ // Step 8: Remove remaining (MODIFIED) resources from template
316
+ log('Removing resources from stack (resources retained in AWS)...');
317
+ const { template: removalTemplate } = (0, template_transformer_1.transformTemplateForRemoval)(retainTemplate, modifiedIdsToRemove, resolvedValues);
318
+ const removalParams = removalTemplate.Parameters ? stackInfo.parameters : undefined;
319
+ await client.updateStack(stackInfo.stackId, (0, template_transformer_1.stringifyTemplate)(removalTemplate), removalParams, capabilities);
320
+ // Step 9: Import resources (only if there are resources to import)
321
+ if (allImportable.length > 0) {
322
+ log('Preparing import template with actual resource state...');
323
+ // Build import template from the removal template (current stack state)
324
+ // and add back the resources being imported with their actual properties
325
+ const importTemplate = (0, utils_1.deepClone)(removalTemplate);
326
+ for (const importable of allImportable) {
327
+ const logicalId = importable.LogicalResourceId;
328
+ const originalResource = originalTemplate.Resources?.[logicalId];
329
+ if (!originalResource)
330
+ continue;
331
+ // Start with original resource definition
332
+ importTemplate.Resources[logicalId] = (0, utils_1.deepClone)(originalResource);
333
+ // For autofix resources, override with actual (drifted) properties
334
+ const autofixResource = decisions.autofix.find((r) => r.logicalResourceId === logicalId);
335
+ if (autofixResource?.actualProperties && Object.keys(autofixResource.actualProperties).length > 0) {
336
+ importTemplate.Resources[logicalId].Properties = autofixResource.actualProperties;
337
+ }
338
+ importTemplate.Resources[logicalId].DeletionPolicy = 'Retain';
339
+ }
340
+ // Ensure Retain on all resources in import template
341
+ for (const logicalId of Object.keys(importTemplate.Resources)) {
342
+ importTemplate.Resources[logicalId].DeletionPolicy = 'Retain';
343
+ }
344
+ log('Creating import change set...');
345
+ const changeSetName = await client.createImportChangeSet(stackInfo.stackName, (0, template_transformer_1.stringifyTemplate)(importTemplate), allImportable, capabilities);
346
+ log('Executing import...');
347
+ await client.executeChangeSet(stackInfo.stackName, changeSetName);
348
+ }
349
+ // Step 10: Restore template
350
+ if (decisions.remove.length > 0) {
351
+ // Some resources permanently removed — restore original MINUS removed resources
352
+ log('Restoring template (excluding removed resources)...');
353
+ const restoredTemplate = (0, utils_1.deepClone)(originalTemplate);
354
+ for (const r of decisions.remove) {
355
+ delete restoredTemplate.Resources[r.logicalResourceId];
356
+ }
357
+ // Clean up references and outputs pointing to removed resources
358
+ const { template: cleanedTemplate } = (0, template_transformer_1.transformTemplateForRemoval)(restoredTemplate, new Set(decisions.remove.map((r) => r.logicalResourceId)), resolvedValues);
359
+ // Restore original DeletionPolicy values (transformTemplateForRemoval sets Retain on all)
360
+ for (const [logicalId, resource] of Object.entries(cleanedTemplate.Resources || {})) {
361
+ const originalResource = originalTemplate.Resources?.[logicalId];
362
+ if (originalResource?.DeletionPolicy) {
363
+ resource.DeletionPolicy = originalResource.DeletionPolicy;
364
+ }
365
+ else {
366
+ delete resource.DeletionPolicy;
367
+ }
368
+ }
369
+ await client.updateStack(stackInfo.stackName, (0, template_transformer_1.stringifyTemplate)(cleanedTemplate), cleanedTemplate.Parameters ? stackInfo.parameters : undefined, capabilities);
370
+ }
371
+ else {
372
+ // No removals — restore exact original
373
+ log('Restoring original template...');
374
+ await client.updateStack(stackInfo.stackName, originalTemplateBody, stackInfo.parameters, capabilities);
375
+ }
376
+ result.success = true;
377
+ result.remediatedResources = allImportable.map((r) => r.LogicalResourceId);
378
+ result.removedResources = [
379
+ ...decisions.remove.map((r) => r.logicalResourceId),
380
+ ...permanentCascade.map((c) => c.logicalResourceId),
381
+ ];
382
+ if (options.verbose) {
383
+ console.log(`Remediation complete. Recovery checkpoint can be removed: ${backupPath}`);
384
+ }
385
+ }
386
+ catch (error) {
387
+ result.errors.push(error instanceof Error ? error.message : String(error));
388
+ }
389
+ return result;
390
+ }
391
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2NsaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQTBDQSw4QkE2YUM7QUF2ZEQsdUNBQXlCO0FBQ3pCLDJDQUE2QjtBQUU3QixpREFBb0Q7QUFDcEQsaUVBQTRGO0FBQzVGLG1EQUE4RTtBQUM5RSxxQ0FBaUY7QUFDakYsK0RBQTBGO0FBQzFGLHFFQVNvQztBQVNwQyx1Q0FBd0M7QUFFeEMsTUFBTSxvQkFBb0IsR0FBRyxDQUFDLGdCQUFnQixFQUFFLHNCQUFzQixFQUFFLHdCQUF3QixDQUFDLENBQUM7QUFFbEcsU0FBUyxjQUFjO0lBQ3JCLElBQUksQ0FBQztRQUNILE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLElBQUksRUFBRSxjQUFjLENBQUMsQ0FBQztRQUMzRCxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7SUFDL0QsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7QUFDSCxDQUFDO0FBRUQ7O0dBRUc7QUFDSSxLQUFLLFVBQVUsU0FBUyxDQUM3QixPQUEyQixFQUMzQixPQUFhO0lBRWIsTUFBTSxNQUFNLEdBQUcsSUFBSSw2QkFBZ0IsQ0FBQztRQUNsQyxNQUFNLEVBQUUsT0FBTyxDQUFDLE1BQU07UUFDdEIsT0FBTyxFQUFFLE9BQU8sQ0FBQyxPQUFPO0tBQ3pCLENBQUMsQ0FBQztJQUVILE1BQU0sTUFBTSxHQUFzQjtRQUNoQyxPQUFPLEVBQUUsS0FBSztRQUNkLG1CQUFtQixFQUFFLEVBQUU7UUFDdkIsZ0JBQWdCLEVBQUUsRUFBRTtRQUNwQixnQkFBZ0IsRUFBRSxFQUFFO1FBQ3BCLE1BQU0sRUFBRSxFQUFFO0tBQ1gs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TUFBTSxDQUFDO0FBQ2hCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBmcyBmcm9tICdmcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IHsgT3JhIH0gZnJvbSAnb3JhJztcbmltcG9ydCB7IENmbkNsaWVudFdyYXBwZXIgfSBmcm9tICcuL2xpYi9jZm4tY2xpZW50JztcbmltcG9ydCB7IGlzUmVzb3VyY2VJbXBvcnRhYmxlLCBnZXRBbGxSZXF1aXJlZENhcGFiaWxpdGllcyB9IGZyb20gJy4vbGliL2VsaWdpYmxlLXJlc291cmNlcyc7XG5pbXBvcnQgeyBkaXNwbGF5Q2FzY2FkZVdhcm5pbmcsIHByb21wdEZvckRlY2lzaW9ucyB9IGZyb20gJy4vbGliL2ludGVyYWN0aXZlJztcbmltcG9ydCB7IGJ1aWxkUGxhbiwgc2VyaWFsaXplUGxhbiwgbG9hZFBsYW4sIHBsYW5Ub0RlY2lzaW9ucyB9IGZyb20gJy4vbGliL3BsYW4nO1xuaW1wb3J0IHsgYnVpbGRSZXNvdXJjZXNUb0ltcG9ydCwgYnVpbGRSZWltcG9ydERlc2NyaXB0b3IgfSBmcm9tICcuL2xpYi9yZXNvdXJjZS1pbXBvcnRlcic7XG5pbXBvcnQge1xuICBwYXJzZVRlbXBsYXRlLFxuICBzdHJpbmdpZnlUZW1wbGF0ZSxcbiAgY29sbGVjdFJlZmVyZW5jZXMsXG4gIGFkZFJlc29sdXRpb25PdXRwdXRzLFxuICBwYXJzZVJlc29sdmVkT3V0cHV0cyxcbiAgc2V0UmV0ZW50aW9uT25BbGxSZXNvdXJjZXMsXG4gIHRyYW5zZm9ybVRlbXBsYXRlRm9yUmVtb3ZhbCxcbiAgYW5hbHl6ZUNhc2NhZGVSZW1vdmFscyxcbn0gZnJvbSAnLi9saWIvdGVtcGxhdGUtdHJhbnNmb3JtZXInO1xuaW1wb3J0IHtcbiAgUmVtZWRpYXRpb25PcHRpb25zLFxuICBSZW1lZGlhdGlvblJlc3VsdCxcbiAgUmVjb3ZlcnlDaGVja3BvaW50LFxuICBEcmlmdGVkUmVzb3VyY2UsXG4gIEludGVyYWN0aXZlRGVjaXNpb25zLFxuICBSZXNvdXJjZVRvSW1wb3J0LFxufSBmcm9tICcuL2xpYi90eXBlcyc7XG5pbXBvcnQgeyBkZWVwQ2xvbmUgfSBmcm9tICcuL2xpYi91dGlscyc7XG5cbmNvbnN0IERFRkFVTFRfQ0FQQUJJTElUSUVTID0gWydDQVBBQklMSVRZX0lBTScsICdDQVBBQklMSVRZX05BTUVEX0lBTScsICdDQVBBQklMSVRZX0FVVE9fRVhQQU5EJ107XG5cbmZ1bmN0aW9uIHBhY2thZ2VWZXJzaW9uKCk6IHN0cmluZyB7XG4gIHRyeSB7XG4gICAgY29uc3QgcGtnUGF0aCA9IHBhdGguam9pbihfX2Rpcm5hbWUsICcuLicsICdwYWNrYWdlLmpzb24nKTtcbiAgICByZXR1cm4gSlNPTi5wYXJzZShmcy5yZWFkRmlsZVN5bmMocGtnUGF0aCwgJ3V0Zi04JykpLnZlcnNpb247XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiAndW5rbm93bic7XG4gIH1cbn1cblxuLyoqXG4gKiBNYWluIHJlbWVkaWF0aW9uIGZ1bmN0aW9uIHRoYXQgb3JjaGVzdHJhdGVzIHRoZSBkcmlmdCByZW1lZGlhdGlvbiBwcm9jZXNzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZW1lZGlhdGUoXG4gIG9wdGlvbnM6IFJlbWVkaWF0aW9uT3B0aW9ucyxcbiAgc3Bpbm5lcj86IE9yYSxcbik6IFByb21pc2U8UmVtZWRpYXRpb25SZXN1bHQ+IHtcbiAgY29uc3QgY2xpZW50ID0gbmV3IENmbkNsaWVudFdyYXBwZXIoe1xuICAgIHJlZ2lvbjogb3B0aW9ucy5yZWdpb24sXG4gICAgcHJvZmlsZTogb3B0aW9ucy5wcm9maWxlLFxuICB9KTtcblxuICBjb25zdCByZXN1bHQ6IFJlbWVkaWF0aW9uUmVzdWx0ID0ge1xuICAgIHN1Y2Nlc3M6IGZhbHNlLFxuICAgIHJlbWVkaWF0ZWRSZXNvdXJjZXM6IFtdLFxuICAgIHNraXBwZWRSZXNvdXJjZXM6IFtdLFxuICAgIHJlbW92ZWRSZXNvdXJjZXM6IFtdLFxuICAgIGVycm9yczogW10sXG4gIH07XG5cbiAgY29uc3QgbG9nID0gKG1lc3NhZ2U6IHN0cmluZykgPT4ge1xuICAgIGlmIChzcGlubmVyKSB7XG4gICAgICBzcGlubmVyLnRleHQgPSBtZXNzYWdlO1xuICAgIH0gZWxzZSBpZiAob3B0aW9ucy52ZXJib3NlKSB7XG4gICAgICBjb25zb2xlLmxvZyhtZXNzYWdlKTtcbiAgICB9XG4gIH07XG5cbiAgdHJ5IHtcbiAgICAvLyBTdGVwIDE6IEdldCBzdGFjayBpbmZvIGFuZCBvcmlnaW5hbCB0ZW1wbGF0ZVxuICAgIGxvZygnRmV0Y2hpbmcgc3RhY2sgaW5mb3JtYXRpb24uLi4nKTtcbiAgICBjb25zdCBzdGFja0luZm8gPSBhd2FpdCBjbGllbnQuZ2V0U3RhY2tJbmZvKG9wdGlvbnMuc3RhY2tOYW1lKTtcblxuICAgIGxvZygnRmV0Y2hpbmcgb3JpZ2luYWwgdGVtcGxhdGUuLi4nKTtcbiAgICBjb25zdCBvcmlnaW5hbFRlbXBsYXRlQm9keSA9IGF3YWl0IGNsaWVudC5nZXRUZW1wbGF0ZShzdGFja0luZm8uc3RhY2tJZCwgdHJ1ZSk7XG4gICAgY29uc3Qgb3JpZ2luYWxUZW1wbGF0ZSA9IHBhcnNlVGVtcGxhdGUob3JpZ2luYWxUZW1wbGF0ZUJvZHkpO1xuXG4gICAgaWYgKG9wdGlvbnMudmVyYm9zZSkge1xuICAgICAgY29uc29sZS5sb2coYEZvdW5kIHN0YWNrOiAke3N0YWNrSW5mby5zdGFja05hbWV9ICgke3N0YWNrSW5mby5zdGFja0lkfSlgKTtcbiAgICB9XG5cbiAgICAvLyBTdGVwcyAyLTQ6IERldGVjdCBkcmlmdCBhbmQgY29sbGVjdCBkZWNpc2lvbnMgKG9yIGxvYWQgZnJvbSBwbGFuKVxuICAgIGxldCBhbGxEcmlmdGVkUmVzb3VyY2VzOiBEcmlmdGVkUmVzb3VyY2VbXTtcbiAgICBsZXQgZGVjaXNpb25zOiBJbnRlcmFjdGl2ZURlY2lzaW9ucztcblxuICAgIGlmIChvcHRpb25zLmFwcGx5UGxhbikge1xuICAgICAgLy8gQXBwbHkgYSBwcmV2aW91c2x5IGV4cG9ydGVkIHBsYW4g4oCUIHNraXAgZHJpZnQgZGV0ZWN0aW9uIGFuZCBwcm9tcHRpbmdcbiAgICAgIGxvZygnTG9hZGluZyByZW1lZGlhdGlvbiBwbGFuLi4uJyk7XG4gICAgICBjb25zdCBwbGFuSnNvbiA9IGZzLnJlYWRGaWxlU3luYyhwYXRoLnJlc29sdmUob3B0aW9ucy5hcHBseVBsYW4pLCAndXRmLTgnKTtcbiAgICAgIGNvbnN0IHBsYW4gPSBsb2FkUGxhbihwbGFuSnNvbiwgb3B0aW9ucy5zdGFja05hbWUpO1xuICAgICAgY29uc3QgbG9hZGVkID0gcGxhblRvRGVjaXNpb25zKHBsYW4pO1xuICAgICAgYWxsRHJpZnRlZFJlc291cmNlcyA9IGxvYWRlZC5hbGxEcmlmdGVkUmVzb3VyY2VzO1xuICAgICAgZGVjaXNpb25zID0gbG9hZGVkLmRlY2lzaW9ucztcblxuICAgICAgaWYgKHNwaW5uZXIpIHNwaW5uZXIuc3RhcnQoJ1Byb2Nlc3NpbmcuLi4nKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gTm9ybWFsIGZsb3c6IGRldGVjdCBkcmlmdCBhbmQgcHJvbXB0IGludGVyYWN0aXZlbHlcblxuICAgICAgLy8gU3RlcCAyOiBEZXRlY3QgZHJpZnRcbiAgICAgIGxvZygnRGV0ZWN0aW5nIHN0YWNrIGRyaWZ0Li4uJyk7XG4gICAgICBjb25zdCBkZXRlY3Rpb25JZCA9IGF3YWl0IGNsaWVudC5kZXRlY3REcmlmdChzdGFja0luZm8uc3RhY2tJZCk7XG5cbiAgICAgIGxvZygnV2FpdGluZyBmb3IgZHJpZnQgZGV0ZWN0aW9uIHRvIGNvbXBsZXRlLi4uJyk7XG4gICAgICBjb25zdCBkZXRlY3Rpb25SZXN1bHQgPSBhd2FpdCBjbGllbnQud2FpdEZvckRyaWZ0RGV0ZWN0aW9uKGRldGVjdGlvbklkKTtcblxuICAgICAgaWYgKGRldGVjdGlvblJlc3VsdC5zdGF0dXMgIT09ICdERVRFQ1RJT05fQ09NUExFVEUnKSB7XG4gICAgICAgIHJlc3VsdC5lcnJvcnMucHVzaChgRHJpZnQgZGV0ZWN0aW9uIGRpZCBub3QgY29tcGxldGU6ICR7ZGV0ZWN0aW9uUmVzdWx0LnN0YXR1c31gKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cblxuICAgICAgaWYgKGRldGVjdGlvblJlc3VsdC5kcmlmdFN0YXR1cyA9PT0gJ0lOX1NZTkMnKSB7XG4gICAgICAgIGlmIChzcGlubmVyKSBzcGlubmVyLnN1Y2NlZWQoJ1N0YWNrIGlzIGluIHN5bmMgLSBubyBkcmlmdCBkZXRlY3RlZCcpO1xuICAgICAgICByZXN1bHQuc3VjY2VzcyA9IHRydWU7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG5cbiAgICAgIC8vIFN0ZXAgMzogR2V0IGRyaWZ0ZWQgcmVzb3VyY2VzIGFuZCBzZXBhcmF0ZSBieSB0eXBlXG4gICAgICBsb2coJ0FuYWx5emluZyBkcmlmdGVkIHJlc291cmNlcy4uLicpO1xuICAgICAgYWxsRHJpZnRlZFJlc291cmNlcyA9IGF3YWl0IGNsaWVudC5nZXREcmlmdGVkUmVzb3VyY2VzKHN0YWNrSW5mby5zdGFja0lkKTtcblxuICAgICAgaWYgKGFsbERyaWZ0ZWRSZXNvdXJjZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGlmIChzcGlubmVyKSBzcGlubmVyLnN1Y2NlZWQoJ05vIGRyaWZ0ZWQgcmVzb3VyY2VzIGZvdW5kJyk7XG4gICAgICAgIHJlc3VsdC5zdWNjZXNzID0gdHJ1ZTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cblxuICAgICAgLy8gRmlsdGVyIHRvIG9ubHkgaW1wb3J0YWJsZSByZXNvdXJjZXNcbiAgICAgIGNvbnN0IG1vZGlmaWVkUmVzb3VyY2VzOiBEcmlmdGVkUmVzb3VyY2VbXSA9IFtdO1xuICAgICAgY29uc3QgZGVsZXRlZFJlc291cmNlczogRHJpZnRlZFJlc291cmNlW10gPSBbXTtcblxuICAgICAgZm9yIChjb25zdCByZXNvdXJjZSBvZiBhbGxEcmlmdGVkUmVzb3VyY2VzKSB7XG4gICAgICAgIGlmICghaXNSZXNvdXJjZUltcG9ydGFibGUocmVzb3VyY2UucmVzb3VyY2VUeXBlKSkge1xuICAgICAgICAgIHJlc3VsdC5za2lwcGVkUmVzb3VyY2VzLnB1c2gocmVzb3VyY2UubG9naWNhbFJlc291cmNlSWQpO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyZXNvdXJjZS5zdGFja1Jlc291cmNlRHJpZnRTdGF0dXMgPT09ICdERUxFVEVEJykge1xuICAgICAgICAgIGRlbGV0ZWRSZXNvdXJjZXMucHVzaChyZXNvdXJjZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbW9kaWZpZWRSZXNvdXJjZXMucHVzaChyZXNvdXJjZSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKG1vZGlmaWVkUmVzb3VyY2VzLmxlbmd0aCA9PT0gMCAmJiBkZWxldGVkUmVzb3VyY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXN1bHQuZXJyb3JzLnB1c2goJ0FsbCBkcmlmdGVkIHJlc291cmNlcyBhcmUgbm90IGVsaWdpYmxlIGZvciBpbXBvcnQnKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgIH1cblxuICAgICAgLy8gU3RlcCA0OiBJbnRlcmFjdGl2ZSBkZWNpc2lvbnNcbiAgICAgIGlmIChzcGlubmVyKSBzcGlubmVyLnN0b3AoKTtcblxuICAgICAgZGVjaXNpb25zID0gYXdhaXQgcHJvbXB0Rm9yRGVjaXNpb25zKFxuICAgICAgICBtb2RpZmllZFJlc291cmNlcyxcbiAgICAgICAgZGVsZXRlZFJlc291cmNlcyxcbiAgICAgICAgb3B0aW9ucy55ZXMgPz8gZmFsc2UsXG4gICAgICApO1xuXG4gICAgICBpZiAoc3Bpbm5lcikgc3Bpbm5lci5zdGFydCgnUHJvY2Vzc2luZy4uLicpO1xuXG4gICAgICAvLyBFeHBvcnQgcGxhbiBpZiByZXF1ZXN0ZWQgKGV4aXQgd2l0aG91dCBleGVjdXRpbmcpXG4gICAgICBpZiAob3B0aW9ucy5leHBvcnRQbGFuKSB7XG4gICAgICAgIGNvbnN0IHBsYW5NZXRhZGF0YSA9IHtcbiAgICAgICAgICBzdGFja05hbWU6IHN0YWNrSW5mby5zdGFja05hbWUsXG4gICAgICAgICAgcmVnaW9uOiBjbGllbnQucmVnaW9uLFxuICAgICAgICAgIGNyZWF0ZWRBdDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICAgICAgICAgIHRvb2xWZXJzaW9uOiBwYWNrYWdlVmVyc2lvbigpLFxuICAgICAgICAgIGRyaWZ0RGV0ZWN0aW9uSWQ6IGRldGVjdGlvbklkLFxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBwbGFuID0gYnVpbGRQbGFuKHBsYW5NZXRhZGF0YSwgZGVjaXNpb25zKTtcbiAgICAgICAgY29uc3QgcGxhblBhdGggPSBwYXRoLnJlc29sdmUob3B0aW9ucy5leHBvcnRQbGFuKTtcbiAgICAgICAgZnMud3JpdGVGaWxlU3luYyhwbGFuUGF0aCwgc2VyaWFsaXplUGxhbihwbGFuKSk7XG4gICAgICAgIGlmIChzcGlubmVyKSBzcGlubmVyLnN1Y2NlZWQoYFBsYW4gZXhwb3J0ZWQgdG8gJHtwbGFuUGF0aH1gKTtcbiAgICAgICAgcmVzdWx0LnN1Y2Nlc3MgPSB0cnVlO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFJlY29yZCBza2lwcGVkIHJlc291cmNlc1xuICAgIGZvciAoY29uc3QgciBvZiBkZWNpc2lvbnMuc2tpcCkge1xuICAgICAgcmVzdWx0LnNraXBwZWRSZXNvdXJjZXMucHVzaChyLmxvZ2ljYWxSZXNvdXJjZUlkKTtcbiAgICB9XG5cbiAgICAvLyBJZiBldmVyeXRoaW5nIHdhcyBza2lwcGVkIG9yIGNhbmNlbGxlZCwgd2UncmUgZG9uZVxuICAgIGlmIChkZWNpc2lvbnMuYXV0b2ZpeC5sZW5ndGggPT09IDAgJiYgZGVjaXNpb25zLnJlaW1wb3J0Lmxlbmd0aCA9PT0gMCAmJiBkZWNpc2lvbnMucmVtb3ZlLmxlbmd0aCA9PT0gMCkge1xuICAgICAgaWYgKHNwaW5uZXIpIHNwaW5uZXIuc3VjY2VlZCgnTm8gYWN0aW9ucyBzZWxlY3RlZCcpO1xuICAgICAgcmVzdWx0LnN1Y2Nlc3MgPSB0cnVlO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvLyBTdGVwIDU6IEJ1aWxkIHJlc291cmNlcyB0byBpbXBvcnQgZnJvbSBkZWNpc2lvbnNcbiAgICBjb25zdCByZXNvdXJjZUlkZW50aWZpZXJzID0gYXdhaXQgY2xpZW50LmdldFJlc291cmNlSWRlbnRpZmllcnMob3JpZ2luYWxUZW1wbGF0ZUJvZHkpO1xuXG4gICAgLy8gQXV0b2ZpeCByZXNvdXJjZXM6IHVzZSBleGlzdGluZyBidWlsZFJlc291cmNlc1RvSW1wb3J0XG4gICAgY29uc3QgeyBpbXBvcnRhYmxlOiBhdXRvZml4SW1wb3J0YWJsZSwgc2tpcHBlZDogYXV0b2ZpeFNraXBwZWQgfSA9XG4gICAgICBidWlsZFJlc291cmNlc1RvSW1wb3J0KGRlY2lzaW9ucy5hdXRvZml4LCByZXNvdXJjZUlkZW50aWZpZXJzKTtcblxuICAgIGZvciAoY29uc3QgcyBvZiBhdXRvZml4U2tpcHBlZCkge1xuICAgICAgaWYgKCFyZXN1bHQuc2tpcHBlZFJlc291cmNlcy5pbmNsdWRlcyhzLmxvZ2ljYWxSZXNvdXJjZUlkKSkge1xuICAgICAgICByZXN1bHQuc2tpcHBlZFJlc291cmNlcy5wdXNoKHMubG9naWNhbFJlc291cmNlSWQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFJlaW1wb3J0IHJlc291cmNlczogYnVpbGQgZnJvbSB1c2VyLXByb3ZpZGVkIHBoeXNpY2FsIElEc1xuICAgIGNvbnN0IHJlaW1wb3J0SW1wb3J0YWJsZTogUmVzb3VyY2VUb0ltcG9ydFtdID0gW107XG4gICAgZm9yIChjb25zdCB7IHJlc291cmNlLCBwaHlzaWNhbElkIH0gb2YgZGVjaXNpb25zLnJlaW1wb3J0KSB7XG4gICAgICBjb25zdCBkZXNjcmlwdG9yID0gYnVpbGRSZWltcG9ydERlc2NyaXB0b3IocmVzb3VyY2UsIHBoeXNpY2FsSWQsIHJlc291cmNlSWRlbnRpZmllcnMpO1xuICAgICAgaWYgKGRlc2NyaXB0b3IpIHtcbiAgICAgICAgcmVpbXBvcnRJbXBvcnRhYmxlLnB1c2goZGVzY3JpcHRvcik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXN1bHQuZXJyb3JzLnB1c2goXG4gICAgICAgICAgYENvdWxkIG5vdCBkZXRlcm1pbmUgaW1wb3J0IGlkZW50aWZpZXIgZm9yICR7cmVzb3VyY2UubG9naWNhbFJlc291cmNlSWR9IGZyb20gXCIke3BoeXNpY2FsSWR9XCJgLFxuICAgICAgICApO1xuICAgICAgICByZXN1bHQuc2tpcHBlZFJlc291cmNlcy5wdXNoKHJlc291cmNlLmxvZ2ljYWxSZXNvdXJjZUlkKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBDb21iaW5lZCBpbXBvcnRhYmxlIGxpc3RcbiAgICBjb25zdCBhbGxJbXBvcnRhYmxlID0gWy4uLmF1dG9maXhJbXBvcnRhYmxlLCAuLi5yZWltcG9ydEltcG9ydGFibGVdO1xuXG4gICAgLy8gSWYgbm90aGluZyB0byBpbXBvcnQgQU5EIG5vdGhpbmcgdG8gcmVtb3ZlLCB3ZSdyZSBzdHVja1xuICAgIGlmIChhbGxJbXBvcnRhYmxlLmxlbmd0aCA9PT0gMCAmJiBkZWNpc2lvbnMucmVtb3ZlLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmVzdWx0LmVycm9ycy5wdXNoKCdDb3VsZCBub3QgZGV0ZXJtaW5lIGltcG9ydCBpZGVudGlmaWVycyBmb3IgYW55IHNlbGVjdGVkIHJlc291cmNlcycpO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvLyBCdWlsZCB0aGUgc2V0IG9mIGxvZ2ljYWwgSURzIHRoYXQgbmVlZCByZW1vdmFsIGZyb20gdGhlIHRlbXBsYXRlXG4gICAgLy8gVGhpcyBpbmNsdWRlcyBldmVyeXRoaW5nIGJlaW5nIGFjdGVkIG9uIChhdXRvZml4LCByZWltcG9ydCwgcmVtb3ZlKVxuICAgIGNvbnN0IGxvZ2ljYWxJZHNUb1JlbW92ZSA9IG5ldyBTZXQoW1xuICAgICAgLi4uYXV0b2ZpeEltcG9ydGFibGUubWFwKChyKSA9PiByLkxvZ2ljYWxSZXNvdXJjZUlkKSxcbiAgICAgIC4uLnJlaW1wb3J0SW1wb3J0YWJsZS5tYXAoKHIpID0+IHIuTG9naWNhbFJlc291cmNlSWQpLFxuICAgICAgLi4uZGVjaXNpb25zLnJlbW92ZS5tYXAoKHIpID0+IHIubG9naWNhbFJlc291cmNlSWQpLFxuICAgIF0pO1xuXG4gICAgLy8gQW5hbHl6ZSBjYXNjYWRlIHJlbW92YWxzIChyZXNvdXJjZXMgd2l0aCBicm9rZW4gUmVmL0dldEF0dCB0byByZW1vdmVkIHJlc291cmNlcylcbiAgICBjb25zdCBjYXNjYWRlUmVtb3ZhbHMgPSBhbmFseXplQ2FzY2FkZVJlbW92YWxzKG9yaWdpbmFsVGVtcGxhdGUsIGxvZ2ljYWxJZHNUb1JlbW92ZSk7XG5cbiAgICAvLyBQYXJ0aXRpb24gaW50byBwZXJtYW5lbnQgKGRlcGVuZCBvbiB1c2VyLXJlbW92ZWQgcmVzb3VyY2VzKSB2cyB0ZW1wb3JhcnkgKGRlcGVuZCBvbiBhdXRvZml4L3JlaW1wb3J0KVxuICAgIGNvbnN0IHBlcm1hbmVudGx5UmVtb3ZlZElkcyA9IG5ldyBTZXQoZGVjaXNpb25zLnJlbW92ZS5tYXAoKHIpID0+IHIubG9naWNhbFJlc291cmNlSWQpKTtcbiAgICBjb25zdCBwZXJtYW5lbnRDYXNjYWRlID0gY2FzY2FkZVJlbW92YWxzLmZpbHRlcigoYykgPT4gcGVybWFuZW50bHlSZW1vdmVkSWRzLmhhcyhjLmRlcGVuZHNPbikpO1xuICAgIGNvbnN0IHRlbXBvcmFyeUNhc2NhZGUgPSBjYXNjYWRlUmVtb3ZhbHMuZmlsdGVyKChjKSA9PiAhcGVybWFuZW50bHlSZW1vdmVkSWRzLmhhcyhjLmRlcGVuZHNPbikpO1xuXG4gICAgaWYgKGNhc2NhZGVSZW1vdmFscy5sZW5ndGggPiAwKSB7XG4gICAgICBpZiAoc3Bpbm5lcikgc3Bpbm5lci5zdG9wKCk7XG4gICAgICBkaXNwbGF5Q2FzY2FkZVdhcm5pbmcocGVybWFuZW50Q2FzY2FkZSwgdGVtcG9yYXJ5Q2FzY2FkZSk7XG4gICAgICBpZiAoc3Bpbm5lcikgc3Bpbm5lci5zdGFydCgnUHJvY2Vzc2luZy4uLicpO1xuICAgIH1cblxuICAgIC8vIERyeSBydW4gLSBzaG93IHdoYXQgd291bGQgYmUgZG9uZVxuICAgIGlmIChvcHRpb25zLmRyeVJ1bikge1xuICAgICAgaWYgKHNwaW5uZXIpIHNwaW5uZXIuaW5mbygnRHJ5IHJ1biAtIHBsYW5uZWQgYWN0aW9uczonKTtcbiAgICAgIGlmIChhbGxJbXBvcnRhYmxlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgY29uc29sZS5sb2coJ1xcblJlc291cmNlcyB0byByZW1lZGlhdGU6Jyk7XG4gICAgICAgIGZvciAoY29uc3QgcmVzb3VyY2Ugb2YgYWxsSW1wb3J0YWJsZSkge1xuICAgICAgICAgIGNvbnNvbGUubG9nKGAgIC0gJHtyZXNvdXJjZS5Mb2dpY2FsUmVzb3VyY2VJZH0gKCR7cmVzb3VyY2UuUmVzb3VyY2VUeXBlfSlgKTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhgICAgIElkZW50aWZpZXI6ICR7SlNPTi5zdHJpbmdpZnkocmVzb3VyY2UuUmVzb3VyY2VJZGVudGlmaWVyKX1gKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGRlY2lzaW9ucy5yZW1vdmUubGVuZ3RoID4gMCkge1xuICAgICAgICBjb25zb2xlLmxvZygnXFxuUmVzb3VyY2VzIHRvIHJlbW92ZSBmcm9tIHN0YWNrOicpO1xuICAgICAgICBmb3IgKGNvbnN0IHIgb2YgZGVjaXNpb25zLnJlbW92ZSkge1xuICAgICAgICAgIGNvbnNvbGUubG9nKGAgIC0gJHtyLmxvZ2ljYWxSZXNvdXJjZUlkfSAoJHtyLnJlc291cmNlVHlwZX0pYCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChwZXJtYW5lbnRDYXNjYWRlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgY29uc29sZS5sb2coJ1xcblJlc291cmNlcyBwZXJtYW5lbnRseSBjYXNjYWRlLXJlbW92ZWQgKGJyb2tlbiByZWZlcmVuY2VzKTonKTtcbiAgICAgICAgZm9yIChjb25zdCBjIG9mIHBlcm1hbmVudENhc2NhZGUpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhgICAtICR7Yy5sb2dpY2FsUmVzb3VyY2VJZH0gKCR7Yy5yZXNvdXJjZVR5cGV9KSAtPiBkZXBlbmRzIG9uICR7Yy5kZXBlbmRzT259YCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmICh0ZW1wb3JhcnlDYXNjYWRlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgY29uc29sZS5sb2coJ1xcblJlc291cmNlcyB0ZW1wb3JhcmlseSByZW1vdmVkIGFuZCByZWNyZWF0ZWQ6Jyk7XG4gICAgICAgIGZvciAoY29uc3QgYyBvZiB0ZW1wb3JhcnlDYXNjYWRlKSB7XG4gICAgICAgICAgY29uc29sZS5sb2coYCAgLSAke2MubG9naWNhbFJlc291cmNlSWR9ICgke2MucmVzb3VyY2VUeXBlfSkgLT4gZGVwZW5kcyBvbiAke2MuZGVwZW5kc09ufWApO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXN1bHQuc3VjY2VzcyA9IHRydWU7XG4gICAgICByZXN1bHQucmVtZWRpYXRlZFJlc291cmNlcyA9IGFsbEltcG9ydGFibGUubWFwKChyKSA9PiByLkxvZ2ljYWxSZXNvdXJjZUlkKTtcbiAgICAgIHJlc3VsdC5yZW1vdmVkUmVzb3VyY2VzID0gW1xuICAgICAgICAuLi5kZWNpc2lvbnMucmVtb3ZlLm1hcCgocikgPT4gci5sb2dpY2FsUmVzb3VyY2VJZCksXG4gICAgICAgIC4uLnBlcm1hbmVudENhc2NhZGUubWFwKChjKSA9PiBjLmxvZ2ljYWxSZXNvdXJjZUlkKSxcbiAgICAgIF07XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8vIERldGVybWluZSByZXF1aXJlZCBjYXBhYmlsaXRpZXNcbiAgICBjb25zdCByZXNvdXJjZVR5cGVzID0gYWxsSW1wb3J0YWJsZS5tYXAoKHIpID0+IHIuUmVzb3VyY2VUeXBlKTtcbiAgICBjb25zdCBhZGRpdGlvbmFsQ2FwcyA9IGdldEFsbFJlcXVpcmVkQ2FwYWJpbGl0aWVzKHJlc291cmNlVHlwZXMpO1xuICAgIGNvbnN0IGNhcGFiaWxpdGllcyA9IFsuLi5uZXcgU2V0KFsuLi5ERUZBVUxUX0NBUEFCSUxJVElFUywgLi4uYWRkaXRpb25hbENhcHNdKV07XG5cbiAgICAvLyBTYXZlIHJlY292ZXJ5IGNoZWNrcG9pbnQgYmVmb3JlIGFueSBzdGFjayBtdXRhdGlvbnNcbiAgICBjb25zdCB0aW1lc3RhbXAgPSBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCkucmVwbGFjZSgvWzouXS9nLCAnLScpO1xuICAgIGNvbnN0IGJhY2t1cEZpbGVOYW1lID0gYC5jZm4tZHJpZnQtcmVtZWRpYXRlLWJhY2t1cC0ke3N0YWNrSW5mby5zdGFja05hbWV9LSR7dGltZXN0YW1wfS5qc29uYDtcbiAgICBjb25zdCBiYWNrdXBQYXRoID0gcGF0aC5yZXNvbHZlKHByb2Nlc3MuY3dkKCksIGJhY2t1cEZpbGVOYW1lKTtcbiAgICBjb25zdCBjaGVja3BvaW50OiBSZWNvdmVyeUNoZWNrcG9pbnQgPSB7XG4gICAgICBzdGFja05hbWU6IHN0YWNrSW5mby5zdGFja05hbWUsXG4gICAgICBzdGFja0lkOiBzdGFja0luZm8uc3RhY2tJZCxcbiAgICAgIG9yaWdpbmFsVGVtcGxhdGVCb2R5LFxuICAgICAgcGFyYW1ldGVyczogc3RhY2tJbmZvLnBhcmFtZXRlcnMsXG4gICAgICBkcmlmdGVkUmVzb3VyY2VJZHM6IEFycmF5LmZyb20obG9naWNhbElkc1RvUmVtb3ZlKSxcbiAgICAgIHRpbWVzdGFtcDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICAgIH07XG4gICAgZnMud3JpdGVGaWxlU3luYyhiYWNrdXBQYXRoLCBKU09OLnN0cmluZ2lmeShjaGVja3BvaW50LCBudWxsLCAyKSk7XG4gICAgbG9nKGBSZWNvdmVyeSBjaGVja3BvaW50IHNhdmVkIHRvOiAke2JhY2t1cFBhdGh9YCk7XG4gICAgaWYgKG9wdGlvbnMudmVyYm9zZSkge1xuICAgICAgY29uc29sZS5sb2coYFJlY292ZXJ5IGNoZWNrcG9pbnQ6ICR7YmFja3VwUGF0aH1gKTtcbiAgICB9XG5cbiAgICAvLyBTdGVwIDY6IFNldCBEZWxldGlvblBvbGljeTogUmV0YWluIG9uIGFsbCByZXNvdXJjZXNcbiAgICAvLyBERUxFVEVEIHJlc291cmNlcyBtdXN0IGJlIHJlbW92ZWQgZnJvbSB0aGUgdGVtcGxhdGUgZmlyc3Qg4oCUIENsb3VkRm9ybWF0aW9uXG4gICAgLy8gY2Fubm90IHVwZGF0ZSBtZXRhZGF0YSBvbiByZXNvdXJjZXMgdGhhdCBubyBsb25nZXIgZXhpc3QgaW4gQVdTLlxuICAgIGxvZygnU2V0dGluZyBEZWxldGlvblBvbGljeTogUmV0YWluIG9uIGFsbCByZXNvdXJjZXMuLi4nKTtcbiAgICBjb25zdCBkZWxldGVkTG9naWNhbElkcyA9IG5ldyBTZXQoXG4gICAgICBhbGxEcmlmdGVkUmVzb3VyY2VzXG4gICAgICAgIC5maWx0ZXIoKHIpID0+IHIuc3RhY2tSZXNvdXJjZURyaWZ0U3RhdHVzID09PSAnREVMRVRFRCcgJiYgbG9naWNhbElkc1RvUmVtb3ZlLmhhcyhyLmxvZ2ljYWxSZXNvdXJjZUlkKSlcbiAgICAgICAgLm1hcCgocikgPT4gci5sb2dpY2FsUmVzb3VyY2VJZCksXG4gICAgKTtcblxuICAgIGxldCByZXRhaW5UZW1wbGF0ZSA9IHNldFJldGVudGlvbk9uQWxsUmVzb3VyY2VzKG9yaWdpbmFsVGVtcGxhdGUpO1xuXG4gICAgaWYgKGRlbGV0ZWRMb2dpY2FsSWRzLnNpemUgPiAwKSB7XG4gICAgICAvLyBSZW1vdmUgZGVsZXRlZCByZXNvdXJjZXMgYW5kIGNsZWFuIHVwIHRoZWlyIGRhbmdsaW5nIHJlZmVyZW5jZXNcbiAgICAgIGNvbnN0IHsgdGVtcGxhdGU6IGNsZWFuZWRUZW1wbGF0ZSB9ID0gdHJhbnNmb3JtVGVtcGxhdGVGb3JSZW1vdmFsKFxuICAgICAgICByZXRhaW5UZW1wbGF0ZSxcbiAgICAgICAgZGVsZXRlZExvZ2ljYWxJZHMsXG4gICAgICAgIG5ldyBNYXAoKSwgLy8gbm8gcmVzb2x2ZWQgdmFsdWVzIOKAlCBqdXN0IHN0cmlwIHVucmVzb2x2YWJsZSByZWZlcmVuY2VzXG4gICAgICApO1xuICAgICAgcmV0YWluVGVtcGxhdGUgPSBjbGVhbmVkVGVtcGxhdGU7XG4gICAgfVxuXG4gICAgYXdhaXQgY2xpZW50LnVwZGF0ZVN0YWNrKFxuICAgICAgc3RhY2tJbmZvLnN0YWNrSWQsXG4gICAgICBzdHJpbmdpZnlUZW1wbGF0ZShyZXRhaW5UZW1wbGF0ZSksXG4gICAgICByZXRhaW5UZW1wbGF0ZS5QYXJhbWV0ZXJzID8gc3RhY2tJbmZvLnBhcmFtZXRlcnMgOiB1bmRlZmluZWQsXG4gICAgICBjYXBhYmlsaXRpZXMsXG4gICAgKTtcblxuICAgIC8vIFN0ZXAgNzogUmVzb2x2ZSBjcm9zcy1yZWZlcmVuY2VzIHRvIE1PRElGSUVEIHJlc291cmNlcyBiZWluZyByZW1vdmVkXG4gICAgLy8gKERFTEVURUQgcmVzb3VyY2VzIGFyZSBhbHJlYWR5IHJlbW92ZWQgZnJvbSB0aGUgdGVtcGxhdGUsIHNvIG9ubHkgTU9ESUZJRUQgcmVmcyByZW1haW4pXG4gICAgY29uc3QgbW9kaWZpZWRJZHNUb1JlbW92ZSA9IG5ldyBTZXQoXG4gICAgICBbLi4ubG9naWNhbElkc1RvUmVtb3ZlXS5maWx0ZXIoKGlkKSA9PiAhZGVsZXRlZExvZ2ljYWxJZHMuaGFzKGlkKSksXG4gICAgKTtcbiAgICBjb25zdCByZWZlcmVuY2VzID0gY29sbGVjdFJlZmVyZW5jZXMocmV0YWluVGVtcGxhdGUsIG1vZGlmaWVkSWRzVG9SZW1vdmUpO1xuXG4gICAgbGV0IHJlc29sdmVkVmFsdWVzID0gbmV3IE1hcDxzdHJpbmcsIHVua25vd24+KCk7XG4gICAgaWYgKHJlZmVyZW5jZXMuc2l6ZSA+IDApIHtcbiAgICAgIGxvZygnUmVzb2x2aW5nIHJlZmVyZW5jZXMgdG8gZHJpZnRlZCByZXNvdXJjZXMuLi4nKTtcblxuICAgICAgY29uc3Qgb3V0cHV0VGVtcGxhdGUgPSBhZGRSZXNvbHV0aW9uT3V0cHV0cyhyZXRhaW5UZW1wbGF0ZSwgcmVmZXJlbmNlcyk7XG4gICAgICBhd2FpdCBjbGllbnQudXBkYXRlU3RhY2soXG4gICAgICAgIHN0YWNrSW5mby5zdGFja0lkLFxuICAgICAgICBzdHJpbmdpZnlUZW1wbGF0ZShvdXRwdXRUZW1wbGF0ZSksXG4gICAgICAgIG91dHB1dFRlbXBsYXRlLlBhcmFtZXRlcnMgPyBzdGFja0luZm8ucGFyYW1ldGVycyA6IHVuZGVmaW5lZCxcbiAgICAgICAgY2FwYWJpbGl0aWVzLFxuICAgICAgKTtcblxuICAgICAgY29uc3QgdXBkYXRlZFN0YWNrSW5mbyA9IGF3YWl0IGNsaWVudC5nZXRTdGFja0luZm8oc3RhY2tJbmZvLnN0YWNrSWQpO1xuICAgICAgcmVzb2x2ZWRWYWx1ZXMgPSBwYXJzZVJlc29sdmVkT3V0cHV0cyh1cGRhdGVkU3RhY2tJbmZvLm91dHB1dHMgfHwgW10sIHJlZmVyZW5jZXMpO1xuICAgIH1cblxuICAgIC8vIFN0ZXAgODogUmVtb3ZlIHJlbWFpbmluZyAoTU9ESUZJRUQpIHJlc291cmNlcyBmcm9tIHRlbXBsYXRlXG4gICAgbG9nKCdSZW1vdmluZyByZXNvdXJjZXMgZnJvbSBzdGFjayAocmVzb3VyY2VzIHJldGFpbmVkIGluIEFXUykuLi4nKTtcbiAgICBjb25zdCB7IHRlbXBsYXRlOiByZW1vdmFsVGVtcGxhdGUgfSA9IHRyYW5zZm9ybVRlbXBsYXRlRm9yUmVtb3ZhbChcbiAgICAgIHJldGFpblRlbXBsYXRlLFxuICAgICAgbW9kaWZpZWRJZHNUb1JlbW92ZSxcbiAgICAgIHJlc29sdmVkVmFsdWVzLFxuICAgICk7XG5cbiAgICBjb25zdCByZW1vdmFsUGFyYW1zID0gcmVtb3ZhbFRlbXBsYXRlLlBhcmFtZXRlcnMgPyBzdGFja0luZm8ucGFyYW1ldGVycyA6IHVuZGVmaW5lZDtcbiAgICBhd2FpdCBjbGllbnQudXBkYXRlU3RhY2soXG4gICAgICBzdGFja0luZm8uc3RhY2tJZCxcbiAgICAgIHN0cmluZ2lmeVRlbXBsYXRlKHJlbW92YWxUZW1wbGF0ZSksXG4gICAgICByZW1vdmFsUGFyYW1zLFxuICAgICAgY2FwYWJpbGl0aWVzLFxuICAgICk7XG5cbiAgICAvLyBTdGVwIDk6IEltcG9ydCByZXNvdXJjZXMgKG9ubHkgaWYgdGhlcmUgYXJlIHJlc291cmNlcyB0byBpbXBvcnQpXG4gICAgaWYgKGFsbEltcG9ydGFibGUubGVuZ3RoID4gMCkge1xuICAgICAgbG9nKCdQcmVwYXJpbmcgaW1wb3J0IHRlbXBsYXRlIHdpdGggYWN0dWFsIHJlc291cmNlIHN0YXRlLi4uJyk7XG5cbiAgICAgIC8vIEJ1aWxkIGltcG9ydCB0ZW1wbGF0ZSBmcm9tIHRoZSByZW1vdmFsIHRlbXBsYXRlIChjdXJyZW50IHN0YWNrIHN0YXRlKVxuICAgICAgLy8gYW5kIGFkZCBiYWNrIHRoZSByZXNvdXJjZXMgYmVpbmcgaW1wb3J0ZWQgd2l0aCB0aGVpciBhY3R1YWwgcHJvcGVydGllc1xuICAgICAgY29uc3QgaW1wb3J0VGVtcGxhdGUgPSBkZWVwQ2xvbmUocmVtb3ZhbFRlbXBsYXRlKTtcblxuICAgICAgZm9yIChjb25zdCBpbXBvcnRhYmxlIG9mIGFsbEltcG9ydGFibGUpIHtcbiAgICAgICAgY29uc3QgbG9naWNhbElkID0gaW1wb3J0YWJsZS5Mb2dpY2FsUmVzb3VyY2VJZDtcbiAgICAgICAgY29uc3Qgb3JpZ2luYWxSZXNvdXJjZSA9IG9yaWdpbmFsVGVtcGxhdGUuUmVzb3VyY2VzPy5bbG9naWNhbElkXTtcbiAgICAgICAgaWYgKCFvcmlnaW5hbFJlc291cmNlKSBjb250aW51ZTtcblxuICAgICAgICAvLyBTdGFydCB3aXRoIG9yaWdpbmFsIHJlc291cmNlIGRlZmluaXRpb25cbiAgICAgICAgaW1wb3J0VGVtcGxhdGUuUmVzb3VyY2VzW2xvZ2ljYWxJZF0gPSBkZWVwQ2xvbmUob3JpZ2luYWxSZXNvdXJjZSk7XG5cbiAgICAgICAgLy8gRm9yIGF1dG9maXggcmVzb3VyY2VzLCBvdmVycmlkZSB3aXRoIGFjdHVhbCAoZHJpZnRlZCkgcHJvcGVydGllc1xuICAgICAgICBjb25zdCBhdXRvZml4UmVzb3VyY2UgPSBkZWNpc2lvbnMuYXV0b2ZpeC5maW5kKChyKSA9PiByLmxvZ2ljYWxSZXNvdXJjZUlkID09PSBsb2dpY2FsSWQpO1xuICAgICAgICBpZiAoYXV0b2ZpeFJlc291cmNlPy5hY3R1YWxQcm9wZXJ0aWVzICYmIE9iamVjdC5rZXlzKGF1dG9maXhSZXNvdXJjZS5hY3R1YWxQcm9wZXJ0aWVzKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgaW1wb3J0VGVtcGxhdGUuUmVzb3VyY2VzW2xvZ2ljYWxJZF0uUHJvcGVydGllcyA9IGF1dG9maXhSZXNvdXJjZS5hY3R1YWxQcm9wZXJ0aWVzO1xuICAgICAgICB9XG5cbiAgICAgICAgaW1wb3J0VGVtcGxhdGUuUmVzb3VyY2VzW2xvZ2ljYWxJZF0uRGVsZXRpb25Qb2xpY3kgPSAnUmV0YWluJztcbiAgICAgIH1cblxuICAgICAgLy8gRW5zdXJlIFJldGFpbiBvbiBhbGwgcmVzb3VyY2VzIGluIGltcG9ydCB0ZW1wbGF0ZVxuICAgICAgZm9yIChjb25zdCBsb2dpY2FsSWQgb2YgT2JqZWN0LmtleXMoaW1wb3J0VGVtcGxhdGUuUmVzb3VyY2VzKSkge1xuICAgICAgICBpbXBvcnRUZW1wbGF0ZS5SZXNvdXJjZXNbbG9naWNhbElkXS5EZWxldGlvblBvbGljeSA9ICdSZXRhaW4nO1xuICAgICAgfVxuXG4gICAgICBsb2coJ0NyZWF0aW5nIGltcG9ydCBjaGFuZ2Ugc2V0Li4uJyk7XG4gICAgICBjb25zdCBjaGFuZ2VTZXROYW1lID0gYXdhaXQgY2xpZW50LmNyZWF0ZUltcG9ydENoYW5nZVNldChcbiAgICAgICAgc3RhY2tJbmZvLnN0YWNrTmFtZSxcbiAgICAgICAgc3RyaW5naWZ5VGVtcGxhdGUoaW1wb3J0VGVtcGxhdGUpLFxuICAgICAgICBhbGxJbXBvcnRhYmxlLFxuICAgICAgICBjYXBhYmlsaXRpZXMsXG4gICAgICApO1xuXG4gICAgICBsb2coJ0V4ZWN1dGluZyBpbXBvcnQuLi4nKTtcbiAgICAgIGF3YWl0IGNsaWVudC5leGVjdXRlQ2hhbmdlU2V0KHN0YWNrSW5mby5zdGFja05hbWUsIGNoYW5nZVNldE5hbWUpO1xuICAgIH1cblxuICAgIC8vIFN0ZXAgMTA6IFJlc3RvcmUgdGVtcGxhdGVcbiAgICBpZiAoZGVjaXNpb25zLnJlbW92ZS5sZW5ndGggPiAwKSB7XG4gICAgICAvLyBTb21lIHJlc291cmNlcyBwZXJtYW5lbnRseSByZW1vdmVkIOKAlCByZXN0b3JlIG9yaWdpbmFsIE1JTlVTIHJlbW92ZWQgcmVzb3VyY2VzXG4gICAgICBsb2coJ1Jlc3RvcmluZyB0ZW1wbGF0ZSAoZXhjbHVkaW5nIHJlbW92ZWQgcmVzb3VyY2VzKS4uLicpO1xuICAgICAgY29uc3QgcmVzdG9yZWRUZW1wbGF0ZSA9IGRlZXBDbG9uZShvcmlnaW5hbFRlbXBsYXRlKTtcbiAgICAgIGZvciAoY29uc3QgciBvZiBkZWNpc2lvbnMucmVtb3ZlKSB7XG4gICAgICAgIGRlbGV0ZSByZXN0b3JlZFRlbXBsYXRlLlJlc291cmNlc1tyLmxvZ2ljYWxSZXNvdXJjZUlkXTtcbiAgICAgIH1cbiAgICAgIC8vIENsZWFuIHVwIHJlZmVyZW5jZXMgYW5kIG91dHB1dHMgcG9pbnRpbmcgdG8gcmVtb3ZlZCByZXNvdXJjZXNcbiAgICAgIGNvbnN0IHsgdGVtcGxhdGU6IGNsZWFuZWRUZW1wbGF0ZSB9ID0gdHJhbnNmb3JtVGVtcGxhdGVGb3JSZW1vdmFsKFxuICAgICAgICByZXN0b3JlZFRlbXBsYXRlLFxuICAgICAgICBuZXcgU2V0KGRlY2lzaW9ucy5yZW1vdmUubWFwKChyKSA9PiByLmxvZ2ljYWxSZXNvdXJjZUlkKSksXG4gICAgICAgIHJlc29sdmVkVmFsdWVzLFxuICAgICAgKTtcbiAgICAgIC8vIFJlc3RvcmUgb3JpZ2luYWwgRGVsZXRpb25Qb2xpY3kgdmFsdWVzICh0cmFuc2Zvcm1UZW1wbGF0ZUZvclJlbW92YWwgc2V0cyBSZXRhaW4gb24gYWxsKVxuICAgICAgZm9yIChjb25zdCBbbG9naWNhbElkLCByZXNvdXJjZV0gb2YgT2JqZWN0LmVudHJpZXMoY2xlYW5lZFRlbXBsYXRlLlJlc291cmNlcyB8fCB7fSkpIHtcbiAgICAgICAgY29uc3Qgb3JpZ2luYWxSZXNvdXJjZSA9IG9yaWdpbmFsVGVtcGxhdGUuUmVzb3VyY2VzPy5bbG9naWNhbElkXTtcbiAgICAgICAgaWYgKG9yaWdpbmFsUmVzb3VyY2U/LkRlbGV0aW9uUG9saWN5KSB7XG4gICAgICAgICAgcmVzb3VyY2UuRGVsZXRpb25Qb2xpY3kgPSBvcmlnaW5hbFJlc291cmNlLkRlbGV0aW9uUG9saWN5O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGRlbGV0ZSByZXNvdXJjZS5EZWxldGlvblBvbGljeTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgYXdhaXQgY2xpZW50LnVwZGF0ZVN0YWNrKFxuICAgICAgICBzdGFja0luZm8uc3RhY2tOYW1lLFxuICAgICAgICBzdHJpbmdpZnlUZW1wbGF0ZShjbGVhbmVkVGVtcGxhdGUpLFxuICAgICAgICBjbGVhbmVkVGVtcGxhdGUuUGFyYW1ldGVycyA/IHN0YWNrSW5mby5wYXJhbWV0ZXJzIDogdW5kZWZpbmVkLFxuICAgICAgICBjYXBhYmlsaXRpZXMsXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBObyByZW1vdmFscyDigJQgcmVzdG9yZSBleGFjdCBvcmlnaW5hbFxuICAgICAgbG9nKCdSZXN0b3Jpbmcgb3JpZ2luYWwgdGVtcGxhdGUuLi4nKTtcbiAgICAgIGF3YWl0IGNsaWVudC51cGRhdGVTdGFjayhcbiAgICAgICAgc3RhY2tJbmZvLnN0YWNrTmFtZSxcbiAgICAgICAgb3JpZ2luYWxUZW1wbGF0ZUJvZHksXG4gICAgICAgIHN0YWNrSW5mby5wYXJhbWV0ZXJzLFxuICAgICAgICBjYXBhYmlsaXRpZXMsXG4gICAgICApO1xuICAgIH1cblxuICAgIHJlc3VsdC5zdWNjZXNzID0gdHJ1ZTtcbiAgICByZXN1bHQucmVtZWRpYXRlZFJlc291cmNlcyA9IGFsbEltcG9ydGFibGUubWFwKChyKSA9PiByLkxvZ2ljYWxSZXNvdXJjZUlkKTtcbiAgICByZXN1bHQucmVtb3ZlZFJlc291cmNlcyA9IFtcbiAgICAgIC4uLmRlY2lzaW9ucy5yZW1vdmUubWFwKChyKSA9PiByLmxvZ2ljYWxSZXNvdXJjZUlkKSxcbiAgICAgIC4uLnBlcm1hbmVudENhc2NhZGUubWFwKChjKSA9PiBjLmxvZ2ljYWxSZXNvdXJjZUlkKSxcbiAgICBdO1xuXG4gICAgaWYgKG9wdGlvbnMudmVyYm9zZSkge1xuICAgICAgY29uc29sZS5sb2coYFJlbWVkaWF0aW9uIGNvbXBsZXRlLiBSZWNvdmVyeSBjaGVja3BvaW50IGNhbiBiZSByZW1vdmVkOiAke2JhY2t1cFBhdGh9YCk7XG4gICAgfVxuXG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgcmVzdWx0LmVycm9ycy5wdXNoKGVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBlcnJvci5tZXNzYWdlIDogU3RyaW5nKGVycm9yKSk7XG4gIH1cblxuICByZXR1cm4gcmVzdWx0O1xufVxuIl19
package/lib/index.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ export { remediate } from './cli';
3
+ export { CfnClientWrapper } from './lib/cfn-client';
4
+ export * from './lib/types';
5
+ export * from './lib/eligible-resources';
6
+ export * from './lib/template-transformer';
7
+ export * from './lib/resource-importer';
8
+ export * from './lib/resource-identifier';
9
+ export { promptForDecisions, formatDriftDiff, displayCascadeWarning } from './lib/interactive';
10
+ export { buildPlan, serializePlan, loadPlan, planToDecisions } from './lib/plan';