UNPKG

@aws-cdk/cx-api

Version:

Cloud executable protocol

354 lines 47 kB
"use strict"; var _a, _b; Object.defineProperty(exports, "__esModule", { value: true }); exports.CloudAssemblyBuilder = exports.CloudAssembly = void 0; const jsiiDeprecationWarnings = require("../.warnings.jsii.js"); const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const fs = require("fs"); const os = require("os"); const path = require("path"); const cloudformation_artifact_1 = require("./artifacts/cloudformation-artifact"); const nested_cloud_assembly_artifact_1 = require("./artifacts/nested-cloud-assembly-artifact"); const tree_cloud_artifact_1 = require("./artifacts/tree-cloud-artifact"); const cloud_artifact_1 = require("./cloud-artifact"); const toposort_1 = require("./toposort"); const cxschema = require("@aws-cdk/cloud-assembly-schema"); const error_1 = require("./private/error"); const CLOUD_ASSEMBLY_SYMBOL = Symbol.for('@aws-cdk/cx-api.CloudAssembly'); /** * The name of the root manifest file of the assembly. */ const MANIFEST_FILE = 'manifest.json'; /** * Represents a deployable cloud application. */ class CloudAssembly { /** * Return whether the given object is a CloudAssembly. * * We do attribute detection since we can't reliably use 'instanceof'. */ static isCloudAssembly(x) { return x !== null && typeof (x) === 'object' && CLOUD_ASSEMBLY_SYMBOL in x; } /** * Reads a cloud assembly from the specified directory. * @param directory The root directory of the assembly. */ constructor(directory, loadOptions) { this.directory = directory; this.manifest = cxschema.Manifest.loadAssemblyManifest(path.join(directory, MANIFEST_FILE), loadOptions); this.version = this.manifest.version; this.artifacts = this.renderArtifacts(loadOptions?.topoSort ?? true); this.runtime = this.manifest.runtime || { libraries: {} }; Object.defineProperty(this, CLOUD_ASSEMBLY_SYMBOL, { value: true }); // force validation of deps by accessing 'depends' on all artifacts this.validateDeps(); } /** * Attempts to find an artifact with a specific identity. * @returns A `CloudArtifact` object or `undefined` if the artifact does not exist in this assembly. * @param id The artifact ID */ tryGetArtifact(id) { return this.artifacts.find(a => a.id === id); } /** * Returns a CloudFormation stack artifact from this assembly. * * Will only search the current assembly. * * @param stackName the name of the CloudFormation stack. * @throws if there is no stack artifact by that name * @throws if there is more than one stack with the same stack name. You can * use `getStackArtifact(stack.artifactId)` instead. * @returns a `CloudFormationStackArtifact` object. */ getStackByName(stackName) { const artifacts = this.artifacts.filter(a => a instanceof cloudformation_artifact_1.CloudFormationStackArtifact && a.stackName === stackName); if (!artifacts || artifacts.length === 0) { throw new error_1.CloudAssemblyError(`Unable to find stack with stack name "${stackName}"`); } if (artifacts.length > 1) { // eslint-disable-next-line max-len throw new error_1.CloudAssemblyError(`There are multiple stacks with the stack name "${stackName}" (${artifacts.map(a => a.id).join(',')}). Use "getStackArtifact(id)" instead`); } return artifacts[0]; } /** * Returns a CloudFormation stack artifact by name from this assembly. * @deprecated renamed to `getStackByName` (or `getStackArtifact(id)`) */ getStack(stackName) { try { jsiiDeprecationWarnings.print("@aws-cdk/cx-api.CloudAssembly#getStack", "renamed to `getStackByName` (or `getStackArtifact(id)`)"); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.getStack); } throw error; } return this.getStackByName(stackName); } /** * Returns a CloudFormation stack artifact from this assembly. * * @param artifactId the artifact id of the stack (can be obtained through `stack.artifactId`). * @throws if there is no stack artifact with that id * @returns a `CloudFormationStackArtifact` object. */ getStackArtifact(artifactId) { const artifact = this.tryGetArtifactRecursively(artifactId); if (!artifact) { throw new error_1.CloudAssemblyError(`Unable to find artifact with id "${artifactId}"`); } if (!(artifact instanceof cloudformation_artifact_1.CloudFormationStackArtifact)) { throw new error_1.CloudAssemblyError(`Artifact ${artifactId} is not a CloudFormation stack`); } return artifact; } tryGetArtifactRecursively(artifactId) { return this.stacksRecursively.find(a => a.id === artifactId); } /** * Returns all the stacks, including the ones in nested assemblies */ get stacksRecursively() { function search(stackArtifacts, assemblies) { if (assemblies.length === 0) { return stackArtifacts; } const [head, ...tail] = assemblies; const nestedAssemblies = head.nestedAssemblies.map(asm => asm.nestedAssembly); return search(stackArtifacts.concat(head.stacks), tail.concat(nestedAssemblies)); } return search([], [this]); } /** * Returns a nested assembly artifact. * * @param artifactId The artifact ID of the nested assembly */ getNestedAssemblyArtifact(artifactId) { const artifact = this.tryGetArtifact(artifactId); if (!artifact) { throw new error_1.CloudAssemblyError(`Unable to find artifact with id "${artifactId}"`); } if (!(artifact instanceof nested_cloud_assembly_artifact_1.NestedCloudAssemblyArtifact)) { throw new error_1.CloudAssemblyError(`Found artifact '${artifactId}' but it's not a nested cloud assembly`); } return artifact; } /** * Returns a nested assembly. * * @param artifactId The artifact ID of the nested assembly */ getNestedAssembly(artifactId) { return this.getNestedAssemblyArtifact(artifactId).nestedAssembly; } /** * Returns the tree metadata artifact from this assembly. * @throws if there is no metadata artifact by that name * @returns a `TreeCloudArtifact` object if there is one defined in the manifest, `undefined` otherwise. */ tree() { const trees = this.artifacts.filter(a => a.manifest.type === cxschema.ArtifactType.CDK_TREE); if (trees.length === 0) { return undefined; } else if (trees.length > 1) { throw new error_1.CloudAssemblyError(`Multiple artifacts of type ${cxschema.ArtifactType.CDK_TREE} found in manifest`); } const tree = trees[0]; if (!(tree instanceof tree_cloud_artifact_1.TreeCloudArtifact)) { throw new error_1.CloudAssemblyError('"Tree" artifact is not of expected type'); } return tree; } /** * @returns all the CloudFormation stack artifacts that are included in this assembly. */ get stacks() { return this.artifacts.filter(isCloudFormationStackArtifact); function isCloudFormationStackArtifact(x) { return x instanceof cloudformation_artifact_1.CloudFormationStackArtifact; } } /** * The nested assembly artifacts in this assembly */ get nestedAssemblies() { return this.artifacts.filter(isNestedCloudAssemblyArtifact); function isNestedCloudAssemblyArtifact(x) { return x instanceof nested_cloud_assembly_artifact_1.NestedCloudAssemblyArtifact; } } validateDeps() { for (const artifact of this.artifacts) { ignore(artifact.dependencies); } } renderArtifacts(topoSort) { const result = new Array(); for (const [name, artifact] of Object.entries(this.manifest.artifacts || {})) { const cloudartifact = cloud_artifact_1.CloudArtifact.fromManifest(this, name, artifact); if (cloudartifact) { result.push(cloudartifact); } } return topoSort ? (0, toposort_1.topologicalSort)(result, x => x.id, x => x._dependencyIDs) : result; } } exports.CloudAssembly = CloudAssembly; _a = JSII_RTTI_SYMBOL_1; CloudAssembly[_a] = { fqn: "@aws-cdk/cx-api.CloudAssembly", version: "2.211.0" }; /** * Can be used to build a cloud assembly. */ class CloudAssemblyBuilder { /** * Initializes a cloud assembly builder. * @param outdir The output directory, uses temporary directory if undefined */ constructor(outdir, props = {}) { this.artifacts = {}; this.missing = new Array(); try { jsiiDeprecationWarnings._aws_cdk_cx_api_CloudAssemblyBuilderProps(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, CloudAssemblyBuilder); } throw error; } this.outdir = determineOutputDirectory(outdir); this.assetOutdir = props.assetOutdir ?? this.outdir; this.parentBuilder = props.parentBuilder; // we leverage the fact that outdir is long-lived to avoid staging assets into it // that were already staged (copying can be expensive). this is achieved by the fact // that assets use a source hash as their name. other artifacts, and the manifest itself, // will overwrite existing files as needed. ensureDirSync(this.outdir); } /** * Adds an artifact into the cloud assembly. * @param id The ID of the artifact. * @param manifest The artifact manifest */ addArtifact(id, manifest) { this.artifacts[id] = filterUndefined(manifest); } /** * Reports that some context is missing in order for this cloud assembly to be fully synthesized. * @param missing Missing context information. */ addMissing(missing) { if (this.missing.every(m => m.key !== missing.key)) { this.missing.push(missing); } // Also report in parent this.parentBuilder?.addMissing(missing); } /** * Finalizes the cloud assembly into the output directory returns a * `CloudAssembly` object that can be used to inspect the assembly. */ buildAssembly(options = {}) { try { jsiiDeprecationWarnings._aws_cdk_cx_api_AssemblyBuildOptions(options); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.buildAssembly); } throw error; } // explicitly initializing this type will help us detect // breaking changes. (For example adding a required property will break compilation). let manifest = { version: cxschema.Manifest.version(), artifacts: this.artifacts, runtime: options.runtimeInfo, missing: this.missing.length > 0 ? this.missing : undefined, }; // now we can filter manifest = filterUndefined(manifest); const manifestFilePath = path.join(this.outdir, MANIFEST_FILE); cxschema.Manifest.saveAssemblyManifest(manifest, manifestFilePath); // "backwards compatibility": in order for the old CLI to tell the user they // need a new version, we'll emit the legacy manifest with only "version". // this will result in an error "CDK Toolkit >= CLOUD_ASSEMBLY_VERSION is required in order to interact with this program." fs.writeFileSync(path.join(this.outdir, 'cdk.out'), JSON.stringify({ version: manifest.version })); return new CloudAssembly(this.outdir); } /** * Creates a nested cloud assembly */ createNestedAssembly(artifactId, displayName) { const directoryName = artifactId; const innerAsmDir = path.join(this.outdir, directoryName); this.addArtifact(artifactId, { type: cxschema.ArtifactType.NESTED_CLOUD_ASSEMBLY, properties: { directoryName, displayName, }, }); return new CloudAssemblyBuilder(innerAsmDir, { // Reuse the same asset output directory as the current Casm builder assetOutdir: this.assetOutdir, parentBuilder: this, }); } /** * Delete the cloud assembly directory */ delete() { fs.rmSync(this.outdir, { recursive: true, force: true }); } } exports.CloudAssemblyBuilder = CloudAssemblyBuilder; _b = JSII_RTTI_SYMBOL_1; CloudAssemblyBuilder[_b] = { fqn: "@aws-cdk/cx-api.CloudAssemblyBuilder", version: "2.211.0" }; /** * Returns a copy of `obj` without undefined values in maps or arrays. */ function filterUndefined(obj) { if (Array.isArray(obj)) { return obj.filter(x => x !== undefined).map(x => filterUndefined(x)); } if (typeof (obj) === 'object') { const ret = {}; for (const [key, value] of Object.entries(obj)) { if (value === undefined) { continue; } ret[key] = filterUndefined(value); } return ret; } return obj; } function ignore(_x) { return; } /** * Turn the given optional output directory into a fixed output directory */ function determineOutputDirectory(outdir) { return outdir ?? fs.mkdtempSync(path.join(fs.realpathSync(os.tmpdir()), 'cdk.out')); } function ensureDirSync(dir) { if (fs.existsSync(dir)) { if (!fs.statSync(dir).isDirectory()) { throw new error_1.CloudAssemblyError(`${dir} must be a directory`); } } else { fs.mkdirSync(dir, { recursive: true }); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xvdWQtYXNzZW1ibHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJjbG91ZC1hc3NlbWJseS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSx5QkFBeUI7QUFDekIseUJBQXlCO0FBQ3pCLDZCQUE2QjtBQUs3QixpRkFBa0Y7QUFDbEYsK0ZBQXlGO0FBQ3pGLHlFQUFvRTtBQUNwRSxxREFBaUQ7QUFDakQseUNBQTZDO0FBQzdDLDJEQUEyRDtBQUMzRCwyQ0FBcUQ7QUFFckQsTUFBTSxxQkFBcUIsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLCtCQUErQixDQUFDLENBQUM7QUFFMUU7O0dBRUc7QUFDSCxNQUFNLGFBQWEsR0FBRyxlQUFlLENBQUM7QUFFdEM7O0dBRUc7QUFDSCxNQUFhLGFBQWE7SUFDeEI7Ozs7T0FJRztJQUNJLE1BQU0sQ0FBQyxlQUFlLENBQUMsQ0FBTTtRQUNsQyxPQUFPLENBQUMsS0FBSyxJQUFJLElBQUksT0FBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLFFBQVEsSUFBSSxxQkFBcUIsSUFBSSxDQUFDLENBQUM7S0FDM0U7SUEyQkQ7OztPQUdHO0lBQ0gsWUFBWSxTQUFpQixFQUFFLFdBQTBDO1FBQ3ZFLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDO1FBRTNCLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDLFFBQVEsQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxhQUFhLENBQUMsRUFBRSxXQUFXLENBQUMsQ0FBQztRQUN6RyxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDO1FBQ3JDLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxXQUFXLEVBQUUsUUFBUSxJQUFJLElBQUksQ0FBQyxDQUFDO1FBQ3JFLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLElBQUks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LENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUMvQyxJQUFJLEtBQUssS0FBSyxTQUFTLEVBQUUsQ0FBQztnQkFDeEIsU0FBUztZQUNYLENBQUM7WUFDRCxHQUFHLENBQUMsR0FBRyxDQUFDLEdBQUcsZUFBZSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3BDLENBQUM7UUFDRCxPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7SUFFRCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUM7QUFFRCxTQUFTLE1BQU0sQ0FBQyxFQUFPO0lBQ3JCLE9BQU87QUFDVCxDQUFDO0FBRUQ7O0dBRUc7QUFDSCxTQUFTLHdCQUF3QixDQUFDLE1BQWU7SUFDL0MsT0FBTyxNQUFNLElBQUksRUFBRSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsU0FBUyxDQUFDLENBQUMsQ0FBQztBQUN0RixDQUFDO0FBRUQsU0FBUyxhQUFhLENBQUMsR0FBVztJQUNoQyxJQUFJLEVBQUUsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUN2QixJQUFJLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDO1lBQ3BDLE1BQU0sSUFBSSwwQkFBa0IsQ0FBQyxHQUFHLEdBQUcsc0JBQXNCLENBQUMsQ0FBQztRQUM3RCxDQUFDO0lBQ0gsQ0FBQztTQUFNLENBQUM7UUFDTixFQUFFLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ3pDLENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMnO1xuaW1wb3J0ICogYXMgb3MgZnJvbSAnb3MnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbi8vIFRoaXMgaXMgZGVsaWJlcmF0ZWx5IGltcG9ydGluZyB0aGUgaW50ZXJmYWNlIGZyb20gdGhlIGV4dGVybmFsIHBhY2thZ2UuXG4vLyBXZSB3YW50IHRoaXMsIHNvIHRoYXQganNpaSBsYW5ndWFnZSBwYWNrYWdlcyBjYW4gZGVwZW5kIG9uIEBhd3MtY2RrL2Nsb3VkLWFzc2VtYmx5LXNjaGVtYVxuLy8gaW5zdGVhZCBvZiBiZWluZyBmb3JjZWQgdG8gdGFrZSBhIGRlcGVuZGVuY3kgb24gdGhlIG11Y2ggbGFyZ2VyIGF3cy1jZGstbGliLlxuaW1wb3J0IHR5cGUgeyBJQ2xvdWRBc3NlbWJseSB9IGZyb20gJ0Bhd3MtY2RrL2Nsb3VkLWFzc2VtYmx5LXNjaGVtYSc7XG5pbXBvcnQgeyBDbG91ZEZvcm1hdGlvblN0YWNrQXJ0aWZhY3QgfSBmcm9tICcuL2FydGlmYWN0cy9jbG91ZGZvcm1hdGlvbi1hcnRpZmFjdCc7XG5pbXBvcnQgeyBOZXN0ZWRDbG91ZEFzc2VtYmx5QXJ0aWZhY3QgfSBmcm9tICcuL2FydGlmYWN0cy9uZXN0ZWQtY2xvdWQtYXNzZW1ibHktYXJ0aWZhY3QnO1xuaW1wb3J0IHsgVHJlZUNsb3VkQXJ0aWZhY3QgfSBmcm9tICcuL2FydGlmYWN0cy90cmVlLWNsb3VkLWFydGlmYWN0JztcbmltcG9ydCB7IENsb3VkQXJ0aWZhY3QgfSBmcm9tICcuL2Nsb3VkLWFydGlmYWN0JztcbmltcG9ydCB7IHRvcG9sb2dpY2FsU29ydCB9IGZyb20gJy4vdG9wb3NvcnQnO1xuaW1wb3J0ICogYXMgY3hzY2hlbWEgZnJvbSAnQGF3cy1jZGsvY2xvdWQtYXNzZW1ibHktc2NoZW1hJztcbmltcG9ydCB7IENsb3VkQXNzZW1ibHlFcnJvciB9IGZyb20gJy4vcHJpdmF0ZS9lcnJvcic7XG5cbmNvbnN0IENMT1VEX0FTU0VNQkxZX1NZTUJPTCA9IFN5bWJvbC5mb3IoJ0Bhd3MtY2RrL2N4LWFwaS5DbG91ZEFzc2VtYmx5Jyk7XG5cbi8qKlxuICogVGhlIG5hbWUgb2YgdGhlIHJvb3QgbWFuaWZlc3QgZmlsZSBvZiB0aGUgYXNzZW1ibHkuXG4gKi9cbmNvbnN0IE1BTklGRVNUX0ZJTEUgPSAnbWFuaWZlc3QuanNvbic7XG5cbi8qKlxuICogUmVwcmVzZW50cyBhIGRlcGxveWFibGUgY2xvdWQgYXBwbGljYXRpb24uXG4gKi9cbmV4cG9ydCBjbGFzcyBDbG91ZEFzc2VtYmx5IGltcGxlbWVudHMgSUNsb3VkQXNzZW1ibHkge1xuICAvKipcbiAgICogUmV0dXJuIHdoZXRoZXIgdGhlIGdpdmVuIG9iamVjdCBpcyBhIENsb3VkQXNzZW1ibHkuXG4gICAqXG4gICAqIFdlIGRvIGF0dHJpYnV0ZSBkZXRlY3Rpb24gc2luY2Ugd2UgY2FuJ3QgcmVsaWFibHkgdXNlICdpbnN0YW5jZW9mJy5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgaXNDbG91ZEFzc2VtYmx5KHg6IGFueSk6IHggaXMgQ2xvdWRBc3NlbWJseSB7XG4gICAgcmV0dXJuIHggIT09IG51bGwgJiYgdHlwZW9mKHgpID09PSAnb2JqZWN0JyAmJiBDTE9VRF9BU1NFTUJMWV9TWU1CT0wgaW4geDtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgcm9vdCBkaXJlY3Rvcnkgb2YgdGhlIGNsb3VkIGFzc2VtYmx5LlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGRpcmVjdG9yeTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgc2NoZW1hIHZlcnNpb24gb2YgdGhlIGFzc2VtYmx5IG1hbmlmZXN0LlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHZlcnNpb246IHN0cmluZztcblxuICAvKipcbiAgICogQWxsIGFydGlmYWN0cyBpbmNsdWRlZCBpbiB0aGlzIGFzc2VtYmx5LlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGFydGlmYWN0czogQ2xvdWRBcnRpZmFjdFtdO1xuXG4gIC8qKlxuICAgKiBSdW50aW1lIGluZm9ybWF0aW9uIHN1Y2ggYXMgbW9kdWxlIHZlcnNpb25zIHVzZWQgdG8gc3ludGhlc2l6ZSB0aGlzIGFzc2VtYmx5LlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHJ1bnRpbWU6IGN4c2NoZW1hLlJ1bnRpbWVJbmZvO1xuXG4gIC8qKlxuICAgKiBUaGUgcmF3IGFzc2VtYmx5IG1hbmlmZXN0LlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IG1hbmlmZXN0OiBjeHNjaGVtYS5Bc3NlbWJseU1hbmlmZXN0O1xuXG4gIC8qKlxuICAgKiBSZWFkcyBhIGNsb3VkIGFzc2VtYmx5IGZyb20gdGhlIHNwZWNpZmllZCBkaXJlY3RvcnkuXG4gICAqIEBwYXJhbSBkaXJlY3RvcnkgVGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoZSBhc3NlbWJseS5cbiAgICovXG4gIGNvbnN0cnVjdG9yKGRpcmVjdG9yeTogc3RyaW5nLCBsb2FkT3B0aW9ucz86IGN4c2NoZW1hLkxvYWRNYW5pZmVzdE9wdGlvbnMpIHtcbiAgICB0aGlzLmRpcmVjdG9yeSA9IGRpcmVjdG9yeTtcblxuICAgIHRoaXMubWFuaWZlc3QgPSBjeHNjaGVtYS5NYW5pZmVzdC5sb2FkQXNzZW1ibHlNYW5pZmVzdChwYXRoLmpvaW4oZGlyZWN0b3J5LCBNQU5JRkVTVF9GSUxFKSwgbG9hZE9wdGlvbnMpO1xuICAgIHRoaXMudmVyc2lvbiA9IHRoaXMubWFuaWZlc3QudmVyc2lvbjtcbiAgICB0aGlzLmFydGlmYWN0cyA9IHRoaXMucmVuZGVyQXJ0aWZhY3RzKGxvYWRPcHRpb25zPy50b3BvU29ydCA/PyB0cnVlKTtcbiAgICB0aGlzLnJ1bnRpbWUgPSB0aGlzLm1hbmlmZXN0LnJ1bnRpbWUgfHwgeyBsaWJyYXJpZXM6IHsgfSB9O1xuXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsIENMT1VEX0FTU0VNQkxZX1NZTUJPTCwgeyB2YWx1ZTogdHJ1ZSB9KTtcblxuICAgIC8vIGZvcmNlIHZhbGlkYXRpb24gb2YgZGVwcyBieSBhY2Nlc3NpbmcgJ2RlcGVuZHMnIG9uIGFsbCBhcnRpZmFjdHNcbiAgICB0aGlzLnZhbGlkYXRlRGVwcygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEF0dGVtcHRzIHRvIGZpbmQgYW4gYXJ0aWZhY3Qgd2l0aCBhIHNwZWNpZmljIGlkZW50aXR5LlxuICAgKiBAcmV0dXJucyBBIGBDbG91ZEFydGlmYWN0YCBvYmplY3Qgb3IgYHVuZGVmaW5lZGAgaWYgdGhlIGFydGlmYWN0IGRvZXMgbm90IGV4aXN0IGluIHRoaXMgYXNzZW1ibHkuXG4gICAqIEBwYXJhbSBpZCBUaGUgYXJ0aWZhY3QgSURcbiAgICovXG4gIHB1YmxpYyB0cnlHZXRBcnRpZmFjdChpZDogc3RyaW5nKTogQ2xvdWRBcnRpZmFjdCB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuYXJ0aWZhY3RzLmZpbmQoYSA9PiBhLmlkID09PSBpZCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIENsb3VkRm9ybWF0aW9uIHN0YWNrIGFydGlmYWN0IGZyb20gdGhpcyBhc3NlbWJseS5cbiAgICpcbiAgICogV2lsbCBvbmx5IHNlYXJjaCB0aGUgY3VycmVudCBhc3NlbWJseS5cbiAgICpcbiAgICogQHBhcmFtIHN0YWNrTmFtZSB0aGUgbmFtZSBvZiB0aGUgQ2xvdWRGb3JtYXRpb24gc3RhY2suXG4gICAqIEB0aHJvd3MgaWYgdGhlcmUgaXMgbm8gc3RhY2sgYXJ0aWZhY3QgYnkgdGhhdCBuYW1lXG4gICAqIEB0aHJvd3MgaWYgdGhlcmUgaXMgbW9yZSB0aGFuIG9uZSBzdGFjayB3aXRoIHRoZSBzYW1lIHN0YWNrIG5hbWUuIFlvdSBjYW5cbiAgICogdXNlIGBnZXRTdGFja0FydGlmYWN0KHN0YWNrLmFydGlmYWN0SWQpYCBpbnN0ZWFkLlxuICAgKiBAcmV0dXJucyBhIGBDbG91ZEZvcm1hdGlvblN0YWNrQXJ0aWZhY3RgIG9iamVjdC5cbiAgICovXG4gIHB1YmxpYyBnZXRTdGFja0J5TmFtZShzdGFja05hbWU6IHN0cmluZyk6IENsb3VkRm9ybWF0aW9uU3RhY2tBcnRpZmFjdCB7XG4gICAgY29uc3QgYXJ0aWZhY3RzID0gdGhpcy5hcnRpZmFjdHMuZmlsdGVyKGEgPT4gYSBpbnN0YW5jZW9mIENsb3VkRm9ybWF0aW9uU3RhY2tBcnRpZmFjdCAmJiBhLnN0YWNrTmFtZSA9PT0gc3RhY2tOYW1lKTtcbiAgICBpZiAoIWFydGlmYWN0cyB8fCBhcnRpZmFjdHMubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgQ2xvdWRBc3NlbWJseUVycm9yKGBVbmFibGUgdG8gZmluZCBzdGFjayB3aXRoIHN0YWNrIG5hbWUgXCIke3N0YWNrTmFtZX1cImApO1xuICAgIH1cblxuICAgIGlmIChhcnRpZmFjdHMubGVuZ3RoID4gMSkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG1heC1sZW5cbiAgICAgIHRocm93IG5ldyBDbG91ZEFzc2VtYmx5RXJyb3IoYFRoZXJlIGFyZSBtdWx0aXBsZSBzdGFja3Mgd2l0aCB0aGUgc3RhY2sgbmFtZSBcIiR7c3RhY2tOYW1lfVwiICgke2FydGlmYWN0cy5tYXAoYSA9PiBhLmlkKS5qb2luKCcsJyl9KS4gVXNlIFwiZ2V0U3RhY2tBcnRpZmFjdChpZClcIiBpbnN0ZWFkYCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGFydGlmYWN0c1swXSBhcyBDbG91ZEZvcm1hdGlvblN0YWNrQXJ0aWZhY3Q7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIENsb3VkRm9ybWF0aW9uIHN0YWNrIGFydGlmYWN0IGJ5IG5hbWUgZnJvbSB0aGlzIGFzc2VtYmx5LlxuICAgKiBAZGVwcmVjYXRlZCByZW5hbWVkIHRvIGBnZXRTdGFja0J5TmFtZWAgKG9yIGBnZXRTdGFja0FydGlmYWN0KGlkKWApXG4gICAqL1xuICBwdWJsaWMgZ2V0U3RhY2soc3RhY2tOYW1lOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRTdGFja0J5TmFtZShzdGFja05hbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBDbG91ZEZvcm1hdGlvbiBzdGFjayBhcnRpZmFjdCBmcm9tIHRoaXMgYXNzZW1ibHkuXG4gICAqXG4gICAqIEBwYXJhbSBhcnRpZmFjdElkIHRoZSBhcnRpZmFjdCBpZCBvZiB0aGUgc3RhY2sgKGNhbiBiZSBvYnRhaW5lZCB0aHJvdWdoIGBzdGFjay5hcnRpZmFjdElkYCkuXG4gICAqIEB0aHJvd3MgaWYgdGhlcmUgaXMgbm8gc3RhY2sgYXJ0aWZhY3Qgd2l0aCB0aGF0IGlkXG4gICAqIEByZXR1cm5zIGEgYENsb3VkRm9ybWF0aW9uU3RhY2tBcnRpZmFjdGAgb2JqZWN0LlxuICAgKi9cbiAgcHVibGljIGdldFN0YWNrQXJ0aWZhY3QoYXJ0aWZhY3RJZDogc3RyaW5nKTogQ2xvdWRGb3JtYXRpb25TdGFja0FydGlmYWN0IHtcbiAgICBjb25zdCBhcnRpZmFjdCA9IHRoaXMudHJ5R2V0QXJ0aWZhY3RSZWN1cnNpdmVseShhcnRpZmFjdElkKTtcblxuICAgIGlmICghYXJ0aWZhY3QpIHtcbiAgICAgIHRocm93IG5ldyBDbG91ZEFzc2VtYmx5RXJyb3IoYFVuYWJsZSB0byBmaW5kIGFydGlmYWN0IHdpdGggaWQgXCIke2FydGlmYWN0SWR9XCJgKTtcbiAgICB9XG5cbiAgICBpZiAoIShhcnRpZmFjdCBpbnN0YW5jZW9mIENsb3VkRm9ybWF0aW9uU3RhY2tBcnRpZmFjdCkpIHtcbiAgICAgIHRocm93IG5ldyBDbG91ZEFzc2VtYmx5RXJyb3IoYEFydGlmYWN0ICR7YXJ0aWZhY3RJZH0gaXMgbm90IGEgQ2xvdWRGb3JtYXRpb24gc3RhY2tgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXJ0aWZhY3Q7XG4gIH1cblxuICBwcml2YXRlIHRyeUdldEFydGlmYWN0UmVjdXJzaXZlbHkoYXJ0aWZhY3RJZDogc3RyaW5nKTogQ2xvdWRBcnRpZmFjdCB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuc3RhY2tzUmVjdXJzaXZlbHkuZmluZChhID0+IGEuaWQgPT09IGFydGlmYWN0SWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYWxsIHRoZSBzdGFja3MsIGluY2x1ZGluZyB0aGUgb25lcyBpbiBuZXN0ZWQgYXNzZW1ibGllc1xuICAgKi9cbiAgcHVibGljIGdldCBzdGFja3NSZWN1cnNpdmVseSgpOiBDbG91ZEZvcm1hdGlvblN0YWNrQXJ0aWZhY3RbXSB7XG4gICAgZnVuY3Rpb24gc2VhcmNoKHN0YWNrQXJ0aWZhY3RzOiBDbG91ZEZvcm1hdGlvblN0YWNrQXJ0aWZhY3RbXSwgYXNzZW1ibGllczogQ2xvdWRBc3NlbWJseVtdKTogQ2xvdWRGb3JtYXRpb25TdGFja0FydGlmYWN0W10ge1xuICAgICAgaWYgKGFzc2VtYmxpZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiBzdGFja0FydGlmYWN0cztcbiAgICAgIH1cblxuICAgICAgY29uc3QgW2hlYWQsIC4uLnRhaWxdID0gYXNzZW1ibGllcztcbiAgICAgIGNvbnN0IG5lc3RlZEFzc2VtYmxpZXMgPSBoZWFkLm5lc3RlZEFzc2VtYmxpZXMubWFwKGFzbSA9PiBhc20ubmVzdGVkQXNzZW1ibHkpO1xuICAgICAgcmV0dXJuIHNlYXJjaChzdGFja0FydGlmYWN0cy5jb25jYXQoaGVhZC5zdGFja3MpLCB0YWlsLmNvbmNhdChuZXN0ZWRBc3NlbWJsaWVzKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNlYXJjaChbXSwgW3RoaXNdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbmVzdGVkIGFzc2VtYmx5IGFydGlmYWN0LlxuICAgKlxuICAgKiBAcGFyYW0gYXJ0aWZhY3RJZCBUaGUgYXJ0aWZhY3QgSUQgb2YgdGhlIG5lc3RlZCBhc3NlbWJseVxuICAgKi9cbiAgcHVibGljIGdldE5lc3RlZEFzc2VtYmx5QXJ0aWZhY3QoYXJ0aWZhY3RJZDogc3RyaW5nKTogTmVzdGVkQ2xvdWRBc3NlbWJseUFydGlmYWN0IHtcbiAgICBjb25zdCBhcnRpZmFjdCA9IHRoaXMudHJ5R2V0QXJ0aWZhY3QoYXJ0aWZhY3RJZCk7XG4gICAgaWYgKCFhcnRpZmFjdCkge1xuICAgICAgdGhyb3cgbmV3IENsb3VkQXNzZW1ibHlFcnJvcihgVW5hYmxlIHRvIGZpbmQgYXJ0aWZhY3Qgd2l0aCBpZCBcIiR7YXJ0aWZhY3RJZH1cImApO1xuICAgIH1cblxuICAgIGlmICghKGFydGlmYWN0IGluc3RhbmNlb2YgTmVzdGVkQ2xvdWRBc3NlbWJseUFydGlmYWN0KSkge1xuICAgICAgdGhyb3cgbmV3IENsb3VkQXNzZW1ibHlFcnJvcihgRm91bmQgYXJ0aWZhY3QgJyR7YXJ0aWZhY3RJZH0nIGJ1dCBpdCdzIG5vdCBhIG5lc3RlZCBjbG91ZCBhc3NlbWJseWApO1xuICAgIH1cblxuICAgIHJldHVybiBhcnRpZmFjdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgbmVzdGVkIGFzc2VtYmx5LlxuICAgKlxuICAgKiBAcGFyYW0gYXJ0aWZhY3RJZCBUaGUgYXJ0aWZhY3QgSUQgb2YgdGhlIG5lc3RlZCBhc3NlbWJseVxuICAgKi9cbiAgcHVibGljIGdldE5lc3RlZEFzc2VtYmx5KGFydGlmYWN0SWQ6IHN0cmluZyk6IENsb3VkQXNzZW1ibHkge1xuICAgIHJldHVybiB0aGlzLmdldE5lc3RlZEFzc2VtYmx5QXJ0aWZhY3QoYXJ0aWZhY3RJZCkubmVzdGVkQXNzZW1ibHk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgdHJlZSBtZXRhZGF0YSBhcnRpZmFjdCBmcm9tIHRoaXMgYXNzZW1ibHkuXG4gICAqIEB0aHJvd3MgaWYgdGhlcmUgaXMgbm8gbWV0YWRhdGEgYXJ0aWZhY3QgYnkgdGhhdCBuYW1lXG4gICAqIEByZXR1cm5zIGEgYFRyZWVDbG91ZEFydGlmYWN0YCBvYmplY3QgaWYgdGhlcmUgaXMgb25lIGRlZmluZWQgaW4gdGhlIG1hbmlmZXN0LCBgdW5kZWZpbmVkYCBvdGhlcndpc2UuXG4gICAqL1xuICBwdWJsaWMgdHJlZSgpOiBUcmVlQ2xvdWRBcnRpZmFjdCB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgdHJlZXMgPSB0aGlzLmFydGlmYWN0cy5maWx0ZXIoYSA9PiBhLm1hbmlmZXN0LnR5cGUgPT09IGN4c2NoZW1hLkFydGlmYWN0VHlwZS5DREtfVFJFRSk7XG4gICAgaWYgKHRyZWVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9IGVsc2UgaWYgKHRyZWVzLmxlbmd0aCA+IDEpIHtcbiAgICAgIHRocm93IG5ldyBDbG91ZEFzc2VtYmx5RXJyb3IoYE11bHRpcGxlIGFydGlmYWN0cyBvZiB0eXBlICR7Y3hzY2hlbWEuQXJ0aWZhY3RUeXBlLkNES19UUkVFfSBmb3VuZCBpbiBtYW5pZmVzdGApO1xuICAgIH1cbiAgICBjb25zdCB0cmVlID0gdHJlZXNbMF07XG5cbiAgICBpZiAoISh0cmVlIGluc3RhbmNlb2YgVHJlZUNsb3VkQXJ0aWZhY3QpKSB7XG4gICAgICB0aHJvdyBuZXcgQ2xvdWRBc3NlbWJseUVycm9yKCdcIlRyZWVcIiBhcnRpZmFjdCBpcyBub3Qgb2YgZXhwZWN0ZWQgdHlwZScpO1xuICAgIH1cblxuICAgIHJldHVybiB0cmVlO1xuICB9XG5cbiAgLyoqXG4gICAqIEByZXR1cm5zIGFsbCB0aGUgQ2xvdWRGb3JtYXRpb24gc3RhY2sgYXJ0aWZhY3RzIHRoYXQgYXJlIGluY2x1ZGVkIGluIHRoaXMgYXNzZW1ibHkuXG4gICAqL1xuICBwdWJsaWMgZ2V0IHN0YWNrcygpOiBDbG91ZEZvcm1hdGlvblN0YWNrQXJ0aWZhY3RbXSB7XG4gICAgcmV0dXJuIHRoaXMuYXJ0aWZhY3RzLmZpbHRlcihpc0Nsb3VkRm9ybWF0aW9uU3RhY2tBcnRpZmFjdCk7XG5cbiAgICBmdW5jdGlvbiBpc0Nsb3VkRm9ybWF0aW9uU3RhY2tBcnRpZmFjdCh4OiBhbnkpOiB4IGlzIENsb3VkRm9ybWF0aW9uU3RhY2tBcnRpZmFjdCB7XG4gICAgICByZXR1cm4geCBpbnN0YW5jZW9mIENsb3VkRm9ybWF0aW9uU3RhY2tBcnRpZmFjdDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVGhlIG5lc3RlZCBhc3NlbWJseSBhcnRpZmFjdHMgaW4gdGhpcyBhc3NlbWJseVxuICAgKi9cbiAgcHVibGljIGdldCBuZXN0ZWRBc3NlbWJsaWVzKCk6IE5lc3RlZENsb3VkQXNzZW1ibHlBcnRpZmFjdFtdIHtcbiAgICByZXR1cm4gdGhpcy5hcnRpZmFjdHMuZmlsdGVyKGlzTmVzdGVkQ2xvdWRBc3NlbWJseUFydGlmYWN0KTtcblxuICAgIGZ1bmN0aW9uIGlzTmVzdGVkQ2xvdWRBc3NlbWJseUFydGlmYWN0KHg6IGFueSk6IHggaXMgTmVzdGVkQ2xvdWRBc3NlbWJseUFydGlmYWN0IHtcbiAgICAgIHJldHVybiB4IGluc3RhbmNlb2YgTmVzdGVkQ2xvdWRBc3NlbWJseUFydGlmYWN0O1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgdmFsaWRhdGVEZXBzKCkge1xuICAgIGZvciAoY29uc3QgYXJ0aWZhY3Qgb2YgdGhpcy5hcnRpZmFjdHMpIHtcbiAgICAgIGlnbm9yZShhcnRpZmFjdC5kZXBlbmRlbmNpZXMpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcmVuZGVyQXJ0aWZhY3RzKHRvcG9Tb3J0OiBib29sZWFuKSB7XG4gICAgY29uc3QgcmVzdWx0ID0gbmV3IEFycmF5PENsb3VkQXJ0aWZhY3Q+KCk7XG4gICAgZm9yIChjb25zdCBbbmFtZSwgYXJ0aWZhY3RdIG9mIE9iamVjdC5lbnRyaWVzKHRoaXMubWFuaWZlc3QuYXJ0aWZhY3RzIHx8IHsgfSkpIHtcbiAgICAgIGNvbnN0IGNsb3VkYXJ0aWZhY3QgPSBDbG91ZEFydGlmYWN0LmZyb21NYW5pZmVzdCh0aGlzLCBuYW1lLCBhcnRpZmFjdCk7XG4gICAgICBpZiAoY2xvdWRhcnRpZmFjdCkge1xuICAgICAgICByZXN1bHQucHVzaChjbG91ZGFydGlmYWN0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdG9wb1NvcnQgPyB0b3BvbG9naWNhbFNvcnQocmVzdWx0LCB4ID0+IHguaWQsIHggPT4geC5fZGVwZW5kZW5jeUlEcykgOiByZXN1bHQ7XG4gIH1cbn1cblxuLyoqXG4gKiBDb25zdHJ1Y3Rpb24gcHJvcGVydGllcyBmb3IgQ2xvdWRBc3NlbWJseUJ1aWxkZXJcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDbG91ZEFzc2VtYmx5QnVpbGRlclByb3BzIHtcbiAgLyoqXG4gICAqIFVzZSB0aGUgZ2l2ZW4gYXNzZXQgb3V0cHV0IGRpcmVjdG9yeVxuICAgKlxuICAgKiBAZGVmYXVsdCAtIFNhbWUgYXMgdGhlIG1hbmlmZXN0IG91dGRpclxuICAgKi9cbiAgcmVhZG9ubHkgYXNzZXRPdXRkaXI/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIElmIHRoaXMgYnVpbGRlciBpcyBmb3IgYSBuZXN0ZWQgYXNzZW1ibHksIHRoZSBwYXJlbnQgYXNzZW1ibHkgYnVpbGRlclxuICAgKlxuICAgKiBAZGVmYXVsdCAtIFRoaXMgaXMgYSByb290IGFzc2VtYmx5XG4gICAqL1xuICByZWFkb25seSBwYXJlbnRCdWlsZGVyPzogQ2xvdWRBc3NlbWJseUJ1aWxkZXI7XG59XG5cbi8qKlxuICogQ2FuIGJlIHVzZWQgdG8gYnVpbGQgYSBjbG91ZCBhc3NlbWJseS5cbiAqL1xuZXhwb3J0IGNsYXNzIENsb3VkQXNzZW1ibHlCdWlsZGVyIHtcbiAgLyoqXG4gICAqIFRoZSByb290IGRpcmVjdG9yeSBvZiB0aGUgcmVzdWx0aW5nIGNsb3VkIGFzc2VtYmx5LlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IG91dGRpcjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgZGlyZWN0b3J5IHdoZXJlIGFzc2V0cyBvZiB0aGlzIENsb3VkIEFzc2VtYmx5IHNob3VsZCBiZSBzdG9yZWRcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBhc3NldE91dGRpcjogc3RyaW5nO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgYXJ0aWZhY3RzOiB7IFtpZDogc3RyaW5nXTogY3hzY2hlbWEuQXJ0aWZhY3RNYW5pZmVzdCB9ID0geyB9O1xuICBwcml2YXRlIHJlYWRvbmx5IG1pc3NpbmcgPSBuZXcgQXJyYXk8Y3hzY2hlbWEuTWlzc2luZ0NvbnRleHQ+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgcGFyZW50QnVpbGRlcj86IENsb3VkQXNzZW1ibHlCdWlsZGVyO1xuXG4gIC8qKlxuICAgKiBJbml0aWFsaXplcyBhIGNsb3VkIGFzc2VtYmx5IGJ1aWxkZXIuXG4gICAqIEBwYXJhbSBvdXRkaXIgVGhlIG91dHB1dCBkaXJlY3RvcnksIHVzZXMgdGVtcG9yYXJ5IGRpcmVjdG9yeSBpZiB1bmRlZmluZWRcbiAgICovXG4gIGNvbnN0cnVjdG9yKG91dGRpcj86IHN0cmluZywgcHJvcHM6IENsb3VkQXNzZW1ibHlCdWlsZGVyUHJvcHMgPSB7fSkge1xuICAgIHRoaXMub3V0ZGlyID0gZGV0ZXJtaW5lT3V0cHV0RGlyZWN0b3J5KG91dGRpcik7XG4gICAgdGhpcy5hc3NldE91dGRpciA9IHByb3BzLmFzc2V0T3V0ZGlyID8/IHRoaXMub3V0ZGlyO1xuICAgIHRoaXMucGFyZW50QnVpbGRlciA9IHByb3BzLnBhcmVudEJ1aWxkZXI7XG5cbiAgICAvLyB3ZSBsZXZlcmFnZSB0aGUgZmFjdCB0aGF0IG91dGRpciBpcyBsb25nLWxpdmVkIHRvIGF2b2lkIHN0YWdpbmcgYXNzZXRzIGludG8gaXRcbiAgICAvLyB0aGF0IHdlcmUgYWxyZWFkeSBzdGFnZWQgKGNvcHlpbmcgY2FuIGJlIGV4cGVuc2l2ZSkuIHRoaXMgaXMgYWNoaWV2ZWQgYnkgdGhlIGZhY3RcbiAgICAvLyB0aGF0IGFzc2V0cyB1c2UgYSBzb3VyY2UgaGFzaCBhcyB0aGVpciBuYW1lLiBvdGhlciBhcnRpZmFjdHMsIGFuZCB0aGUgbWFuaWZlc3QgaXRzZWxmLFxuICAgIC8vIHdpbGwgb3ZlcndyaXRlIGV4aXN0aW5nIGZpbGVzIGFzIG5lZWRlZC5cbiAgICBlbnN1cmVEaXJTeW5jKHRoaXMub3V0ZGlyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGFuIGFydGlmYWN0IGludG8gdGhlIGNsb3VkIGFzc2VtYmx5LlxuICAgKiBAcGFyYW0gaWQgVGhlIElEIG9mIHRoZSBhcnRpZmFjdC5cbiAgICogQHBhcmFtIG1hbmlmZXN0IFRoZSBhcnRpZmFjdCBtYW5pZmVzdFxuICAgKi9cbiAgcHVibGljIGFkZEFydGlmYWN0KGlkOiBzdHJpbmcsIG1hbmlmZXN0OiBjeHNjaGVtYS5BcnRpZmFjdE1hbmlmZXN0KSB7XG4gICAgdGhpcy5hcnRpZmFjdHNbaWRdID0gZmlsdGVyVW5kZWZpbmVkKG1hbmlmZXN0KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXBvcnRzIHRoYXQgc29tZSBjb250ZXh0IGlzIG1pc3NpbmcgaW4gb3JkZXIgZm9yIHRoaXMgY2xvdWQgYXNzZW1ibHkgdG8gYmUgZnVsbHkgc3ludGhlc2l6ZWQuXG4gICAqIEBwYXJhbSBtaXNzaW5nIE1pc3NpbmcgY29udGV4dCBpbmZvcm1hdGlvbi5cbiAgICovXG4gIHB1YmxpYyBhZGRNaXNzaW5nKG1pc3Npbmc6IGN4c2NoZW1hLk1pc3NpbmdDb250ZXh0KSB7XG4gICAgaWYgKHRoaXMubWlzc2luZy5ldmVyeShtID0+IG0ua2V5ICE9PSBtaXNzaW5nLmtleSkpIHtcbiAgICAgIHRoaXMubWlzc2luZy5wdXNoKG1pc3NpbmcpO1xuICAgIH1cbiAgICAvLyBBbHNvIHJlcG9ydCBpbiBwYXJlbnRcbiAgICB0aGlzLnBhcmVudEJ1aWxkZXI/LmFkZE1pc3NpbmcobWlzc2luZyk7XG4gIH1cblxuICAvKipcbiAgICogRmluYWxpemVzIHRoZSBjbG91ZCBhc3NlbWJseSBpbnRvIHRoZSBvdXRwdXQgZGlyZWN0b3J5IHJldHVybnMgYVxuICAgKiBgQ2xvdWRBc3NlbWJseWAgb2JqZWN0IHRoYXQgY2FuIGJlIHVzZWQgdG8gaW5zcGVjdCB0aGUgYXNzZW1ibHkuXG4gICAqL1xuICBwdWJsaWMgYnVpbGRBc3NlbWJseShvcHRpb25zOiBBc3NlbWJseUJ1aWxkT3B0aW9ucyA9IHsgfSk6IENsb3VkQXNzZW1ibHkge1xuICAgIC8vIGV4cGxpY2l0bHkgaW5pdGlhbGl6aW5nIHRoaXMgdHlwZSB3aWxsIGhlbHAgdXMgZGV0ZWN0XG4gICAgLy8gYnJlYWtpbmcgY2hhbmdlcy4gKEZvciBleGFtcGxlIGFkZGluZyBhIHJlcXVpcmVkIHByb3BlcnR5IHdpbGwgYnJlYWsgY29tcGlsYXRpb24pLlxuICAgIGxldCBtYW5pZmVzdDogY3hzY2hlbWEuQXNzZW1ibHlNYW5pZmVzdCA9IHtcbiAgICAgIHZlcnNpb246IGN4c2NoZW1hLk1hbmlmZXN0LnZlcnNpb24oKSxcbiAgICAgIGFydGlmYWN0czogdGhpcy5hcnRpZmFjdHMsXG4gICAgICBydW50aW1lOiBvcHRpb25zLnJ1bnRpbWVJbmZvLFxuICAgICAgbWlzc2luZzogdGhpcy5taXNzaW5nLmxlbmd0aCA+IDAgPyB0aGlzLm1pc3NpbmcgOiB1bmRlZmluZWQsXG4gICAgfTtcblxuICAgIC8vIG5vdyB3ZSBjYW4gZmlsdGVyXG4gICAgbWFuaWZlc3QgPSBmaWx0ZXJVbmRlZmluZWQobWFuaWZlc3QpO1xuXG4gICAgY29uc3QgbWFuaWZlc3RGaWxlUGF0aCA9IHBhdGguam9pbih0aGlzLm91dGRpciwgTUFOSUZFU1RfRklMRSk7XG4gICAgY3hzY2hlbWEuTWFuaWZlc3Quc2F2ZUFzc2VtYmx5TWFuaWZlc3QobWFuaWZlc3QsIG1hbmlmZXN0RmlsZVBhdGgpO1xuXG4gICAgLy8gXCJiYWNrd2FyZHMgY29tcGF0aWJpbGl0eVwiOiBpbiBvcmRlciBmb3IgdGhlIG9sZCBDTEkgdG8gdGVsbCB0aGUgdXNlciB0aGV5XG4gICAgLy8gbmVlZCBhIG5ldyB2ZXJzaW9uLCB3ZSdsbCBlbWl0IHRoZSBsZWdhY3kgbWFuaWZlc3Qgd2l0aCBvbmx5IFwidmVyc2lvblwiLlxuICAgIC8vIHRoaXMgd2lsbCByZXN1bHQgaW4gYW4gZXJyb3IgXCJDREsgVG9vbGtpdCA+PSBDTE9VRF9BU1NFTUJMWV9WRVJTSU9OIGlzIHJlcXVpcmVkIGluIG9yZGVyIHRvIGludGVyYWN0IHdpdGggdGhpcyBwcm9ncmFtLlwiXG4gICAgZnMud3JpdGVGaWxlU3luYyhwYXRoLmpvaW4odGhpcy5vdXRkaXIsICdjZGsub3V0JyksIEpTT04uc3RyaW5naWZ5KHsgdmVyc2lvbjogbWFuaWZlc3QudmVyc2lvbiB9KSk7XG5cbiAgICByZXR1cm4gbmV3IENsb3VkQXNzZW1ibHkodGhpcy5vdXRkaXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXN0ZWQgY2xvdWQgYXNzZW1ibHlcbiAgICovXG4gIHB1YmxpYyBjcmVhdGVOZXN0ZWRBc3NlbWJseShhcnRpZmFjdElkOiBzdHJpbmcsIGRpc3BsYXlOYW1lOiBzdHJpbmcpIHtcbiAgICBjb25zdCBkaXJlY3RvcnlOYW1lID0gYXJ0aWZhY3RJZDtcbiAgICBjb25zdCBpbm5lckFzbURpciA9IHBhdGguam9pbih0aGlzLm91dGRpciwgZGlyZWN0b3J5TmFtZSk7XG5cbiAgICB0aGlzLmFkZEFydGlmYWN0KGFydGlmYWN0SWQsIHtcbiAgICAgIHR5cGU6IGN4c2NoZW1hLkFydGlmYWN0VHlwZS5ORVNURURfQ0xPVURfQVNTRU1CTFksXG4gICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgIGRpcmVjdG9yeU5hbWUsXG4gICAgICAgIGRpc3BsYXlOYW1lLFxuICAgICAgfSBhcyBjeHNjaGVtYS5OZXN0ZWRDbG91ZEFzc2VtYmx5UHJvcGVydGllcyxcbiAgICB9KTtcblxuICAgIHJldHVybiBuZXcgQ2xvdWRBc3NlbWJseUJ1aWxkZXIoaW5uZXJBc21EaXIsIHtcbiAgICAgIC8vIFJldXNlIHRoZSBzYW1lIGFzc2V0IG91dHB1dCBkaXJlY3RvcnkgYXMgdGhlIGN1cnJlbnQgQ2FzbSBidWlsZGVyXG4gICAgICBhc3NldE91dGRpcjogdGhpcy5hc3NldE91dGRpcixcbiAgICAgIHBhcmVudEJ1aWxkZXI6IHRoaXMsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogRGVsZXRlIHRoZSBjbG91ZCBhc3NlbWJseSBkaXJlY3RvcnlcbiAgICovXG4gIHB1YmxpYyBkZWxldGUoKSB7XG4gICAgZnMucm1TeW5jKHRoaXMub3V0ZGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSk7XG4gIH1cbn1cblxuLyoqXG4gKiBCYWNrd2FyZHMgY29tcGF0aWJpbGl0eSBmb3Igd2hlbiBgUnVudGltZUluZm9gXG4gKiB3YXMgZGVmaW5lZCBoZXJlLiBUaGlzIGlzIG5lY2Vzc2FyeSBiZWNhdXNlIGl0cyB1c2VkIGFzIGFuIGlucHV0IGluIHRoZSBzdGFibGVcbiAqIEBhd3MtY2RrL2NvcmUgbGlicmFyeS5cbiAqXG4gKiBAZGVwcmVjYXRlZCBtb3ZlZCB0byBwYWNrYWdlICdjbG91ZC1hc3NlbWJseS1zY2hlbWEnXG4gKiBAc2VlIGNvcmUuQ29uc3RydWN0Tm9kZS5zeW50aFxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJ1bnRpbWVJbmZvIGV4dGVuZHMgY3hzY2hlbWEuUnVudGltZUluZm8ge1xuXG59XG5cbi8qKlxuICogQmFja3dhcmRzIGNvbXBhdGliaWxpdHkgZm9yIHdoZW4gYE1ldGFkYXRhRW50cnlgXG4gKiB3YXMgZGVmaW5lZCBoZXJlLiBUaGlzIGlzIG5lY2Vzc2FyeSBiZWNhdXNlIGl0cyB1c2VkIGFzIGFuIGlucHV0IGluIHRoZSBzdGFibGVcbiAqIEBhd3MtY2RrL2NvcmUgbGlicmFyeS5cbiAqXG4gKiBAZGVwcmVjYXRlZCBtb3ZlZCB0byBwYWNrYWdlICdjbG91ZC1hc3NlbWJseS1zY2hlbWEnXG4gKiBAc2VlIGNvcmUuQ29uc3RydWN0Tm9kZS5tZXRhZGF0YVxuICovXG5leHBvcnQgaW50ZXJmYWNlIE1ldGFkYXRhRW50cnkgZXh0ZW5kcyBjeHNjaGVtYS5NZXRhZGF0YUVudHJ5IHtcblxufVxuXG4vKipcbiAqIEJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IGZvciB3aGVuIGBNaXNzaW5nQ29udGV4dGBcbiAqIHdhcyBkZWZpbmVkIGhlcmUuIFRoaXMgaXMgbmVjZXNzYXJ5IGJlY2F1c2UgaXRzIHVzZWQgYXMgYW4gaW5wdXQgaW4gdGhlIHN0YWJsZVxuICogQGF3cy1jZGsvY29yZSBsaWJyYXJ5LlxuICpcbiAqIEBkZXByZWNhdGVkIG1vdmVkIHRvIHBhY2thZ2UgJ2Nsb3VkLWFzc2VtYmx5LXNjaGVtYSdcbiAqIEBzZWUgY29yZS5TdGFjay5yZXBvcnRNaXNzaW5nQ29udGV4dFxuICovXG5leHBvcnQgaW50ZXJmYWNlIE1pc3NpbmdDb250ZXh0IHtcbiAgLyoqXG4gICAqIFRoZSBtaXNzaW5nIGNvbnRleHQga2V5LlxuICAgKi9cbiAgcmVhZG9ubHkga2V5OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBwcm92aWRlciBmcm9tIHdoaWNoIHdlIGV4cGVjdCB0aGlzIGNvbnRleHQga2V5IHRvIGJlIG9idGFpbmVkLlxuICAgKlxuICAgKiAoVGhpcyBpcyB0aGUgb2xkIHVudHlwZWQgZGVmaW5pdGlvbiwgd2hpY2ggaXMgbmVjZXNzYXJ5IGZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eS5cbiAgICogU2VlIGN4c2NoZW1hIGZvciBhIHR5cGUgZGVmaW5pdGlvbi4pXG4gICAqL1xuICByZWFkb25seSBwcm92aWRlcjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBIHNldCBvZiBwcm92aWRlci1zcGVjaWZpYyBvcHRpb25zLlxuICAgKlxuICAgKiAoVGhpcyBpcyB0aGUgb2xkIHVudHlwZWQgZGVmaW5pdGlvbiwgd2hpY2ggaXMgbmVjZXNzYXJ5IGZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eS5cbiAgICogU2VlIGN4c2NoZW1hIGZvciBhIHR5cGUgZGVmaW5pdGlvbi4pXG4gICAqL1xuICByZWFkb25seSBwcm9wczogUmVjb3JkPHN0cmluZywgYW55Pjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBc3NlbWJseUJ1aWxkT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBJbmNsdWRlIHRoZSBzcGVjaWZpZWQgcnVudGltZSBpbmZvcm1hdGlvbiAobW9kdWxlIHZlcnNpb25zKSBpbiBtYW5pZmVzdC5cbiAgICogQGRlZmF1bHQgLSBpZiB0aGlzIG9wdGlvbiBpcyBub3Qgc3BlY2lmaWVkLCBydW50aW1lIGluZm8gd2lsbCBub3QgYmUgaW5jbHVkZWRcbiAgICogQGRlcHJlY2F0ZWQgQWxsIHRlbXBsYXRlIG1vZGlmaWNhdGlvbnMgdGhhdCBzaG91bGQgcmVzdWx0IGZyb20gdGhpcyBzaG91bGRcbiAgICogaGF2ZSBhbHJlYWR5IGJlZW4gaW5zZXJ0ZWQgaW50byB0aGUgdGVtcGxhdGUuXG4gICAqL1xuICByZWFkb25seSBydW50aW1lSW5mbz86IFJ1bnRpbWVJbmZvO1xufVxuXG4vKipcbiAqIFJldHVybnMgYSBjb3B5IG9mIGBvYmpgIHdpdGhvdXQgdW5kZWZpbmVkIHZhbHVlcyBpbiBtYXBzIG9yIGFycmF5cy5cbiAqL1xuZnVuY3Rpb24gZmlsdGVyVW5kZWZpbmVkKG9iajogYW55KTogYW55IHtcbiAgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkge1xuICAgIHJldHVybiBvYmouZmlsdGVyKHggPT4geCAhPT0gdW5kZWZpbmVkKS5tYXAoeCA9PiBmaWx0ZXJVbmRlZmluZWQoeCkpO1xuICB9XG5cbiAgaWYgKHR5cGVvZihvYmopID09PSAnb2JqZWN0Jykge1xuICAgIGNvbnN0IHJldDogYW55ID0geyB9O1xuICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKG9iaikpIHtcbiAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuICAgICAgcmV0W2tleV0gPSBmaWx0ZXJVbmRlZmluZWQodmFsdWUpO1xuICAgIH1cbiAgICByZXR1cm4gcmV0O1xuICB9XG5cbiAgcmV0dXJuIG9iajtcbn1cblxuZnVuY3Rpb24gaWdub3JlKF94OiBhbnkpIHtcbiAgcmV0dXJuO1xufVxuXG4vKipcbiAqIFR1cm4gdGhlIGdpdmVuIG9wdGlvbmFsIG91dHB1dCBkaXJlY3RvcnkgaW50byBhIGZpeGVkIG91dHB1dCBkaXJlY3RvcnlcbiAqL1xuZnVuY3Rpb24gZGV0ZXJtaW5lT3V0cHV0RGlyZWN0b3J5KG91dGRpcj86IHN0cmluZykge1xuICByZXR1cm4gb3V0ZGlyID8/IGZzLm1rZHRlbXBTeW5jKHBhdGguam9pbihmcy5yZWFscGF0aFN5bmMob3MudG1wZGlyKCkpLCAnY2RrLm91dCcpKTtcbn1cblxuZnVuY3Rpb24gZW5zdXJlRGlyU3luYyhkaXI6IHN0cmluZykge1xuICBpZiAoZnMuZXhpc3RzU3luYyhkaXIpKSB7XG4gICAgaWYgKCFmcy5zdGF0U3luYyhkaXIpLmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgIHRocm93IG5ldyBDbG91ZEFzc2VtYmx5RXJyb3IoYCR7ZGlyfSBtdXN0IGJlIGEgZGlyZWN0b3J5YCk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGZzLm1rZGlyU3luYyhkaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICB9XG59XG4iXX0=