UNPKG

@aws-cdk/integ-runner

Version:

CDK Integration Testing Tool

247 lines 34.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AssemblyManifestReader = void 0; const path = require("path"); const cdk_assets_lib_1 = require("@aws-cdk/cdk-assets-lib"); const cloud_assembly_api_1 = require("@aws-cdk/cloud-assembly-api"); const cloud_assembly_schema_1 = require("@aws-cdk/cloud-assembly-schema"); const fs = require("fs-extra"); /** * Reads a Cloud Assembly manifest */ class AssemblyManifestReader { manifest; manifestFileName; static DEFAULT_FILENAME = 'manifest.json'; /** * Reads a Cloud Assembly manifest from a file */ static fromFile(fileName) { try { const obj = cloud_assembly_schema_1.Manifest.loadAssemblyManifest(fileName); return new AssemblyManifestReader(path.dirname(fileName), obj, fileName); } catch (e) { throw new Error(`Cannot read integ manifest '${fileName}': ${e.message}`); } } /** * Reads a Cloud Assembly manifest from a file or a directory * If the given filePath is a directory then it will look for * a file within the directory with the DEFAULT_FILENAME */ static fromPath(filePath) { let st; try { st = fs.statSync(filePath); } catch (e) { throw new Error(`Cannot read integ manifest at '${filePath}': ${e.message}`); } if (st.isDirectory()) { return AssemblyManifestReader.fromFile(path.join(filePath, AssemblyManifestReader.DEFAULT_FILENAME)); } return AssemblyManifestReader.fromFile(filePath); } /** * The directory where the manifest was found */ directory; constructor(directory, manifest, manifestFileName) { this.manifest = manifest; this.manifestFileName = manifestFileName; this.directory = directory; } /** * Get the stacks from the manifest * returns a map of artifactId to CloudFormation template */ get stacks() { const stacks = {}; for (const [artifactId, artifact] of Object.entries(this.manifest.artifacts ?? {})) { if (artifact.type !== cloud_assembly_schema_1.ArtifactType.AWS_CLOUDFORMATION_STACK) { continue; } const props = artifact.properties; const template = fs.readJSONSync(path.resolve(this.directory, props.templateFile)); stacks[artifactId] = template; } return stacks; } /** * Get the nested stacks for a given stack * returns a map of artifactId to CloudFormation template */ getNestedStacksForStack(stackId) { const nestedTemplates = this.getAssetManifestsForStack(stackId).flatMap(manifest => manifest.files .filter(asset => asset.source.path?.endsWith('.nested.template.json')) .map(asset => asset.source.path)); const nestedStacks = Object.fromEntries(nestedTemplates.map(templateFile => ([ templateFile.split('.', 1)[0], fs.readJSONSync(path.resolve(this.directory, templateFile)), ]))); return nestedStacks; } /** * Write trace data to the assembly manifest metadata */ recordTrace(trace) { const newManifest = { ...this.manifest, artifacts: this.renderArtifacts(trace), }; cloud_assembly_schema_1.Manifest.saveAssemblyManifest(newManifest, this.manifestFileName); } /** * Return a list of assets for a given stack */ getAssetIdsForStack(stackId) { const assets = []; for (const artifact of Object.values(this.manifest.artifacts ?? {})) { if (artifact.type === cloud_assembly_schema_1.ArtifactType.ASSET_MANIFEST && artifact.properties?.file === `${stackId}.assets.json`) { assets.push(...this.assetsFromAssetManifest(artifact).map(asset => asset.id.assetId)); } else if (artifact.type === cloud_assembly_schema_1.ArtifactType.AWS_CLOUDFORMATION_STACK) { assets.push(...this.assetsFromAssemblyManifest(artifact).map(asset => asset.id)); } } return assets; } /** * For a given stackId return a list of assets that belong to the stack */ getAssetLocationsForStack(stackId) { const assets = []; for (const artifact of Object.values(this.manifest.artifacts ?? {})) { if (artifact.type === cloud_assembly_schema_1.ArtifactType.ASSET_MANIFEST && artifact.properties?.file === `${stackId}.assets.json`) { assets.push(...this.assetsFromAssetManifest(artifact).flatMap(asset => { if (asset.type === 'file' && !asset.source.path?.endsWith('nested.template.json')) { return asset.source.path; } else if (asset.type !== 'file') { return asset.source.directory; } return []; })); } else if (artifact.type === cloud_assembly_schema_1.ArtifactType.AWS_CLOUDFORMATION_STACK) { assets.push(...this.assetsFromAssemblyManifest(artifact).map(asset => asset.path)); } } return assets; } /** * Return a list of asset artifacts for a given stack */ getAssetManifestsForStack(stackId) { return Object.values(this.manifest.artifacts ?? {}) .filter(artifact => artifact.type === cloud_assembly_schema_1.ArtifactType.ASSET_MANIFEST && artifact.properties?.file === `${stackId}.assets.json`) .map(artifact => { const fileName = artifact.properties.file; return cdk_assets_lib_1.AssetManifest.fromFile(path.join(this.directory, fileName)); }); } /** * Get a list of assets from the assembly manifest */ assetsFromAssemblyManifest(artifact) { const assets = []; for (const metadata of Object.values(cloud_assembly_api_1.CloudArtifact.readMetadata(this.directory, artifact) ?? {})) { metadata.forEach(data => { if (data.type === cloud_assembly_schema_1.ArtifactMetadataEntryType.ASSET) { const asset = data.data; if (asset.path.startsWith('asset.')) { assets.push(asset); } } }); } return assets; } /** * Get a list of assets from the asset manifest */ assetsFromAssetManifest(artifact) { const assets = []; const fileName = artifact.properties.file; const assetManifest = cdk_assets_lib_1.AssetManifest.fromFile(path.join(this.directory, fileName)); assetManifest.entries.forEach(entry => { if (entry.type === 'file') { const source = entry.source; if (source.path && (source.path.startsWith('asset.') || source.path.endsWith('nested.template.json'))) { assets.push(entry); } } else if (entry.type === 'docker-image') { const source = entry.source; if (source.directory && source.directory.startsWith('asset.')) { assets.push(entry); } } }); return assets; } /** * Clean the manifest of any unneccesary data. Currently that includes * the metadata trace information since this includes trace information like * file system locations and file lines that will change depending on what machine the test is run on */ cleanManifest() { const newManifest = { ...this.manifest, artifacts: this.renderArtifacts(), }; cloud_assembly_schema_1.Manifest.saveAssemblyManifest(newManifest, this.manifestFileName); } renderArtifactMetadata(artifact, trace) { const newMetadata = {}; if (!artifact.metadata) return artifact.metadata; for (const [metadataId, metadataEntry] of Object.entries(artifact.metadata ?? {})) { newMetadata[metadataId] = metadataEntry.map((meta) => { if (meta.type === 'aws:cdk:logicalId' && trace && meta.data) { const traceData = trace.get(meta.data.toString()); if (traceData) { trace.delete(meta.data.toString()); return { type: meta.type, data: meta.data, trace: [traceData], }; } } // return metadata without the trace data return { type: meta.type, data: meta.data, }; }); } if (trace && trace.size > 0) { for (const [id, data] of trace.entries()) { newMetadata[id] = [{ type: 'aws:cdk:logicalId', data: id, trace: [data], }]; } } return newMetadata; } renderArtifacts(trace) { const newArtifacts = {}; for (const [artifactId, artifact] of Object.entries(this.manifest.artifacts ?? {})) { let stackTrace = undefined; if (artifact.type === cloud_assembly_schema_1.ArtifactType.AWS_CLOUDFORMATION_STACK && trace) { stackTrace = trace.get(artifactId); } newArtifacts[artifactId] = { ...artifact, metadata: this.renderArtifactMetadata(artifact, stackTrace), }; } return newArtifacts; } } exports.AssemblyManifestReader = AssemblyManifestReader; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xvdWQtYXNzZW1ibHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJjbG91ZC1hc3NlbWJseS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2QkFBNkI7QUFFN0IsNERBQXdEO0FBQ3hELG9FQUE0RDtBQUU1RCwwRUFBbUc7QUFDbkcsK0JBQStCO0FBZS9COztHQUVHO0FBQ0gsTUFBYSxzQkFBc0I7SUFzQ2U7SUFBNkM7SUFyQ3RGLE1BQU0sQ0FBVSxnQkFBZ0IsR0FBRyxlQUFlLENBQUM7SUFFMUQ7O09BRUc7SUFDSSxNQUFNLENBQUMsUUFBUSxDQUFDLFFBQWdCO1FBQ3JDLElBQUksQ0FBQztZQUNILE1BQU0sR0FBRyxHQUFHLGdDQUFRLENBQUMsb0JBQW9CLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDcEQsT0FBTyxJQUFJLHNCQUFzQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEVBQUUsR0FBRyxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQzNFLENBQUM7UUFBQyxPQUFPLENBQU0sRUFBRSxDQUFDO1lBQ2hCLE1BQU0sSUFBSSxLQUFLLENBQUMsK0JBQStCLFFBQVEsTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUM1RSxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxNQUFNLENBQUMsUUFBUSxDQUFDLFFBQWdCO1FBQ3JDLElBQUksRUFBRSxDQUFDO1FBQ1AsSUFBSSxDQUFDO1lBQ0gsRUFBRSxHQUFHLEVBQUUsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDN0IsQ0FBQztRQUFDLE9BQU8sQ0FBTSxFQUFFLENBQUM7WUFDaEIsTUFBTSxJQUFJLEtBQUssQ0FBQyxrQ0FBa0MsUUFBUSxNQUFNLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1FBQy9FLENBQUM7UUFDRCxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDO1lBQ3JCLE9BQU8sc0JBQXNCLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLHNCQUFzQixDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQztRQUN2RyxDQUFDO1FBQ0QsT0FBTyxzQkFBc0IsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDbkQsQ0FBQztJQUVEOztPQUVHO0lBQ2EsU0FBUyxDQUFTO0lBRWxDLFlBQVksU0FBaUIsRUFBbUIsUUFBMEIsRUFBbUIsZ0JBQXdCO1FBQXJFLGFBQVEsR0FBUixRQUFRLENBQWtCO1FBQW1CLHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBUTtRQUNuSCxJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztJQUM3QixDQUFDO0lBRUQ7OztPQUdHO0lBQ0gsSUFBVyxNQUFNO1FBQ2YsTUFBTSxNQUFNLEdBQXdCLEVBQUUsQ0FBQztRQUN2QyxLQUFLLE1BQU0sQ0FBQyxVQUFVLEVBQUUsUUFBUSxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDO1lBQ25GLElBQUksUUFBUSxDQUFDLElBQUksS0FBSyxvQ0FBWSxDQUFDLHdCQUF3QixFQUFFLENBQUM7Z0JBQzVELFNBQVM7WUFDWCxDQUFDO1lBQ0QsTUFBTSxLQUFLLEdBQUcsUUFBUSxDQUFDLFVBQThDLENBQUM7WUFFdEUsTUFBTSxRQUFRLEdBQUcsRUFBRSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUM7WUFDbkYsTUFBTSxDQUFDLFVBQVUsQ0FBQyxHQUFHLFFBQVEsQ0FBQztRQUNoQyxDQUFDO1FBQ0QsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUVEOzs7T0FHRztJQUNJLHVCQUF1QixDQUFDLE9BQWU7UUFDNUMsTUFBTSxlQUFlLEdBQWEsSUFBSSxDQUFDLHlCQUF5QixDQUFDLE9BQU8sQ0FBQyxDQUFDLE9BQU8sQ0FDL0UsUUFBUSxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsS0FBSzthQUN2QixNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUMsdUJBQXVCLENBQUMsQ0FBQzthQUNyRSxHQUFHLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUssQ0FBQyxDQUNwQyxDQUFDO1FBRUYsTUFBTSxZQUFZLEdBQXdCLE1BQU0sQ0FBQyxXQUFXLENBQUMsZUFBZSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDaEcsWUFBWSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzdCLEVBQUUsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFlBQVksQ0FBQyxDQUFDO1NBQzVELENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFTCxPQUFPLFlBQVksQ0FBQztJQUN0QixDQUFDO0lBRUQ7O09BRUc7SUFDSSxXQUFXLENBQUMsS0FBb0I7UUFDckMsTUFBTSxXQUFXLEdBQUc7WUFDbEIsR0FBRyxJQUFJLENBQUMsUUFBUTtZQUNoQixTQUFTLEVBQUUsSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUM7U0FDdkMsQ0FBQztRQUNGLGdDQUFRLENBQUMsb0JBQW9CLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0lBQ3BFLENBQUM7SUFFRDs7T0FFRztJQUNJLG1CQUFtQixDQUFDLE9BQWU7UUFDeEMsTUFBTSxNQUFNLEdBQWEsRUFBRSxDQUFDO1FBQzVCLEtBQUssTUFBTSxRQUFRLElBQUksTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDO1lBQ3BFLElBQUksUUFBUSxDQUFDLElBQUksS0FBSyxvQ0FBWSxDQUFDLGNBQWMsSUFBSyxRQUFRLENBQUMsVUFBc0MsRUFBRSxJQUFJLEtBQUssR0FBRyxPQUFPLGNBQWMsRUFBRSxDQUFDO2dCQUN6SSxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLHVCQUF1QixDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztZQUN4RixDQUFDO2lCQUFNLElBQUksUUFBUSxDQUFDLElBQUksS0FBSyxvQ0FBWSxDQUFDLHdCQUF3QixFQUFFLENBQUM7Z0JBQ25FLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsMEJBQTBCLENBQUMsUUFBUSxDQUFDLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDbkYsQ0FBQztRQUNILENBQUM7UUFDRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0lBRUQ7O09BRUc7SUFDSSx5QkFBeUIsQ0FBQyxPQUFlO1FBQzlDLE1BQU0sTUFBTSxHQUFhLEVBQUUsQ0FBQztRQUM1QixLQUFLLE1BQU0sUUFBUSxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQztZQUNwRSxJQUFJLFFBQVEsQ0FBQyxJQUFJLEtBQUssb0NBQVksQ0FBQyxjQUFjLElBQUssUUFBUSxDQUFDLFVBQXNDLEVBQUUsSUFBSSxLQUFLLEdBQUcsT0FBTyxjQUFjLEVBQUUsQ0FBQztnQkFDekksTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxRQUFRLENBQUMsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUU7b0JBQ3BFLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxRQUFRLENBQUMsc0JBQXNCLENBQUMsRUFBRSxDQUFDO3dCQUNsRixPQUFPLEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSyxDQUFDO29CQUM1QixDQUFDO3lCQUFNLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxNQUFNLEVBQUUsQ0FBQzt3QkFDakMsT0FBTyxLQUFLLENBQUMsTUFBTSxDQUFDLFNBQVUsQ0FBQztvQkFDakMsQ0FBQztvQkFDRCxPQUFPLEVBQUUsQ0FBQztnQkFDWixDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ04sQ0FBQztpQkFBTSxJQUFJLFFBQVEsQ0FBQyxJQUFJLEtBQUssb0NBQVksQ0FBQyx3QkFBd0IsRUFBRSxDQUFDO2dCQUNuRSxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLDBCQUEwQixDQUFDLFFBQVEsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQ3JGLENBQUM7UUFDSCxDQUFDO1FBQ0QsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUVEOztPQUVHO0lBQ0kseUJBQXlCLENBQUMsT0FBZTtRQUM5QyxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLElBQUksRUFBRSxDQUFDO2FBQ2hELE1BQU0sQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUNqQixRQUFRLENBQUMsSUFBSSxLQUFLLG9DQUFZLENBQUMsY0FBYyxJQUFLLFFBQVEsQ0FBQyxVQUFzQyxFQUFFLElBQUksS0FBSyxHQUFHLE9BQU8sY0FBYyxDQUFDO2FBQ3RJLEdBQUcsQ0FBQyxRQUFRLENBQUMsRUFBRTtZQUNkLE1BQU0sUUFBUSxHQUFJLFFBQVEsQ0FBQyxVQUFzQyxDQUFDLElBQUksQ0FBQztZQUN2RSxPQUFPLDhCQUFhLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDO1FBQ3JFLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVEOztPQUVHO0lBQ0ssMEJBQTBCLENBQUMsUUFBMEI7UUFDM0QsTUFBTSxNQUFNLEdBQWtFLEVBQUUsQ0FBQztRQUNqRixLQUFLLE1BQU0sUUFBUSxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsa0NBQWEsQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDO1lBQ2pHLFFBQVEsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUU7Z0JBQ3RCLElBQUksSUFBSSxDQUFDLElBQUksS0FBSyxpREFBeUIsQ0FBQyxLQUFLLEVBQUUsQ0FBQztvQkFDbEQsTUFBTSxLQUFLLEdBQUksSUFBSSxDQUFDLElBQWtFLENBQUM7b0JBQ3ZGLElBQUksS0FBSyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQzt3QkFDcEMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztvQkFDckIsQ0FBQztnQkFDSCxDQUFDO1lBQ0gsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDO1FBQ0QsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUVEOztPQUVHO0lBQ0ssdUJBQXVCLENBQUMsUUFBMEI7UUFDeEQsTUFBTSxNQUFNLEdBQXFELEVBQUUsQ0FBQztRQUNwRSxNQUFNLFFBQVEsR0FBSSxRQUFRLENBQUMsVUFBc0MsQ0FBQyxJQUFJLENBQUM7UUFDdkUsTUFBTSxhQUFhLEdBQUcsOEJBQWEsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBQyxDQUFDLENBQUM7UUFDbEYsYUFBYSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUU7WUFDcEMsSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLE1BQU0sRUFBRSxDQUFDO2dCQUMxQixNQUFNLE1BQU0sR0FBSSxLQUEyQixDQUFDLE1BQU0sQ0FBQztnQkFDbkQsSUFBSSxNQUFNLENBQUMsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxFQUFFLENBQUM7b0JBQ3RHLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBMEIsQ0FBQyxDQUFDO2dCQUMxQyxDQUFDO1lBQ0gsQ0FBQztpQkFBTSxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssY0FBYyxFQUFFLENBQUM7Z0JBQ3pDLE1BQU0sTUFBTSxHQUFJLEtBQWtDLENBQUMsTUFBTSxDQUFDO2dCQUMxRCxJQUFJLE1BQU0sQ0FBQyxTQUFTLElBQUksTUFBTSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztvQkFDOUQsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFpQyxDQUFDLENBQUM7Z0JBQ2pELENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7UUFDSCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLGFBQWE7UUFDbEIsTUFBTSxXQUFXLEdBQUc7WUFDbEIsR0FBRyxJQUFJLENBQUMsUUFBUTtZQUNoQixTQUFTLEVBQUUsSUFBSSxDQUFDLGVBQWUsRUFBRTtTQUNsQyxDQUFDO1FBQ0YsZ0NBQVEsQ0FBQyxvQkFBb0IsQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDcEUsQ0FBQztJQUVPLHNCQUFzQixDQUFDLFFBQTBCLEVBQUUsS0FBa0I7UUFDM0UsTUFBTSxXQUFXLEdBQXNDLEVBQUUsQ0FBQztRQUMxRCxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVE7WUFBRSxPQUFPLFFBQVEsQ0FBQyxRQUFRLENBQUM7UUFDakQsS0FBSyxNQUFNLENBQUMsVUFBVSxFQUFFLGFBQWEsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLFFBQVEsSUFBSSxFQUFFLENBQUMsRUFBRSxDQUFDO1lBQ2xGLFdBQVcsQ0FBQyxVQUFVLENBQUMsR0FBRyxhQUFhLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBbUIsRUFBRSxFQUFFO2dCQUNsRSxJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssbUJBQW1CLElBQUksS0FBSyxJQUFJLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztvQkFDNUQsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7b0JBQ2xELElBQUksU0FBUyxFQUFFLENBQUM7d0JBQ2QsS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7d0JBQ25DLE9BQU87NEJBQ0wsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJOzRCQUNmLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSTs0QkFDZixLQUFLLEVBQUUsQ0FBQyxTQUFTLENBQUM7eUJBQ25CLENBQUM7b0JBQ0osQ0FBQztnQkFDSCxDQUFDO2dCQUNELHlDQUF5QztnQkFDekMsT0FBTztvQkFDTCxJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUk7b0JBQ2YsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJO2lCQUNoQixDQUFDO1lBQ0osQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDO1FBQ0QsSUFBSSxLQUFLLElBQUksS0FBSyxDQUFDLElBQUksR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUM1QixLQUFLLE1BQU0sQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLElBQUksS0FBSyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUM7Z0JBQ3pDLFdBQVcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDO3dCQUNqQixJQUFJLEVBQUUsbUJBQW1CO3dCQUN6QixJQUFJLEVBQUUsRUFBRTt3QkFDUixLQUFLLEVBQUUsQ0FBQyxJQUFJLENBQUM7cUJBQ2QsQ0FBQyxDQUFDO1lBQ0wsQ0FBQztRQUNILENBQUM7UUFDRCxPQUFPLFdBQVcsQ0FBQztJQUNyQixDQUFDO0lBRU8sZUFBZSxDQUFDLEtBQXFCO1FBQzNDLE1BQU0sWUFBWSxHQUF1QyxFQUFFLENBQUM7UUFDNUQsS0FBSyxNQUFNLENBQUMsVUFBVSxFQUFFLFFBQVEsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQztZQUNuRixJQUFJLFVBQVUsR0FBMkIsU0FBUyxDQUFDO1lBQ25ELElBQUksUUFBUSxDQUFDLElBQUksS0FBSyxvQ0FBWSxDQUFDLHdCQUF3QixJQUFJLEtBQUssRUFBRSxDQUFDO2dCQUNyRSxVQUFVLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUNyQyxDQUFDO1lBQ0QsWUFBWSxDQUFDLFVBQVUsQ0FBQyxHQUFHO2dCQUN6QixHQUFHLFFBQVE7Z0JBQ1gsUUFBUSxFQUFFLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxRQUFRLEVBQUUsVUFBVSxDQUFDO2FBQzVELENBQUM7UUFDSixDQUFDO1FBQ0QsT0FBTyxZQUFZLENBQUM7SUFDdEIsQ0FBQzs7QUFsUEgsd0RBbVBDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB0eXBlIHsgRmlsZU1hbmlmZXN0RW50cnksIERvY2tlckltYWdlTWFuaWZlc3RFbnRyeSB9IGZyb20gJ0Bhd3MtY2RrL2Nkay1hc3NldHMtbGliJztcbmltcG9ydCB7IEFzc2V0TWFuaWZlc3QgfSBmcm9tICdAYXdzLWNkay9jZGstYXNzZXRzLWxpYic7XG5pbXBvcnQgeyBDbG91ZEFydGlmYWN0IH0gZnJvbSAnQGF3cy1jZGsvY2xvdWQtYXNzZW1ibHktYXBpJztcbmltcG9ydCB0eXBlIHsgQXNzZW1ibHlNYW5pZmVzdCwgQXdzQ2xvdWRGb3JtYXRpb25TdGFja1Byb3BlcnRpZXMsIEFydGlmYWN0TWFuaWZlc3QsIE1ldGFkYXRhRW50cnksIEFzc2V0TWFuaWZlc3RQcm9wZXJ0aWVzLCBDb250YWluZXJJbWFnZUFzc2V0TWV0YWRhdGFFbnRyeSwgRmlsZUFzc2V0TWV0YWRhdGFFbnRyeSB9IGZyb20gJ0Bhd3MtY2RrL2Nsb3VkLWFzc2VtYmx5LXNjaGVtYSc7XG5pbXBvcnQgeyBNYW5pZmVzdCwgQXJ0aWZhY3RUeXBlLCBBcnRpZmFjdE1ldGFkYXRhRW50cnlUeXBlIH0gZnJvbSAnQGF3cy1jZGsvY2xvdWQtYXNzZW1ibHktc2NoZW1hJztcbmltcG9ydCAqIGFzIGZzIGZyb20gJ2ZzLWV4dHJhJztcblxuLyoqXG4gKiBUcmFjZSBpbmZvcm1hdGlvbiBmb3Igc3RhY2tcbiAqIG1hcCBvZiByZXNvdXJjZSBsb2dpY2FsSWQgdG8gdHJhY2UgbWVzc2FnZVxuICovXG5leHBvcnQgdHlwZSBTdGFja1RyYWNlID0gTWFwPHN0cmluZywgc3RyaW5nPjtcblxuLyoqXG4gKiBUcmFjZSBpbmZvcm1hdGlvbiBmb3IgYSBhc3NlbWJseVxuICpcbiAqIG1hcCBvZiBzdGFja0lkIHRvIFN0YWNrVHJhY2VcbiAqL1xuZXhwb3J0IHR5cGUgTWFuaWZlc3RUcmFjZSA9IE1hcDxzdHJpbmcsIFN0YWNrVHJhY2U+O1xuXG4vKipcbiAqIFJlYWRzIGEgQ2xvdWQgQXNzZW1ibHkgbWFuaWZlc3RcbiAqL1xuZXhwb3J0IGNsYXNzIEFzc2VtYmx5TWFuaWZlc3RSZWFkZXIge1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IERFRkFVTFRfRklMRU5BTUUgPSAnbWFuaWZlc3QuanNvbic7XG5cbiAgLyoqXG4gICAqIFJlYWRzIGEgQ2xvdWQgQXNzZW1ibHkgbWFuaWZlc3QgZnJvbSBhIGZpbGVcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbUZpbGUoZmlsZU5hbWU6IHN0cmluZyk6IEFzc2VtYmx5TWFuaWZlc3RSZWFkZXIge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBvYmogPSBNYW5pZmVzdC5sb2FkQXNzZW1ibHlNYW5pZmVzdChmaWxlTmFtZSk7XG4gICAgICByZXR1cm4gbmV3IEFzc2VtYmx5TWFuaWZlc3RSZWFkZXIocGF0aC5kaXJuYW1lKGZpbGVOYW1lKSwgb2JqLCBmaWxlTmFtZSk7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZWFkIGludGVnIG1hbmlmZXN0ICcke2ZpbGVOYW1lfSc6ICR7ZS5tZXNzYWdlfWApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZWFkcyBhIENsb3VkIEFzc2VtYmx5IG1hbmlmZXN0IGZyb20gYSBmaWxlIG9yIGEgZGlyZWN0b3J5XG4gICAqIElmIHRoZSBnaXZlbiBmaWxlUGF0aCBpcyBhIGRpcmVjdG9yeSB0aGVuIGl0IHdpbGwgbG9vayBmb3JcbiAgICogYSBmaWxlIHdpdGhpbiB0aGUgZGlyZWN0b3J5IHdpdGggdGhlIERFRkFVTFRfRklMRU5BTUVcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbVBhdGgoZmlsZVBhdGg6IHN0cmluZyk6IEFzc2VtYmx5TWFuaWZlc3RSZWFkZXIge1xuICAgIGxldCBzdDtcbiAgICB0cnkge1xuICAgICAgc3QgPSBmcy5zdGF0U3luYyhmaWxlUGF0aCk7XG4gICAgfSBjYXRjaCAoZTogYW55KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZWFkIGludGVnIG1hbmlmZXN0IGF0ICcke2ZpbGVQYXRofSc6ICR7ZS5tZXNzYWdlfWApO1xuICAgIH1cbiAgICBpZiAoc3QuaXNEaXJlY3RvcnkoKSkge1xuICAgICAgcmV0dXJuIEFzc2VtYmx5TWFuaWZlc3RSZWFkZXIuZnJvbUZpbGUocGF0aC5qb2luKGZpbGVQYXRoLCBBc3NlbWJseU1hbmlmZXN0UmVhZGVyLkRFRkFVTFRfRklMRU5BTUUpKTtcbiAgICB9XG4gICAgcmV0dXJuIEFzc2VtYmx5TWFuaWZlc3RSZWFkZXIuZnJvbUZpbGUoZmlsZVBhdGgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBkaXJlY3Rvcnkgd2hlcmUgdGhlIG1hbmlmZXN0IHdhcyBmb3VuZFxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGRpcmVjdG9yeTogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKGRpcmVjdG9yeTogc3RyaW5nLCBwcml2YXRlIHJlYWRvbmx5IG1hbmlmZXN0OiBBc3NlbWJseU1hbmlmZXN0LCBwcml2YXRlIHJlYWRvbmx5IG1hbmlmZXN0RmlsZU5hbWU6IHN0cmluZykge1xuICAgIHRoaXMuZGlyZWN0b3J5ID0gZGlyZWN0b3J5O1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgc3RhY2tzIGZyb20gdGhlIG1hbmlmZXN0XG4gICAqIHJldHVybnMgYSBtYXAgb2YgYXJ0aWZhY3RJZCB0byBDbG91ZEZvcm1hdGlvbiB0ZW1wbGF0ZVxuICAgKi9cbiAgcHVibGljIGdldCBzdGFja3MoKTogUmVjb3JkPHN0cmluZywgYW55PiB7XG4gICAgY29uc3Qgc3RhY2tzOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge307XG4gICAgZm9yIChjb25zdCBbYXJ0aWZhY3RJZCwgYXJ0aWZhY3RdIG9mIE9iamVjdC5lbnRyaWVzKHRoaXMubWFuaWZlc3QuYXJ0aWZhY3RzID8/IHt9KSkge1xuICAgICAgaWYgKGFydGlmYWN0LnR5cGUgIT09IEFydGlmYWN0VHlwZS5BV1NfQ0xPVURGT1JNQVRJT05fU1RBQ0spIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBjb25zdCBwcm9wcyA9IGFydGlmYWN0LnByb3BlcnRpZXMgYXMgQXdzQ2xvdWRGb3JtYXRpb25TdGFja1Byb3BlcnRpZXM7XG5cbiAgICAgIGNvbnN0IHRlbXBsYXRlID0gZnMucmVhZEpTT05TeW5jKHBhdGgucmVzb2x2ZSh0aGlzLmRpcmVjdG9yeSwgcHJvcHMudGVtcGxhdGVGaWxlKSk7XG4gICAgICBzdGFja3NbYXJ0aWZhY3RJZF0gPSB0ZW1wbGF0ZTtcbiAgICB9XG4gICAgcmV0dXJuIHN0YWNrcztcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIG5lc3RlZCBzdGFja3MgZm9yIGEgZ2l2ZW4gc3RhY2tcbiAgICogcmV0dXJucyBhIG1hcCBvZiBhcnRpZmFjdElkIHRvIENsb3VkRm9ybWF0aW9uIHRlbXBsYXRlXG4gICAqL1xuICBwdWJsaWMgZ2V0TmVzdGVkU3RhY2tzRm9yU3RhY2soc3RhY2tJZDogc3RyaW5nKTogUmVjb3JkPHN0cmluZywgYW55PiB7XG4gICAgY29uc3QgbmVzdGVkVGVtcGxhdGVzOiBzdHJpbmdbXSA9IHRoaXMuZ2V0QXNzZXRNYW5pZmVzdHNGb3JTdGFjayhzdGFja0lkKS5mbGF0TWFwKFxuICAgICAgbWFuaWZlc3QgPT4gbWFuaWZlc3QuZmlsZXNcbiAgICAgICAgLmZpbHRlcihhc3NldCA9PiBhc3NldC5zb3VyY2UucGF0aD8uZW5kc1dpdGgoJy5uZXN0ZWQudGVtcGxhdGUuanNvbicpKVxuICAgICAgICAubWFwKGFzc2V0ID0+IGFzc2V0LnNvdXJjZS5wYXRoISksXG4gICAgKTtcblxuICAgIGNvbnN0IG5lc3RlZFN0YWNrczogUmVjb3JkPHN0cmluZywgYW55PiA9IE9iamVjdC5mcm9tRW50cmllcyhuZXN0ZWRUZW1wbGF0ZXMubWFwKHRlbXBsYXRlRmlsZSA9PiAoW1xuICAgICAgdGVtcGxhdGVGaWxlLnNwbGl0KCcuJywgMSlbMF0sXG4gICAgICBmcy5yZWFkSlNPTlN5bmMocGF0aC5yZXNvbHZlKHRoaXMuZGlyZWN0b3J5LCB0ZW1wbGF0ZUZpbGUpKSxcbiAgICBdKSkpO1xuXG4gICAgcmV0dXJuIG5lc3RlZFN0YWNrcztcbiAgfVxuXG4gIC8qKlxuICAgKiBXcml0ZSB0cmFjZSBkYXRhIHRvIHRoZSBhc3NlbWJseSBtYW5pZmVzdCBtZXRhZGF0YVxuICAgKi9cbiAgcHVibGljIHJlY29yZFRyYWNlKHRyYWNlOiBNYW5pZmVzdFRyYWNlKTogdm9pZCB7XG4gICAgY29uc3QgbmV3TWFuaWZlc3QgPSB7XG4gICAgICAuLi50aGlzLm1hbmlmZXN0LFxuICAgICAgYXJ0aWZhY3RzOiB0aGlzLnJlbmRlckFydGlmYWN0cyh0cmFjZSksXG4gICAgfTtcbiAgICBNYW5pZmVzdC5zYXZlQXNzZW1ibHlNYW5pZmVzdChuZXdNYW5pZmVzdCwgdGhpcy5tYW5pZmVzdEZpbGVOYW1lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYSBsaXN0IG9mIGFzc2V0cyBmb3IgYSBnaXZlbiBzdGFja1xuICAgKi9cbiAgcHVibGljIGdldEFzc2V0SWRzRm9yU3RhY2soc3RhY2tJZDogc3RyaW5nKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IGFzc2V0czogc3RyaW5nW10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IGFydGlmYWN0IG9mIE9iamVjdC52YWx1ZXModGhpcy5tYW5pZmVzdC5hcnRpZmFjdHMgPz8ge30pKSB7XG4gICAgICBpZiAoYXJ0aWZhY3QudHlwZSA9PT0gQXJ0aWZhY3RUeXBlLkFTU0VUX01BTklGRVNUICYmIChhcnRpZmFjdC5wcm9wZXJ0aWVzIGFzIEFzc2V0TWFuaWZlc3RQcm9wZXJ0aWVzKT8uZmlsZSA9PT0gYCR7c3RhY2tJZH0uYXNzZXRzLmpzb25gKSB7XG4gICAgICAgIGFzc2V0cy5wdXNoKC4uLnRoaXMuYXNzZXRzRnJvbUFzc2V0TWFuaWZlc3QoYXJ0aWZhY3QpLm1hcChhc3NldCA9PiBhc3NldC5pZC5hc3NldElkKSk7XG4gICAgICB9IGVsc2UgaWYgKGFydGlmYWN0LnR5cGUgPT09IEFydGlmYWN0VHlwZS5BV1NfQ0xPVURGT1JNQVRJT05fU1RBQ0spIHtcbiAgICAgICAgYXNzZXRzLnB1c2goLi4udGhpcy5hc3NldHNGcm9tQXNzZW1ibHlNYW5pZmVzdChhcnRpZmFjdCkubWFwKGFzc2V0ID0+IGFzc2V0LmlkKSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBhc3NldHM7XG4gIH1cblxuICAvKipcbiAgICogRm9yIGEgZ2l2ZW4gc3RhY2tJZCByZXR1cm4gYSBsaXN0IG9mIGFzc2V0cyB0aGF0IGJlbG9uZyB0byB0aGUgc3RhY2tcbiAgICovXG4gIHB1YmxpYyBnZXRBc3NldExvY2F0aW9uc0ZvclN0YWNrKHN0YWNrSWQ6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCBhc3NldHM6IHN0cmluZ1tdID0gW107XG4gICAgZm9yIChjb25zdCBhcnRpZmFjdCBvZiBPYmplY3QudmFsdWVzKHRoaXMubWFuaWZlc3QuYXJ0aWZhY3RzID8/IHt9KSkge1xuICAgICAgaWYgKGFydGlmYWN0LnR5cGUgPT09IEFydGlmYWN0VHlwZS5BU1NFVF9NQU5JRkVTVCAmJiAoYXJ0aWZhY3QucHJvcGVydGllcyBhcyBBc3NldE1hbmlmZXN0UHJvcGVydGllcyk/LmZpbGUgPT09IGAke3N0YWNrSWR9LmFzc2V0cy5qc29uYCkge1xuICAgICAgICBhc3NldHMucHVzaCguLi50aGlzLmFzc2V0c0Zyb21Bc3NldE1hbmlmZXN0KGFydGlmYWN0KS5mbGF0TWFwKGFzc2V0ID0+IHtcbiAgICAgICAgICBpZiAoYXNzZXQudHlwZSA9PT0gJ2ZpbGUnICYmICFhc3NldC5zb3VyY2UucGF0aD8uZW5kc1dpdGgoJ25lc3RlZC50ZW1wbGF0ZS5qc29uJykpIHtcbiAgICAgICAgICAgIHJldHVybiBhc3NldC5zb3VyY2UucGF0aCE7XG4gICAgICAgICAgfSBlbHNlIGlmIChhc3NldC50eXBlICE9PSAnZmlsZScpIHtcbiAgICAgICAgICAgIHJldHVybiBhc3NldC5zb3VyY2UuZGlyZWN0b3J5ITtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9KSk7XG4gICAgICB9IGVsc2UgaWYgKGFydGlmYWN0LnR5cGUgPT09IEFydGlmYWN0VHlwZS5BV1NfQ0xPVURGT1JNQVRJT05fU1RBQ0spIHtcbiAgICAgICAgYXNzZXRzLnB1c2goLi4udGhpcy5hc3NldHNGcm9tQXNzZW1ibHlNYW5pZmVzdChhcnRpZmFjdCkubWFwKGFzc2V0ID0+IGFzc2V0LnBhdGgpKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGFzc2V0cztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYSBsaXN0IG9mIGFzc2V0IGFydGlmYWN0cyBmb3IgYSBnaXZlbiBzdGFja1xuICAgKi9cbiAgcHVibGljIGdldEFzc2V0TWFuaWZlc3RzRm9yU3RhY2soc3RhY2tJZDogc3RyaW5nKTogQXNzZXRNYW5pZmVzdFtdIHtcbiAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyh0aGlzLm1hbmlmZXN0LmFydGlmYWN0cyA/PyB7fSlcbiAgICAgIC5maWx0ZXIoYXJ0aWZhY3QgPT5cbiAgICAgICAgYXJ0aWZhY3QudHlwZSA9PT0gQXJ0aWZhY3RUeXBlLkFTU0VUX01BTklGRVNUICYmIChhcnRpZmFjdC5wcm9wZXJ0aWVzIGFzIEFzc2V0TWFuaWZlc3RQcm9wZXJ0aWVzKT8uZmlsZSA9PT0gYCR7c3RhY2tJZH0uYXNzZXRzLmpzb25gKVxuICAgICAgLm1hcChhcnRpZmFjdCA9PiB7XG4gICAgICAgIGNvbnN0IGZpbGVOYW1lID0gKGFydGlmYWN0LnByb3BlcnRpZXMgYXMgQXNzZXRNYW5pZmVzdFByb3BlcnRpZXMpLmZpbGU7XG4gICAgICAgIHJldHVybiBBc3NldE1hbmlmZXN0LmZyb21GaWxlKHBhdGguam9pbih0aGlzLmRpcmVjdG9yeSwgZmlsZU5hbWUpKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhIGxpc3Qgb2YgYXNzZXRzIGZyb20gdGhlIGFzc2VtYmx5IG1hbmlmZXN0XG4gICAqL1xuICBwcml2YXRlIGFzc2V0c0Zyb21Bc3NlbWJseU1hbmlmZXN0KGFydGlmYWN0OiBBcnRpZmFjdE1hbmlmZXN0KTogKENvbnRhaW5lckltYWdlQXNzZXRNZXRhZGF0YUVudHJ5IHwgRmlsZUFzc2V0TWV0YWRhdGFFbnRyeSlbXSB7XG4gICAgY29uc3QgYXNzZXRzOiAoQ29udGFpbmVySW1hZ2VBc3NldE1ldGFkYXRhRW50cnkgfCBGaWxlQXNzZXRNZXRhZGF0YUVudHJ5KVtdID0gW107XG4gICAgZm9yIChjb25zdCBtZXRhZGF0YSBvZiBPYmplY3QudmFsdWVzKENsb3VkQXJ0aWZhY3QucmVhZE1ldGFkYXRhKHRoaXMuZGlyZWN0b3J5LCBhcnRpZmFjdCkgPz8ge30pKSB7XG4gICAgICBtZXRhZGF0YS5mb3JFYWNoKGRhdGEgPT4ge1xuICAgICAgICBpZiAoZGF0YS50eXBlID09PSBBcnRpZmFjdE1ldGFkYXRhRW50cnlUeXBlLkFTU0VUKSB7XG4gICAgICAgICAgY29uc3QgYXNzZXQgPSAoZGF0YS5kYXRhIGFzIENvbnRhaW5lckltYWdlQXNzZXRNZXRhZGF0YUVudHJ5IHwgRmlsZUFzc2V0TWV0YWRhdGFFbnRyeSk7XG4gICAgICAgICAgaWYgKGFzc2V0LnBhdGguc3RhcnRzV2l0aCgnYXNzZXQuJykpIHtcbiAgICAgICAgICAgIGFzc2V0cy5wdXNoKGFzc2V0KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gYXNzZXRzO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhIGxpc3Qgb2YgYXNzZXRzIGZyb20gdGhlIGFzc2V0IG1hbmlmZXN0XG4gICAqL1xuICBwcml2YXRlIGFzc2V0c0Zyb21Bc3NldE1hbmlmZXN0KGFydGlmYWN0OiBBcnRpZmFjdE1hbmlmZXN0KTogKEZpbGVNYW5pZmVzdEVudHJ5IHwgRG9ja2VySW1hZ2VNYW5pZmVzdEVudHJ5KVtdIHtcbiAgICBjb25zdCBhc3NldHM6IChGaWxlTWFuaWZlc3RFbnRyeSB8IERvY2tlckltYWdlTWFuaWZlc3RFbnRyeSlbXSA9IFtdO1xuICAgIGNvbnN0IGZpbGVOYW1lID0gKGFydGlmYWN0LnByb3BlcnRpZXMgYXMgQXNzZXRNYW5pZmVzdFByb3BlcnRpZXMpLmZpbGU7XG4gICAgY29uc3QgYXNzZXRNYW5pZmVzdCA9IEFzc2V0TWFuaWZlc3QuZnJvbUZpbGUocGF0aC5qb2luKHRoaXMuZGlyZWN0b3J5LCBmaWxlTmFtZSkpO1xuICAgIGFzc2V0TWFuaWZlc3QuZW50cmllcy5mb3JFYWNoKGVudHJ5ID0+IHtcbiAgICAgIGlmIChlbnRyeS50eXBlID09PSAnZmlsZScpIHtcbiAgICAgICAgY29uc3Qgc291cmNlID0gKGVudHJ5IGFzIEZpbGVNYW5pZmVzdEVudHJ5KS5zb3VyY2U7XG4gICAgICAgIGlmIChzb3VyY2UucGF0aCAmJiAoc291cmNlLnBhdGguc3RhcnRzV2l0aCgnYXNzZXQuJykgfHwgc291cmNlLnBhdGguZW5kc1dpdGgoJ25lc3RlZC50ZW1wbGF0ZS5qc29uJykpKSB7XG4gICAgICAgICAgYXNzZXRzLnB1c2goZW50cnkgYXMgRmlsZU1hbmlmZXN0RW50cnkpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGVudHJ5LnR5cGUgPT09ICdkb2NrZXItaW1hZ2UnKSB7XG4gICAgICAgIGNvbnN0IHNvdXJjZSA9IChlbnRyeSBhcyBEb2NrZXJJbWFnZU1hbmlmZXN0RW50cnkpLnNvdXJjZTtcbiAgICAgICAgaWYgKHNvdXJjZS5kaXJlY3RvcnkgJiYgc291cmNlLmRpcmVjdG9yeS5zdGFydHNXaXRoKCdhc3NldC4nKSkge1xuICAgICAgICAgIGFzc2V0cy5wdXNoKGVudHJ5IGFzIERvY2tlckltYWdlTWFuaWZlc3RFbnRyeSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gYXNzZXRzO1xuICB9XG5cbiAgLyoqXG4gICAqIENsZWFuIHRoZSBtYW5pZmVzdCBvZiBhbnkgdW5uZWNjZXNhcnkgZGF0YS4gQ3VycmVudGx5IHRoYXQgaW5jbHVkZXNcbiAgICogdGhlIG1ldGFkYXRhIHRyYWNlIGluZm9ybWF0aW9uIHNpbmNlIHRoaXMgaW5jbHVkZXMgdHJhY2UgaW5mb3JtYXRpb24gbGlrZVxuICAgKiBmaWxlIHN5c3RlbSBsb2NhdGlvbnMgYW5kIGZpbGUgbGluZXMgdGhhdCB3aWxsIGNoYW5nZSBkZXBlbmRpbmcgb24gd2hhdCBtYWNoaW5lIHRoZSB0ZXN0IGlzIHJ1biBvblxuICAgKi9cbiAgcHVibGljIGNsZWFuTWFuaWZlc3QoKTogdm9pZCB7XG4gICAgY29uc3QgbmV3TWFuaWZlc3QgPSB7XG4gICAgICAuLi50aGlzLm1hbmlmZXN0LFxuICAgICAgYXJ0aWZhY3RzOiB0aGlzLnJlbmRlckFydGlmYWN0cygpLFxuICAgIH07XG4gICAgTWFuaWZlc3Quc2F2ZUFzc2VtYmx5TWFuaWZlc3QobmV3TWFuaWZlc3QsIHRoaXMubWFuaWZlc3RGaWxlTmFtZSk7XG4gIH1cblxuICBwcml2YXRlIHJlbmRlckFydGlmYWN0TWV0YWRhdGEoYXJ0aWZhY3Q6IEFydGlmYWN0TWFuaWZlc3QsIHRyYWNlPzogU3RhY2tUcmFjZSk6IHsgW2lkOiBzdHJpbmddOiBNZXRhZGF0YUVudHJ5W10gfSB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgbmV3TWV0YWRhdGE6IHsgW2lkOiBzdHJpbmddOiBNZXRhZGF0YUVudHJ5W10gfSA9IHt9O1xuICAgIGlmICghYXJ0aWZhY3QubWV0YWRhdGEpIHJldHVybiBhcnRpZmFjdC5tZXRhZGF0YTtcbiAgICBmb3IgKGNvbnN0IFttZXRhZGF0YUlkLCBtZXRhZGF0YUVudHJ5XSBvZiBPYmplY3QuZW50cmllcyhhcnRpZmFjdC5tZXRhZGF0YSA/PyB7fSkpIHtcbiAgICAgIG5ld01ldGFkYXRhW21ldGFkYXRhSWRdID0gbWV0YWRhdGFFbnRyeS5tYXAoKG1ldGE6IE1ldGFkYXRhRW50cnkpID0+IHtcbiAgICAgICAgaWYgKG1ldGEudHlwZSA9PT0gJ2F3czpjZGs6bG9naWNhbElkJyAmJiB0cmFjZSAmJiBtZXRhLmRhdGEpIHtcbiAgICAgICAgICBjb25zdCB0cmFjZURhdGEgPSB0cmFjZS5nZXQobWV0YS5kYXRhLnRvU3RyaW5nKCkpO1xuICAgICAgICAgIGlmICh0cmFjZURhdGEpIHtcbiAgICAgICAgICAgIHRyYWNlLmRlbGV0ZShtZXRhLmRhdGEudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICB0eXBlOiBtZXRhLnR5cGUsXG4gICAgICAgICAgICAgIGRhdGE6IG1ldGEuZGF0YSxcbiAgICAgICAgICAgICAgdHJhY2U6IFt0cmFjZURhdGFdLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gcmV0dXJuIG1ldGFkYXRhIHdpdGhvdXQgdGhlIHRyYWNlIGRhdGFcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB0eXBlOiBtZXRhLnR5cGUsXG4gICAgICAgICAgZGF0YTogbWV0YS5kYXRhLFxuICAgICAgICB9O1xuICAgICAgfSk7XG4gICAgfVxuICAgIGlmICh0cmFjZSAmJiB0cmFjZS5zaXplID4gMCkge1xuICAgICAgZm9yIChjb25zdCBbaWQsIGRhdGFdIG9mIHRyYWNlLmVudHJpZXMoKSkge1xuICAgICAgICBuZXdNZXRhZGF0YVtpZF0gPSBbe1xuICAgICAgICAgIHR5cGU6ICdhd3M6Y2RrOmxvZ2ljYWxJZCcsXG4gICAgICAgICAgZGF0YTogaWQsXG4gICAgICAgICAgdHJhY2U6IFtkYXRhXSxcbiAgICAgICAgfV07XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBuZXdNZXRhZGF0YTtcbiAgfVxuXG4gIHByaXZhdGUgcmVuZGVyQXJ0aWZhY3RzKHRyYWNlPzogTWFuaWZlc3RUcmFjZSk6IHsgW2lkOiBzdHJpbmddOiBBcnRpZmFjdE1hbmlmZXN0IH0gfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IG5ld0FydGlmYWN0czogeyBbaWQ6IHN0cmluZ106IEFydGlmYWN0TWFuaWZlc3QgfSA9IHt9O1xuICAgIGZvciAoY29uc3QgW2FydGlmYWN0SWQsIGFydGlmYWN0XSBvZiBPYmplY3QuZW50cmllcyh0aGlzLm1hbmlmZXN0LmFydGlmYWN0cyA/PyB7fSkpIHtcbiAgICAgIGxldCBzdGFja1RyYWNlOiBTdGFja1RyYWNlIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuICAgICAgaWYgKGFydGlmYWN0LnR5cGUgPT09IEFydGlmYWN0VHlwZS5BV1NfQ0xPVURGT1JNQVRJT05fU1RBQ0sgJiYgdHJhY2UpIHtcbiAgICAgICAgc3RhY2tUcmFjZSA9IHRyYWNlLmdldChhcnRpZmFjdElkKTtcbiAgICAgIH1cbiAgICAgIG5ld0FydGlmYWN0c1thcnRpZmFjdElkXSA9IHtcbiAgICAgICAgLi4uYXJ0aWZhY3QsXG4gICAgICAgIG1ldGFkYXRhOiB0aGlzLnJlbmRlckFydGlmYWN0TWV0YWRhdGEoYXJ0aWZhY3QsIHN0YWNrVHJhY2UpLFxuICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIG5ld0FydGlmYWN0cztcbiAgfVxufVxuIl19