UNPKG

@aws-cdk/aws-apigateway

Version:

The CDK Construct Library for AWS::ApiGateway

380 lines 51.4 kB
"use strict"; var _a, _b, _c; Object.defineProperty(exports, "__esModule", { value: true }); exports.ProxyResource = exports.Resource = exports.ResourceBase = void 0; const jsiiDeprecationWarnings = require("../.warnings.jsii.js"); const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const core_1 = require("@aws-cdk/core"); const apigateway_generated_1 = require("./apigateway.generated"); const cors_1 = require("./cors"); const integrations_1 = require("./integrations"); const method_1 = require("./method"); class ResourceBase extends core_1.Resource { constructor(scope, id) { super(scope, id); this.children = {}; } addResource(pathPart, options) { try { jsiiDeprecationWarnings._aws_cdk_aws_apigateway_ResourceOptions(options); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.addResource); } throw error; } return new Resource(this, pathPart, { parent: this, pathPart, ...options }); } addMethod(httpMethod, integration, options) { try { jsiiDeprecationWarnings._aws_cdk_aws_apigateway_Integration(integration); jsiiDeprecationWarnings._aws_cdk_aws_apigateway_MethodOptions(options); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.addMethod); } throw error; } return new method_1.Method(this, httpMethod, { resource: this, httpMethod, integration, options }); } addProxy(options) { try { jsiiDeprecationWarnings._aws_cdk_aws_apigateway_ProxyResourceOptions(options); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.addProxy); } throw error; } return new ProxyResource(this, '{proxy+}', { parent: this, ...options }); } addCorsPreflight(options) { try { jsiiDeprecationWarnings._aws_cdk_aws_apigateway_CorsOptions(options); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.addCorsPreflight); } throw error; } const headers = {}; // // Access-Control-Allow-Headers const allowHeaders = options.allowHeaders || cors_1.Cors.DEFAULT_HEADERS; headers['Access-Control-Allow-Headers'] = `'${allowHeaders.join(',')}'`; // // Access-Control-Allow-Origin if (options.allowOrigins.length === 0) { throw new Error('allowOrigins must contain at least one origin'); } if (options.allowOrigins.includes('*') && options.allowOrigins.length > 1) { throw new Error(`Invalid "allowOrigins" - cannot mix "*" with specific origins: ${options.allowOrigins.join(',')}`); } // we use the first origin here and if there are more origins in the list, we // will match against them in the response velocity template const initialOrigin = options.allowOrigins[0]; headers['Access-Control-Allow-Origin'] = `'${initialOrigin}'`; // the "Vary" header is required if we allow a specific origin // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin#CORS_and_caching if (initialOrigin !== '*') { headers.Vary = '\'Origin\''; } // // Access-Control-Allow-Methods let allowMethods = options.allowMethods || cors_1.Cors.ALL_METHODS; if (allowMethods.includes('ANY')) { if (allowMethods.length > 1) { throw new Error(`ANY cannot be used with any other method. Received: ${allowMethods.join(',')}`); } allowMethods = cors_1.Cors.ALL_METHODS; } headers['Access-Control-Allow-Methods'] = `'${allowMethods.join(',')}'`; // // Access-Control-Allow-Credentials if (options.allowCredentials) { headers['Access-Control-Allow-Credentials'] = '\'true\''; } // // Access-Control-Max-Age let maxAgeSeconds; if (options.maxAge && options.disableCache) { throw new Error('The options "maxAge" and "disableCache" are mutually exclusive'); } if (options.maxAge) { maxAgeSeconds = options.maxAge.toSeconds(); } if (options.disableCache) { maxAgeSeconds = -1; } if (maxAgeSeconds) { headers['Access-Control-Max-Age'] = `'${maxAgeSeconds}'`; } // // Access-Control-Expose-Headers // if (options.exposeHeaders) { headers['Access-Control-Expose-Headers'] = `'${options.exposeHeaders.join(',')}'`; } // // statusCode const statusCode = options.statusCode ?? 204; // // prepare responseParams const integrationResponseParams = {}; const methodResponseParams = {}; for (const [name, value] of Object.entries(headers)) { const key = `method.response.header.${name}`; integrationResponseParams[key] = value; methodResponseParams[key] = true; } return this.addMethod('OPTIONS', new integrations_1.MockIntegration({ requestTemplates: { 'application/json': '{ statusCode: 200 }' }, integrationResponses: [ { statusCode: `${statusCode}`, responseParameters: integrationResponseParams, responseTemplates: renderResponseTemplate() }, ], }), { methodResponses: [ { statusCode: `${statusCode}`, responseParameters: methodResponseParams }, ], }); // renders the response template to match all possible origins (if we have more than one) function renderResponseTemplate() { const origins = options.allowOrigins.slice(1); if (origins.length === 0) { return undefined; } const template = new Array(); template.push('#set($origin = $input.params().header.get("Origin"))'); template.push('#if($origin == "") #set($origin = $input.params().header.get("origin")) #end'); const condition = origins.map(o => `$origin.matches("${o}")`).join(' || '); template.push(`#if(${condition})`); template.push(' #set($context.responseOverride.header.Access-Control-Allow-Origin = $origin)'); template.push('#end'); return { 'application/json': template.join('\n'), }; } } getResource(pathPart) { return this.children[pathPart]; } /** * @internal */ _trackChild(pathPart, resource) { this.children[pathPart] = resource; } resourceForPath(path) { if (!path) { return this; } if (path.startsWith('/')) { if (this.path !== '/') { throw new Error(`Path may start with "/" only for the resource, but we are at: ${this.path}`); } // trim trailing "/" return this.resourceForPath(path.slice(1)); } const parts = path.split('/'); const next = parts.shift(); if (!next || next === '') { throw new Error('resourceForPath cannot be called with an empty path'); } let resource = this.getResource(next); if (!resource) { resource = this.addResource(next); } return resource.resourceForPath(parts.join('/')); } /** * @deprecated - Throws error in some use cases that have been enabled since this deprecation notice. Use `RestApi.urlForPath()` instead. */ get url() { try { jsiiDeprecationWarnings.print("@aws-cdk/aws-apigateway.ResourceBase#url", "- Throws error in some use cases that have been enabled since this deprecation notice. Use `RestApi.urlForPath()` instead."); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, jsiiDeprecationWarnings.getPropertyDescriptor(this, "url").get); } throw error; } return this.restApi.urlForPath(this.path); } } exports.ResourceBase = ResourceBase; _a = JSII_RTTI_SYMBOL_1; ResourceBase[_a] = { fqn: "@aws-cdk/aws-apigateway.ResourceBase", version: "1.204.0" }; class Resource extends ResourceBase { constructor(scope, id, props) { super(scope, id); try { jsiiDeprecationWarnings._aws_cdk_aws_apigateway_ResourceProps(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, Resource); } throw error; } validateResourcePathPart(props.pathPart); this.parentResource = props.parent; if (props.parent instanceof ResourceBase) { props.parent._trackChild(props.pathPart, this); } const resourceProps = { restApiId: props.parent.api.restApiId, parentId: props.parent.resourceId, pathPart: props.pathPart, }; const resource = new apigateway_generated_1.CfnResource(this, 'Resource', resourceProps); this.resourceId = resource.ref; this.api = props.parent.api; // render resource path (special case for root) this.path = props.parent.path; if (!this.path.endsWith('/')) { this.path += '/'; } this.path += props.pathPart; const deployment = props.parent.api.latestDeployment; if (deployment) { deployment.node.addDependency(resource); deployment.addToLogicalId({ resource: resourceProps }); } // setup defaults based on properties and inherit from parent. method defaults // are inherited per property, so children can override piecemeal. this.defaultIntegration = props.defaultIntegration || props.parent.defaultIntegration; this.defaultMethodOptions = { ...props.parent.defaultMethodOptions, ...props.defaultMethodOptions, }; this.defaultCorsPreflightOptions = props.defaultCorsPreflightOptions || props.parent.defaultCorsPreflightOptions; if (this.defaultCorsPreflightOptions) { this.addCorsPreflight(this.defaultCorsPreflightOptions); } } /** * Import an existing resource */ static fromResourceAttributes(scope, id, attrs) { try { jsiiDeprecationWarnings._aws_cdk_aws_apigateway_ResourceAttributes(attrs); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.fromResourceAttributes); } throw error; } class Import extends ResourceBase { constructor() { super(...arguments); this.api = attrs.restApi; this.resourceId = attrs.resourceId; this.path = attrs.path; this.defaultIntegration = undefined; this.defaultMethodOptions = undefined; this.defaultCorsPreflightOptions = undefined; } get parentResource() { throw new Error('parentResource is not configured for imported resource.'); } get restApi() { throw new Error('restApi is not configured for imported resource.'); } } return new Import(scope, id); } /** * The RestApi associated with this Resource * @deprecated - Throws an error if this Resource is not associated with an instance of `RestApi`. Use `api` instead. */ get restApi() { try { jsiiDeprecationWarnings.print("@aws-cdk/aws-apigateway.Resource#restApi", "- Throws an error if this Resource is not associated with an instance of `RestApi`. Use `api` instead."); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, jsiiDeprecationWarnings.getPropertyDescriptor(this, "restApi").get); } throw error; } if (!this.parentResource) { throw new Error('parentResource was unexpectedly not defined'); } return this.parentResource.restApi; } } exports.Resource = Resource; _b = JSII_RTTI_SYMBOL_1; Resource[_b] = { fqn: "@aws-cdk/aws-apigateway.Resource", version: "1.204.0" }; /** * Defines a {proxy+} greedy resource and an ANY method on a route. * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-set-up-simple-proxy.html */ class ProxyResource extends Resource { constructor(scope, id, props) { super(scope, id, { parent: props.parent, pathPart: '{proxy+}', defaultIntegration: props.defaultIntegration, defaultMethodOptions: props.defaultMethodOptions, }); try { jsiiDeprecationWarnings._aws_cdk_aws_apigateway_ProxyResourceProps(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, ProxyResource); } throw error; } const anyMethod = props.anyMethod ?? true; if (anyMethod) { this.anyMethod = this.addMethod('ANY'); } } addMethod(httpMethod, integration, options) { try { jsiiDeprecationWarnings._aws_cdk_aws_apigateway_Integration(integration); jsiiDeprecationWarnings._aws_cdk_aws_apigateway_MethodOptions(options); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.addMethod); } throw error; } // In case this proxy is mounted under the root, also add this method to // the root so that empty paths are proxied as well. if (this.parentResource && this.parentResource.path === '/') { // skip if the root resource already has this method defined if (!(this.parentResource.node.tryFindChild(httpMethod) instanceof method_1.Method)) { this.parentResource.addMethod(httpMethod, integration, options); } } return super.addMethod(httpMethod, integration, options); } } exports.ProxyResource = ProxyResource; _c = JSII_RTTI_SYMBOL_1; ProxyResource[_c] = { fqn: "@aws-cdk/aws-apigateway.ProxyResource", version: "1.204.0" }; function validateResourcePathPart(part) { // strip {} which indicate this is a parameter if (part.startsWith('{') && part.endsWith('}')) { part = part.slice(1, -1); // proxy resources are allowed to end with a '+' if (part.endsWith('+')) { part = part.slice(0, -1); } } if (!/^[a-zA-Z0-9\.\_\-]+$/.test(part)) { throw new Error(`Resource's path part only allow [a-zA-Z0-9._-], an optional trailing '+' and curly braces at the beginning and the end: ${part}`); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzb3VyY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJyZXNvdXJjZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSx3Q0FBMEY7QUFFMUYsaUVBQXVFO0FBQ3ZFLGlDQUEyQztBQUUzQyxpREFBaUQ7QUFDakQscUNBQWlEO0FBNEpqRCxNQUFzQixZQUFhLFNBQVEsZUFBaUI7SUFlMUQsWUFBWSxLQUFnQixFQUFFLEVBQVU7UUFDdEMsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUhGLGFBQVEsR0FBcUMsRUFBRyxDQUFDO0tBSWpFO0lBRU0sV0FBVyxDQUFDLFFBQWdCLEVBQUUsT0FBeUI7Ozs7Ozs7Ozs7UUFDNUQsT0FBTyxJQUFJLFFBQVEsQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsR0FBRyxPQUFPLEVBQUUsQ0FBQyxDQUFDO0tBQzdFO0lBRU0sU0FBUyxDQUFDLFVBQWtCLEVBQUUsV0FBeUIsRUFBRSxPQUF1Qjs7Ozs7Ozs7Ozs7UUFDckYsT0FBTyxJQUFJLGVBQU0sQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsV0FBVyxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUM7S0FDM0Y7SUFFTSxRQUFRLENBQUMsT0FBOEI7Ozs7Ozs7Ozs7UUFDNUMsT0FBTyxJQUFJLGFBQWEsQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxHQUFHLE9BQU8sRUFBRSxDQUFDLENBQUM7S0FDMUU7SUFFTSxnQkFBZ0IsQ0FBQyxPQUFvQjs7Ozs7Ozs7OztRQUMxQyxNQUFNLE9BQU8sR0FBK0IsRUFBRyxDQUFDO1FBRWhELEVBQUU7UUFDRiwrQkFBK0I7UUFFL0IsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLFlBQVksSUFBSSxXQUFJLENBQUMsZUFBZSxDQUFD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QUFnRDtRQUNoRCxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFDdEIsSUFBSSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDMUI7S0FDRjtJQUVELElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUU7UUFDdEMsTUFBTSxJQUFJLEtBQUssQ0FBQzt1REFDbUMsSUFBSSxFQUFFLENBQUMsQ0FBQztLQUM1RDtBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJUmVzb3VyY2UgYXMgSVJlc291cmNlQmFzZSwgUmVzb3VyY2UgYXMgUmVzb3VyY2VDb25zdHJ1Y3QgfSBmcm9tICdAYXdzLWNkay9jb3JlJztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgQ2ZuUmVzb3VyY2UsIENmblJlc291cmNlUHJvcHMgfSBmcm9tICcuL2FwaWdhdGV3YXkuZ2VuZXJhdGVkJztcbmltcG9ydCB7IENvcnMsIENvcnNPcHRpb25zIH0gZnJvbSAnLi9jb3JzJztcbmltcG9ydCB7IEludGVncmF0aW9uIH0gZnJvbSAnLi9pbnRlZ3JhdGlvbic7XG5pbXBvcnQgeyBNb2NrSW50ZWdyYXRpb24gfSBmcm9tICcuL2ludGVncmF0aW9ucyc7XG5pbXBvcnQgeyBNZXRob2QsIE1ldGhvZE9wdGlvbnMgfSBmcm9tICcuL21ldGhvZCc7XG5pbXBvcnQgeyBJUmVzdEFwaSwgUmVzdEFwaSB9IGZyb20gJy4vcmVzdGFwaSc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgSVJlc291cmNlIGV4dGVuZHMgSVJlc291cmNlQmFzZSB7XG4gIC8qKlxuICAgKiBUaGUgcGFyZW50IG9mIHRoaXMgcmVzb3VyY2Ugb3IgdW5kZWZpbmVkIGZvciB0aGUgcm9vdCByZXNvdXJjZS5cbiAgICovXG4gIHJlYWRvbmx5IHBhcmVudFJlc291cmNlPzogSVJlc291cmNlO1xuXG4gIC8qKlxuICAgKiBUaGUgcmVzdCBBUEkgdGhhdCB0aGlzIHJlc291cmNlIGlzIHBhcnQgb2YuXG4gICAqXG4gICAqIEBkZXByZWNhdGVkIC0gVGhyb3dzIGFuIGVycm9yIGlmIHRoaXMgUmVzb3VyY2UgaXMgbm90IGFzc29jaWF0ZWQgd2l0aCBhbiBpbnN0YW5jZSBvZiBgUmVzdEFwaWAuIFVzZSBgYXBpYCBpbnN0ZWFkLlxuICAgKi9cbiAgcmVhZG9ubHkgcmVzdEFwaTogUmVzdEFwaTtcblxuICAvKipcbiAgICogVGhlIHJlc3QgQVBJIHRoYXQgdGhpcyByZXNvdXJjZSBpcyBwYXJ0IG9mLlxuICAgKlxuICAgKiBUaGUgcmVhc29uIHdlIG5lZWQgdGhlIFJlc3RBcGkgb2JqZWN0IGl0c2VsZiBhbmQgbm90IGp1c3QgdGhlIElEIGlzIGJlY2F1c2UgdGhlIG1vZGVsXG4gICAqIGlzIGJlaW5nIHRyYWNrZWQgYnkgdGhlIHRvcC1sZXZlbCBSZXN0QXBpIG9iamVjdCBmb3IgdGhlIHB1cnBvc2Ugb2YgY2FsY3VsYXRpbmcgaXQnc1xuICAgKiBoYXNoIHRvIGRldGVybWluZSB0aGUgSUQgb2YgdGhlIGRlcGxveW1lbnQuIFRoaXMgYWxsb3dzIHVzIHRvIGF1dG9tYXRpY2FsbHkgdXBkYXRlXG4gICAqIHRoZSBkZXBsb3ltZW50IHdoZW4gdGhlIG1vZGVsIG9mIHRoZSBSRVNUIEFQSSBjaGFuZ2VzLlxuICAgKi9cbiAgcmVhZG9ubHkgYXBpOiBJUmVzdEFwaTtcblxuICAvKipcbiAgICogVGhlIElEIG9mIHRoZSByZXNvdXJjZS5cbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcmVhZG9ubHkgcmVzb3VyY2VJZDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgZnVsbCBwYXRoIG9mIHRoaXMgcmVzb3VyY2UuXG4gICAqL1xuICByZWFkb25seSBwYXRoOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEFuIGludGVncmF0aW9uIHRvIHVzZSBhcyBhIGRlZmF1bHQgZm9yIGFsbCBtZXRob2RzIGNyZWF0ZWQgd2l0aGluIHRoaXNcbiAgICogQVBJIHVubGVzcyBhbiBpbnRlZ3JhdGlvbiBpcyBzcGVjaWZpZWQuXG4gICAqL1xuICByZWFkb25seSBkZWZhdWx0SW50ZWdyYXRpb24/OiBJbnRlZ3JhdGlvbjtcblxuICAvKipcbiAgICogTWV0aG9kIG9wdGlvbnMgdG8gdXNlIGFzIGEgZGVmYXVsdCBmb3IgYWxsIG1ldGhvZHMgY3JlYXRlZCB3aXRoaW4gdGhpc1xuICAgKiBBUEkgdW5sZXNzIGN1c3RvbSBvcHRpb25zIGFyZSBzcGVjaWZpZWQuXG4gICAqL1xuICByZWFkb25seSBkZWZhdWx0TWV0aG9kT3B0aW9ucz86IE1ldGhvZE9wdGlvbnM7XG5cbiAgLyoqXG4gICAqIERlZmF1bHQgb3B0aW9ucyBmb3IgQ09SUyBwcmVmbGlnaHQgT1BUSU9OUyBtZXRob2QuXG4gICAqL1xuICByZWFkb25seSBkZWZhdWx0Q29yc1ByZWZsaWdodE9wdGlvbnM/OiBDb3JzT3B0aW9ucztcblxuICAvKipcbiAgICogR2V0cyBvciBjcmVhdGUgYWxsIHJlc291cmNlcyBsZWFkaW5nIHVwIHRvIHRoZSBzcGVjaWZpZWQgcGF0aC5cbiAgICpcbiAgICogLSBQYXRoIG1heSBvbmx5IHN0YXJ0IHdpdGggXCIvXCIgaWYgdGhpcyBtZXRob2QgaXMgY2FsbGVkIG9uIHRoZSByb290IHJlc291cmNlLlxuICAgKiAtIEFsbCByZXNvdXJjZXMgYXJlIGNyZWF0ZWQgdXNpbmcgZGVmYXVsdCBvcHRpb25zLlxuICAgKlxuICAgKiBAcGFyYW0gcGF0aCBUaGUgcmVsYXRpdmUgcGF0aFxuICAgKiBAcmV0dXJucyBhIG5ldyBvciBleGlzdGluZyByZXNvdXJjZS5cbiAgICovXG4gIHJlc291cmNlRm9yUGF0aChwYXRoOiBzdHJpbmcpOiBSZXNvdXJjZTtcblxuICAvKipcbiAgICogRGVmaW5lcyBhIG5ldyBjaGlsZCByZXNvdXJjZSB3aGVyZSB0aGlzIHJlc291cmNlIGlzIHRoZSBwYXJlbnQuXG4gICAqIEBwYXJhbSBwYXRoUGFydCBUaGUgcGF0aCBwYXJ0IGZvciB0aGUgY2hpbGQgcmVzb3VyY2VcbiAgICogQHBhcmFtIG9wdGlvbnMgUmVzb3VyY2Ugb3B0aW9uc1xuICAgKiBAcmV0dXJucyBBIFJlc291cmNlIG9iamVjdFxuICAgKi9cbiAgYWRkUmVzb3VyY2UocGF0aFBhcnQ6IHN0cmluZywgb3B0aW9ucz86IFJlc291cmNlT3B0aW9ucyk6IFJlc291cmNlO1xuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgYSBjaGlsZCByZXNvdXJjZSBieSBwYXRoIHBhcnQuXG4gICAqXG4gICAqIEBwYXJhbSBwYXRoUGFydCBUaGUgcGF0aCBwYXJ0IG9mIHRoZSBjaGlsZCByZXNvdXJjZVxuICAgKiBAcmV0dXJucyB0aGUgY2hpbGQgcmVzb3VyY2Ugb3IgdW5kZWZpbmVkIGlmIG5vdCBmb3VuZFxuICAgKi9cbiAgZ2V0UmVzb3VyY2UocGF0aFBhcnQ6IHN0cmluZyk6IElSZXNvdXJjZSB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQWRkcyBhIGdyZWVkeSBwcm94eSByZXNvdXJjZSAoXCJ7cHJveHkrfVwiKSBhbmQgYW4gQU5ZIG1ldGhvZCB0byB0aGlzIHJvdXRlLlxuICAgKiBAcGFyYW0gb3B0aW9ucyBEZWZhdWx0IGludGVncmF0aW9uIGFuZCBtZXRob2Qgb3B0aW9ucy5cbiAgICovXG4gIGFkZFByb3h5KG9wdGlvbnM/OiBQcm94eVJlc291cmNlT3B0aW9ucyk6IFByb3h5UmVzb3VyY2U7XG5cbiAgLyoqXG4gICAqIERlZmluZXMgYSBuZXcgbWV0aG9kIGZvciB0aGlzIHJlc291cmNlLlxuICAgKiBAcGFyYW0gaHR0cE1ldGhvZCBUaGUgSFRUUCBtZXRob2RcbiAgICogQHBhcmFtIHRhcmdldCBUaGUgdGFyZ2V0IGJhY2tlbmQgaW50ZWdyYXRpb24gZm9yIHRoaXMgbWV0aG9kXG4gICAqIEBwYXJhbSBvcHRpb25zIE1ldGhvZCBvcHRpb25zLCBzdWNoIGFzIGF1dGhlbnRpY2F0aW9uLlxuICAgKlxuICAgKiBAcmV0dXJucyBUaGUgbmV3bHkgY3JlYXRlZCBgTWV0aG9kYCBvYmplY3QuXG4gICAqL1xuICBhZGRNZXRob2QoaHR0cE1ldGhvZDogc3RyaW5nLCB0YXJnZXQ/OiBJbnRlZ3JhdGlvbiwgb3B0aW9ucz86IE1ldGhvZE9wdGlvbnMpOiBNZXRob2Q7XG5cbiAgLyoqXG4gICAqIEFkZHMgYW4gT1BUSU9OUyBtZXRob2QgdG8gdGhpcyByZXNvdXJjZSB3aGljaCByZXNwb25kcyB0byBDcm9zcy1PcmlnaW5cbiAgICogUmVzb3VyY2UgU2hhcmluZyAoQ09SUykgcHJlZmxpZ2h0IHJlcXVlc3RzLlxuICAgKlxuICAgKiBDcm9zcy1PcmlnaW4gUmVzb3VyY2UgU2hhcmluZyAoQ09SUykgaXMgYSBtZWNoYW5pc20gdGhhdCB1c2VzIGFkZGl0aW9uYWxcbiAgICogSFRUUCBoZWFkZXJzIHRvIHRlbGwgYnJvd3NlcnMgdG8gZ2l2ZSBhIHdlYiBhcHBsaWNhdGlvbiBydW5uaW5nIGF0IG9uZVxuICAgKiBvcmlnaW4sIGFjY2VzcyB0byBzZWxlY3RlZCByZXNvdXJjZXMgZnJvbSBhIGRpZmZlcmVudCBvcmlnaW4uIEEgd2ViXG4gICAqIGFwcGxpY2F0aW9uIGV4ZWN1dGVzIGEgY3Jvc3Mtb3JpZ2luIEhUVFAgcmVxdWVzdCB3aGVuIGl0IHJlcXVlc3RzIGFcbiAgICogcmVzb3VyY2UgdGhhdCBoYXMgYSBkaWZmZXJlbnQgb3JpZ2luIChkb21haW4sIHByb3RvY29sLCBvciBwb3J0KSBmcm9tIGl0c1xuICAgKiBvd24uXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSFRUUC9DT1JTXG4gICAqIEBwYXJhbSBvcHRpb25zIENPUlMgb3B0aW9uc1xuICAgKiBAcmV0dXJucyBhIGBNZXRob2RgIG9iamVjdFxuICAgKi9cbiAgYWRkQ29yc1ByZWZsaWdodChvcHRpb25zOiBDb3JzT3B0aW9ucyk6IE1ldGhvZDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXNvdXJjZU9wdGlvbnMge1xuICAvKipcbiAgICogQW4gaW50ZWdyYXRpb24gdG8gdXNlIGFzIGEgZGVmYXVsdCBmb3IgYWxsIG1ldGhvZHMgY3JlYXRlZCB3aXRoaW4gdGhpc1xuICAgKiBBUEkgdW5sZXNzIGFuIGludGVncmF0aW9uIGlzIHNwZWNpZmllZC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBJbmhlcml0ZWQgZnJvbSBwYXJlbnQuXG4gICAqL1xuICByZWFkb25seSBkZWZhdWx0SW50ZWdyYXRpb24/OiBJbnRlZ3JhdGlvbjtcblxuICAvKipcbiAgICogTWV0aG9kIG9wdGlvbnMgdG8gdXNlIGFzIGEgZGVmYXVsdCBmb3IgYWxsIG1ldGhvZHMgY3JlYXRlZCB3aXRoaW4gdGhpc1xuICAgKiBBUEkgdW5sZXNzIGN1c3RvbSBvcHRpb25zIGFyZSBzcGVjaWZpZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gSW5oZXJpdGVkIGZyb20gcGFyZW50LlxuICAgKi9cbiAgcmVhZG9ubHkgZGVmYXVsdE1ldGhvZE9wdGlvbnM/OiBNZXRob2RPcHRpb25zO1xuXG4gIC8qKlxuICAgKiBBZGRzIGEgQ09SUyBwcmVmbGlnaHQgT1BUSU9OUyBtZXRob2QgdG8gdGhpcyByZXNvdXJjZSBhbmQgYWxsIGNoaWxkXG4gICAqIHJlc291cmNlcy5cbiAgICpcbiAgICogWW91IGNhbiBhZGQgQ09SUyBhdCB0aGUgcmVzb3VyY2UtbGV2ZWwgdXNpbmcgYGFkZENvcnNQcmVmbGlnaHRgLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIENPUlMgaXMgZGlzYWJsZWRcbiAgICovXG4gIHJlYWRvbmx5IGRlZmF1bHRDb3JzUHJlZmxpZ2h0T3B0aW9ucz86IENvcnNPcHRpb25zO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlc291cmNlUHJvcHMgZXh0ZW5kcyBSZXNvdXJjZU9wdGlvbnMge1xuICAvKipcbiAgICogVGhlIHBhcmVudCByZXNvdXJjZSBvZiB0aGlzIHJlc291cmNlLiBZb3UgY2FuIGVpdGhlciBwYXNzIGFub3RoZXJcbiAgICogYFJlc291cmNlYCBvYmplY3Qgb3IgYSBgUmVzdEFwaWAgb2JqZWN0IGhlcmUuXG4gICAqL1xuICByZWFkb25seSBwYXJlbnQ6IElSZXNvdXJjZTtcblxuICAvKipcbiAgICogQSBwYXRoIG5hbWUgZm9yIHRoZSByZXNvdXJjZS5cbiAgICovXG4gIHJlYWRvbmx5IHBhdGhQYXJ0OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBSZXNvdXJjZUJhc2UgZXh0ZW5kcyBSZXNvdXJjZUNvbnN0cnVjdCBpbXBsZW1lbnRzIElSZXNvdXJjZSB7XG4gIHB1YmxpYyBhYnN0cmFjdCByZWFkb25seSBwYXJlbnRSZXNvdXJjZT86IElSZXNvdXJjZTtcbiAgLyoqXG4gICAqIEBkZXByZWNhdGVkIC0gIFRocm93cyBhbiBlcnJvciBpZiB0aGlzIFJlc291cmNlIGlzIG5vdCBhc3NvY2lhdGVkIHdpdGggYW4gaW5zdGFuY2Ugb2YgYFJlc3RBcGlgLiBVc2UgYGFwaWAgaW5zdGVhZC5cbiAgICovXG4gIHB1YmxpYyBhYnN0cmFjdCByZWFkb25seSByZXN0QXBpOiBSZXN0QXBpO1xuICBwdWJsaWMgYWJzdHJhY3QgcmVhZG9ubHkgYXBpOiBJUmVzdEFwaTtcbiAgcHVibGljIGFic3RyYWN0IHJlYWRvbmx5IHJlc291cmNlSWQ6IHN0cmluZztcbiAgcHVibGljIGFic3RyYWN0IHJlYWRvbmx5IHBhdGg6IHN0cmluZztcbiAgcHVibGljIGFic3RyYWN0IHJlYWRvbmx5IGRlZmF1bHRJbnRlZ3JhdGlvbj86IEludGVncmF0aW9uO1xuICBwdWJsaWMgYWJzdHJhY3QgcmVhZG9ubHkgZGVmYXVsdE1ldGhvZE9wdGlvbnM/OiBNZXRob2RPcHRpb25zO1xuICBwdWJsaWMgYWJzdHJhY3QgcmVhZG9ubHkgZGVmYXVsdENvcnNQcmVmbGlnaHRPcHRpb25zPzogQ29yc09wdGlvbnM7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBjaGlsZHJlbjogeyBbcGF0aFBhcnQ6IHN0cmluZ106IFJlc291cmNlIH0gPSB7IH07XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG4gIH1cblxuICBwdWJsaWMgYWRkUmVzb3VyY2UocGF0aFBhcnQ6IHN0cmluZywgb3B0aW9ucz86IFJlc291cmNlT3B0aW9ucyk6IFJlc291cmNlIHtcbiAgICByZXR1cm4gbmV3IFJlc291cmNlKHRoaXMsIHBhdGhQYXJ0LCB7IHBhcmVudDogdGhpcywgcGF0aFBhcnQsIC4uLm9wdGlvbnMgfSk7XG4gIH1cblxuICBwdWJsaWMgYWRkTWV0aG9kKGh0dHBNZXRob2Q6IHN0cmluZywgaW50ZWdyYXRpb24/OiBJbnRlZ3JhdGlvbiwgb3B0aW9ucz86IE1ldGhvZE9wdGlvbnMpOiBNZXRob2Qge1xuICAgIHJldHVybiBuZXcgTWV0aG9kKHRoaXMsIGh0dHBNZXRob2QsIHsgcmVzb3VyY2U6IHRoaXMsIGh0dHBNZXRob2QsIGludGVncmF0aW9uLCBvcHRpb25zIH0pO1xuICB9XG5cbiAgcHVibGljIGFkZFByb3h5KG9wdGlvbnM/OiBQcm94eVJlc291cmNlT3B0aW9ucyk6IFByb3h5UmVzb3VyY2Uge1xuICAgIHJldHVybiBuZXcgUHJveHlSZXNvdXJjZSh0aGlzLCAne3Byb3h5K30nLCB7IHBhcmVudDogdGhpcywgLi4ub3B0aW9ucyB9KTtcbiAgfVxuXG4gIHB1YmxpYyBhZGRDb3JzUHJlZmxpZ2h0KG9wdGlvbnM6IENvcnNPcHRpb25zKSB7XG4gICAgY29uc3QgaGVhZGVyczogeyBbbmFtZTogc3RyaW5nXTogc3RyaW5nIH0gPSB7IH07XG5cbiAgICAvL1xuICAgIC8vIEFjY2Vzcy1Db250cm9sLUFsbG93LUhlYWRlcnNcblxuICAgIGNvbnN0IGFsbG93SGVhZGVycyA9IG9wdGlvbnMuYWxsb3dIZWFkZXJzIHx8IENvcnMuREVGQVVMVF9IRUFERVJTO1xuICAgIGhlYWRlcnNbJ0FjY2Vzcy1Db250cm9sLUFsbG93LUhlYWRlcnMnXSA9IGAnJHthbGxvd0hlYWRlcnMuam9pbignLCcpfSdgO1xuXG4gICAgLy9cbiAgICAvLyBBY2Nlc3MtQ29udHJvbC1BbGxvdy1PcmlnaW5cblxuICAgIGlmIChvcHRpb25zLmFsbG93T3JpZ2lucy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignYWxsb3dPcmlnaW5zIG11c3QgY29udGFpbiBhdCBsZWFzdCBvbmUgb3JpZ2luJyk7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnMuYWxsb3dPcmlnaW5zLmluY2x1ZGVzKCcqJykgJiYgb3B0aW9ucy5hbGxvd09yaWdpbnMubGVuZ3RoID4gMSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIFwiYWxsb3dPcmlnaW5zXCIgLSBjYW5ub3QgbWl4IFwiKlwiIHdpdGggc3BlY2lmaWMgb3JpZ2luczogJHtvcHRpb25zLmFsbG93T3JpZ2lucy5qb2luKCcsJyl9YCk7XG4gICAgfVxuXG4gICAgLy8gd2UgdXNlIHRoZSBmaXJzdCBvcmlnaW4gaGVyZSBhbmQgaWYgdGhlcmUgYXJlIG1vcmUgb3JpZ2lucyBpbiB0aGUgbGlzdCwgd2VcbiAgICAvLyB3aWxsIG1hdGNoIGFnYWluc3QgdGhlbSBpbiB0aGUgcmVzcG9uc2UgdmVsb2NpdHkgdGVtcGxhdGVcbiAgICBjb25zdCBpbml0aWFsT3JpZ2luID0gb3B0aW9ucy5hbGxvd09yaWdpbnNbMF07XG4gICAgaGVhZGVyc1snQWNjZXNzLUNvbnRyb2wtQWxsb3ctT3JpZ2luJ10gPSBgJyR7aW5pdGlhbE9yaWdpbn0nYDtcblxuICAgIC8vIHRoZSBcIlZhcnlcIiBoZWFkZXIgaXMgcmVxdWlyZWQgaWYgd2UgYWxsb3cgYSBzcGVjaWZpYyBvcmlnaW5cbiAgICAvLyBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9IVFRQL0hlYWRlcnMvQWNjZXNzLUNvbnRyb2wtQWxsb3ctT3JpZ2luI0NPUlNfYW5kX2NhY2hpbmdcbiAgICBpZiAoaW5pdGlhbE9yaWdpbiAhPT0gJyonKSB7XG4gICAgICBoZWFkZXJzLlZhcnkgPSAnXFwnT3JpZ2luXFwnJztcbiAgICB9XG5cbiAgICAvL1xuICAgIC8vIEFjY2Vzcy1Db250cm9sLUFsbG93LU1ldGhvZHNcblxuICAgIGxldCBhbGxvd01ldGhvZHMgPSBvcHRpb25zLmFsbG93TWV0aG9kcyB8fCBDb3JzLkFMTF9NRVRIT0RTO1xuXG4gICAgaWYgKGFsbG93TWV0aG9kcy5pbmNsdWRlcygnQU5ZJykpIHtcbiAgICAgIGlmIChhbGxvd01ldGhvZHMubGVuZ3RoID4gMSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEFOWSBjYW5ub3QgYmUgdXNlZCB3aXRoIGFueSBvdGhlciBtZXRob2QuIFJlY2VpdmVkOiAke2FsbG93TWV0aG9kcy5qb2luKCcsJyl9YCk7XG4gICAgICB9XG5cbiAgICAgIGFsbG93TWV0aG9kcyA9IENvcnMuQUxMX01FVEhPRFM7XG4gICAgfVxuXG4gICAgaGVhZGVyc1snQWNjZXNzLUNvbnRyb2wtQWxsb3ctTWV0aG9kcyddID0gYCcke2FsbG93TWV0aG9kcy5qb2luKCcsJyl9J2A7XG5cbiAgICAvL1xuICAgIC8vIEFjY2Vzcy1Db250cm9sLUFsbG93LUNyZWRlbnRpYWxzXG5cbiAgICBpZiAob3B0aW9ucy5hbGxvd0NyZWRlbnRpYWxzKSB7XG4gICAgICBoZWFkZXJzWydBY2Nlc3MtQ29udHJvbC1BbGxvdy1DcmVkZW50aWFscyddID0gJ1xcJ3RydWVcXCcnO1xuICAgIH1cblxuICAgIC8vXG4gICAgLy8gQWNjZXNzLUNvbnRyb2wtTWF4LUFnZVxuXG4gICAgbGV0IG1heEFnZVNlY29uZHM7XG5cbiAgICBpZiAob3B0aW9ucy5tYXhBZ2UgJiYgb3B0aW9ucy5kaXNhYmxlQ2FjaGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIG9wdGlvbnMgXCJtYXhBZ2VcIiBhbmQgXCJkaXNhYmxlQ2FjaGVcIiBhcmUgbXV0dWFsbHkgZXhjbHVzaXZlJyk7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnMubWF4QWdlKSB7XG4gICAgICBtYXhBZ2VTZWNvbmRzID0gb3B0aW9ucy5tYXhBZ2UudG9TZWNvbmRzKCk7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnMuZGlzYWJsZUNhY2hlKSB7XG4gICAgICBtYXhBZ2VTZWNvbmRzID0gLTE7XG4gICAgfVxuXG4gICAgaWYgKG1heEFnZVNlY29uZHMpIHtcbiAgICAgIGhlYWRlcnNbJ0FjY2Vzcy1Db250cm9sLU1heC1BZ2UnXSA9IGAnJHttYXhBZ2VTZWNvbmRzfSdgO1xuICAgIH1cblxuICAgIC8vXG4gICAgLy8gQWNjZXNzLUNvbnRyb2wtRXhwb3NlLUhlYWRlcnNcbiAgICAvL1xuXG4gICAgaWYgKG9wdGlvbnMuZXhwb3NlSGVhZGVycykge1xuICAgICAgaGVhZGVyc1snQWNjZXNzLUNvbnRyb2wtRXhwb3NlLUhlYWRlcnMnXSA9IGAnJHtvcHRpb25zLmV4cG9zZUhlYWRlcnMuam9pbignLCcpfSdgO1xuICAgIH1cblxuICAgIC8vXG4gICAgLy8gc3RhdHVzQ29kZVxuXG4gICAgY29uc3Qgc3RhdHVzQ29kZSA9IG9wdGlvbnMuc3RhdHVzQ29kZSA/PyAyMDQ7XG5cbiAgICAvL1xuICAgIC8vIHByZXBhcmUgcmVzcG9uc2VQYXJhbXNcblxuICAgIGNvbnN0IGludGVncmF0aW9uUmVzcG9uc2VQYXJhbXM6IHsgW3A6IHN0cmluZ106IHN0cmluZyB9ID0geyB9O1xuICAgIGNvbnN0IG1ldGhvZFJlc3BvbnNlUGFyYW1zOiB7IFtwOiBzdHJpbmddOiBib29sZWFuIH0gPSB7IH07XG5cbiAgICBmb3IgKGNvbnN0IFtuYW1lLCB2YWx1ZV0gb2YgT2JqZWN0LmVudHJpZXMoaGVhZGVycykpIHtcbiAgICAgIGNvbnN0IGtleSA9IGBtZXRob2QucmVzcG9uc2UuaGVhZGVyLiR7bmFtZX1gO1xuICAgICAgaW50ZWdyYXRpb25SZXNwb25zZVBhcmFtc1trZXldID0gdmFsdWU7XG4gICAgICBtZXRob2RSZXNwb25zZVBhcmFtc1trZXldID0gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5hZGRNZXRob2QoJ09QVElPTlMnLCBuZXcgTW9ja0ludGVncmF0aW9uKHtcbiAgICAgIHJlcXVlc3RUZW1wbGF0ZXM6IHsgJ2FwcGxpY2F0aW9uL2pzb24nOiAneyBzdGF0dXNDb2RlOiAyMDAgfScgfSxcbiAgICAgIGludGVncmF0aW9uUmVzcG9uc2VzOiBbXG4gICAgICAgIHsgc3RhdHVzQ29kZTogYCR7c3RhdHVzQ29kZX1gLCByZXNwb25zZVBhcmFtZXRlcnM6IGludGVncmF0aW9uUmVzcG9uc2VQYXJhbXMsIHJlc3BvbnNlVGVtcGxhdGVzOiByZW5kZXJSZXNwb25zZVRlbXBsYXRlKCkgfSxcbiAgICAgIF0sXG4gICAgfSksIHtcbiAgICAgIG1ldGhvZFJlc3BvbnNlczogW1xuICAgICAgICB7IHN0YXR1c0NvZGU6IGAke3N0YXR1c0NvZGV9YCwgcmVzcG9uc2VQYXJhbWV0ZXJzOiBtZXRob2RSZXNwb25zZVBhcmFtcyB9LFxuICAgICAgXSxcbiAgICB9KTtcblxuICAgIC8vIHJlbmRlcnMgdGhlIHJlc3BvbnNlIHRlbXBsYXRlIHRvIG1hdGNoIGFsbCBwb3NzaWJsZSBvcmlnaW5zIChpZiB3ZSBoYXZlIG1vcmUgdGhhbiBvbmUpXG4gICAgZnVuY3Rpb24gcmVuZGVyUmVzcG9uc2VUZW1wbGF0ZSgpIHtcbiAgICAgIGNvbnN0IG9yaWdpbnMgPSBvcHRpb25zLmFsbG93T3JpZ2lucy5zbGljZSgxKTtcblxuICAgICAgaWYgKG9yaWdpbnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHRlbXBsYXRlID0gbmV3IEFycmF5PHN0cmluZz4oKTtcblxuICAgICAgdGVtcGxhdGUucHVzaCgnI3NldCgkb3JpZ2luID0gJGlucHV0LnBhcmFtcygpLmhlYWRlci5nZXQoXCJPcmlnaW5cIikpJyk7XG4gICAgICB0ZW1wbGF0ZS5wdXNoKCcjaWYoJG9yaWdpbiA9PSBcIlwiKSAjc2V0KCRvcmlnaW4gPSAkaW5wdXQucGFyYW1zKCkuaGVhZGVyLmdldChcIm9yaWdpblwiKSkgI2VuZCcpO1xuXG4gICAgICBjb25zdCBjb25kaXRpb24gPSBvcmlnaW5zLm1hcChvID0+IGAkb3JpZ2luLm1hdGNoZXMoXCIke299XCIpYCkuam9pbignIHx8ICcpO1xuXG4gICAgICB0ZW1wbGF0ZS5wdXNoKGAjaWYoJHtjb25kaXRpb259KWApO1xuICAgICAgdGVtcGxhdGUucHVzaCgnICAjc2V0KCRjb250ZXh0LnJlc3BvbnNlT3ZlcnJpZGUuaGVhZGVyLkFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpbiA9ICRvcmlnaW4pJyk7XG4gICAgICB0ZW1wbGF0ZS5wdXNoKCcjZW5kJyk7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgICdhcHBsaWNhdGlvbi9qc29uJzogdGVtcGxhdGUuam9pbignXFxuJyksXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBnZXRSZXNvdXJjZShwYXRoUGFydDogc3RyaW5nKTogSVJlc291cmNlIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5jaGlsZHJlbltwYXRoUGFydF07XG4gIH1cblxuICAvKipcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgX3RyYWNrQ2hpbGQocGF0aFBhcnQ6IHN0cmluZywgcmVzb3VyY2U6IFJlc291cmNlKSB7XG4gICAgdGhpcy5jaGlsZHJlbltwYXRoUGFydF0gPSByZXNvdXJjZTtcbiAgfVxuXG4gIHB1YmxpYyByZXNvdXJjZUZvclBhdGgocGF0aDogc3RyaW5nKTogUmVzb3VyY2Uge1xuICAgIGlmICghcGF0aCkge1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgaWYgKHBhdGguc3RhcnRzV2l0aCgnLycpKSB7XG4gICAgICBpZiAodGhpcy5wYXRoICE9PSAnLycpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBQYXRoIG1heSBzdGFydCB3aXRoIFwiL1wiIG9ubHkgZm9yIHRoZSByZXNvdXJjZSwgYnV0IHdlIGFyZSBhdDogJHt0aGlzLnBhdGh9YCk7XG4gICAgICB9XG5cbiAgICAgIC8vIHRyaW0gdHJhaWxpbmcgXCIvXCJcbiAgICAgIHJldHVybiB0aGlzLnJlc291cmNlRm9yUGF0aChwYXRoLnNsaWNlKDEpKTtcbiAgICB9XG5cbiAgICBjb25zdCBwYXJ0cyA9IHBhdGguc3BsaXQoJy8nKTtcbiAgICBjb25zdCBuZXh0ID0gcGFydHMuc2hpZnQoKTtcbiAgICBpZiAoIW5leHQgfHwgbmV4dCA9PT0gJycpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigncmVzb3VyY2VGb3JQYXRoIGNhbm5vdCBiZSBjYWxsZWQgd2l0aCBhbiBlbXB0eSBwYXRoJyk7XG4gICAgfVxuXG4gICAgbGV0IHJlc291cmNlID0gdGhpcy5nZXRSZXNvdXJjZShuZXh0KTtcbiAgICBpZiAoIXJlc291cmNlKSB7XG4gICAgICByZXNvdXJjZSA9IHRoaXMuYWRkUmVzb3VyY2UobmV4dCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc291cmNlLnJlc291cmNlRm9yUGF0aChwYXJ0cy5qb2luKCcvJykpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXByZWNhdGVkIC0gVGhyb3dzIGVycm9yIGluIHNvbWUgdXNlIGNhc2VzIHRoYXQgaGF2ZSBiZWVuIGVuYWJsZWQgc2luY2UgdGhpcyBkZXByZWNhdGlvbiBub3RpY2UuIFVzZSBgUmVzdEFwaS51cmxGb3JQYXRoKClgIGluc3RlYWQuXG4gICAqL1xuICBwdWJsaWMgZ2V0IHVybCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnJlc3RBcGkudXJsRm9yUGF0aCh0aGlzLnBhdGgpO1xuICB9XG59XG5cbi8qKlxuICogQXR0cmlidXRlcyB0aGF0IGNhbiBiZSBzcGVjaWZpZWQgd2hlbiBpbXBvcnRpbmcgYSBSZXNvdXJjZVxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlc291cmNlQXR0cmlidXRlcyB7XG4gIC8qKlxuICAgKiBUaGUgSUQgb2YgdGhlIHJlc291cmNlLlxuICAgKi9cbiAgcmVhZG9ubHkgcmVzb3VyY2VJZDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgcmVzdCBBUEkgdGhhdCB0aGlzIHJlc291cmNlIGlzIHBhcnQgb2YuXG4gICAqL1xuICByZWFkb25seSByZXN0QXBpOiBJUmVzdEFwaTtcblxuICAvKipcbiAgICogVGhlIGZ1bGwgcGF0aCBvZiB0aGlzIHJlc291cmNlLlxuICAgKi9cbiAgcmVhZG9ubHkgcGF0aDogc3RyaW5nO1xufVxuXG5leHBvcnQgY2xhc3MgUmVzb3VyY2UgZXh0ZW5kcyBSZXNvdXJjZUJhc2Uge1xuICAvKipcbiAgICogSW1wb3J0IGFuIGV4aXN0aW5nIHJlc291cmNlXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21SZXNvdXJjZUF0dHJpYnV0ZXMoc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgYXR0cnM6IFJlc291cmNlQXR0cmlidXRlcyk6IElSZXNvdXJjZSB7XG4gICAgY2xhc3MgSW1wb3J0IGV4dGVuZHMgUmVzb3VyY2VCYXNlIHtcbiAgICAgIHB1YmxpYyByZWFkb25seSBhcGkgPSBhdHRycy5yZXN0QXBpO1xuICAgICAgcHVibGljIHJlYWRvbmx5IHJlc291cmNlSWQgPSBhdHRycy5yZXNvdXJjZUlkO1xuICAgICAgcHVibGljIHJlYWRvbmx5IHBhdGggPSBhdHRycy5wYXRoO1xuICAgICAgcHVibGljIHJlYWRvbmx5IGRlZmF1bHRJbnRlZ3JhdGlvbj86IEludGVncmF0aW9uID0gdW5kZWZpbmVkO1xuICAgICAgcHVibGljIHJlYWRvbmx5IGRlZmF1bHRNZXRob2RPcHRpb25zPzogTWV0aG9kT3B0aW9ucyA9IHVuZGVmaW5lZDtcbiAgICAgIHB1YmxpYyByZWFkb25seSBkZWZhdWx0Q29yc1ByZWZsaWdodE9wdGlvbnM/OiBDb3JzT3B0aW9ucyA9IHVuZGVmaW5lZDtcblxuICAgICAgcHVibGljIGdldCBwYXJlbnRSZXNvdXJjZSgpOiBJUmVzb3VyY2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3BhcmVudFJlc291cmNlIGlzIG5vdCBjb25maWd1cmVkIGZvciBpbXBvcnRlZCByZXNvdXJjZS4nKTtcbiAgICAgIH1cblxuICAgICAgcHVibGljIGdldCByZXN0QXBpKCk6IFJlc3RBcGkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3Jlc3RBcGkgaXMgbm90IGNvbmZpZ3VyZWQgZm9yIGltcG9ydGVkIHJlc291cmNlLicpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBuZXcgSW1wb3J0KHNjb3BlLCBpZCk7XG4gIH1cblxuICBwdWJsaWMgcmVhZG9ubHkgcGFyZW50UmVzb3VyY2U/OiBJUmVzb3VyY2U7XG4gIHB1YmxpYyByZWFkb25seSBhcGk6IElSZXN0QXBpO1xuICBwdWJsaWMgcmVhZG9ubHkgcmVzb3VyY2VJZDogc3RyaW5nO1xuICBwdWJsaWMgcmVhZG9ubHkgcGF0aDogc3RyaW5nO1xuXG4gIHB1YmxpYyByZWFkb25seSBkZWZhdWx0SW50ZWdyYXRpb24/OiBJbnRlZ3JhdGlvbjtcbiAgcHVibGljIHJlYWRvbmx5IGRlZmF1bHRNZXRob2RPcHRpb25zPzogTWV0aG9kT3B0aW9ucztcbiAgcHVibGljIHJlYWRvbmx5IGRlZmF1bHRDb3JzUHJlZmxpZ2h0T3B0aW9ucz86IENvcnNPcHRpb25zO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBSZXNvdXJjZVByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgIHZhbGlkYXRlUmVzb3VyY2VQYXRoUGFydChwcm9wcy5wYXRoUGFydCk7XG5cbiAgICB0aGlzLnBhcmVudFJlc291cmNlID0gcHJvcHMucGFyZW50O1xuXG4gICAgaWYgKHByb3BzLnBhcmVudCBpbnN0YW5jZW9mIFJlc291cmNlQmFzZSkge1xuICAgICAgcHJvcHMucGFyZW50Ll90cmFja0NoaWxkKHByb3BzLnBhdGhQYXJ0LCB0aGlzKTtcbiAgICB9XG5cbiAgICBjb25zdCByZXNvdXJjZVByb3BzOiBDZm5SZXNvdXJjZVByb3BzID0ge1xuICAgICAgcmVzdEFwaUlkOiBwcm9wcy5wYXJlbnQuYXBpLnJlc3RBcGlJZCxcbiAgICAgIHBhcmVudElkOiBwcm9wcy5wYXJlbnQucmVzb3VyY2VJZCxcbiAgICAgIHBhdGhQYXJ0OiBwcm9wcy5wYXRoUGFydCxcbiAgICB9O1xuICAgIGNvbnN0IHJlc291cmNlID0gbmV3IENmblJlc291cmNlKHRoaXMsICdSZXNvdXJjZScsIHJlc291cmNlUHJvcHMpO1xuXG4gICAgdGhpcy5yZXNvdXJjZUlkID0gcmVzb3VyY2UucmVmO1xuICAgIHRoaXMuYXBpID0gcHJvcHMucGFyZW50LmFwaTtcblxuICAgIC8vIHJlbmRlciByZXNvdXJjZSBwYXRoIChzcGVjaWFsIGNhc2UgZm9yIHJvb3QpXG4gICAgdGhpcy5wYXRoID0gcHJvcHMucGFyZW50LnBhdGg7XG4gICAgaWYgKCF0aGlzLnBhdGguZW5kc1dpdGgoJy8nKSkgeyB0aGlzLnBhdGggKz0gJy8nOyB9XG4gICAgdGhpcy5wYXRoICs9IHByb3BzLnBhdGhQYXJ0O1xuXG4gICAgY29uc3QgZGVwbG95bWVudCA9IHByb3BzLnBhcmVudC5hcGkubGF0ZXN0RGVwbG95bWVudDtcbiAgICBpZiAoZGVwbG95bWVudCkge1xuICAgICAgZGVwbG95bWVudC5ub2RlLmFkZERlcGVuZGVuY3kocmVzb3VyY2UpO1xuICAgICAgZGVwbG95bWVudC5hZGRUb0xvZ2ljYWxJZCh7IHJlc291cmNlOiByZXNvdXJjZVByb3BzIH0pO1xuICAgIH1cblxuICAgIC8vIHNldHVwIGRlZmF1bHRzIGJhc2VkIG9uIHByb3BlcnRpZXMgYW5kIGluaGVyaXQgZnJvbSBwYXJlbnQuIG1ldGhvZCBkZWZhdWx0c1xuICAgIC8vIGFyZSBpbmhlcml0ZWQgcGVyIHByb3BlcnR5LCBzbyBjaGlsZHJlbiBjYW4gb3ZlcnJpZGUgcGllY2VtZWFsLlxuICAgIHRoaXMuZGVmYXVsdEludGVncmF0aW9uID0gcHJvcHMuZGVmYXVsdEludGVncmF0aW9uIHx8IHByb3BzLnBhcmVudC5kZWZhdWx0SW50ZWdyYXRpb247XG4gICAgdGhpcy5kZWZhdWx0TWV0aG9kT3B0aW9ucyA9IHtcbiAgICAgIC4uLnByb3BzLnBhcmVudC5kZWZhdWx0TWV0aG9kT3B0aW9ucyxcbiAgICAgIC4uLnByb3BzLmRlZmF1bHRNZXRob2RPcHRpb25zLFxuICAgIH07XG4gICAgdGhpcy5kZWZhdWx0Q29yc1ByZWZsaWdodE9wdGlvbnMgPSBwcm9wcy5kZWZhdWx0Q29yc1ByZWZsaWdodE9wdGlvbnMgfHwgcHJvcHMucGFyZW50LmRlZmF1bHRDb3JzUHJlZmxpZ2h0T3B0aW9ucztcblxuICAgIGlmICh0aGlzLmRlZmF1bHRDb3JzUHJlZmxpZ2h0T3B0aW9ucykge1xuICAgICAgdGhpcy5hZGRDb3JzUHJlZmxpZ2h0KHRoaXMuZGVmYXVsdENvcnNQcmVmbGlnaHRPcHRpb25zKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVGhlIFJlc3RBcGkgYXNzb2NpYXRlZCB3aXRoIHRoaXMgUmVzb3VyY2VcbiAgICogQGRlcHJlY2F0ZWQgLSBUaHJvd3MgYW4gZXJyb3IgaWYgdGhpcyBSZXNvdXJjZSBpcyBub3QgYXNzb2NpYXRlZCB3aXRoIGFuIGluc3RhbmNlIG9mIGBSZXN0QXBpYC4gVXNlIGBhcGlgIGluc3RlYWQuXG4gICAqL1xuICBwdWJsaWMgZ2V0IHJlc3RBcGkoKTogUmVzdEFwaSB7XG4gICAgaWYgKCF0aGlzLnBhcmVudFJlc291cmNlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3BhcmVudFJlc291cmNlIHdhcyB1bmV4cGVjdGVkbHkgbm90IGRlZmluZWQnKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMucGFyZW50UmVzb3VyY2UucmVzdEFwaTtcbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFByb3h5UmVzb3VyY2VPcHRpb25zIGV4dGVuZHMgUmVzb3VyY2VPcHRpb25zIHtcbiAgLyoqXG4gICAqIEFkZHMgYW4gXCJBTllcIiBtZXRob2QgdG8gdGhpcyByZXNvdXJjZS4gSWYgc2V0IHRvIGBmYWxzZWAsIHlvdSB3aWxsIGhhdmUgdG8gZXhwbGljaXRseVxuICAgKiBhZGQgbWV0aG9kcyB0byB0aGlzIHJlc291cmNlIGFmdGVyIGl0J3MgY3JlYXRlZC5cbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgYW55TWV0aG9kPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQcm94eVJlc291cmNlUHJvcHMgZXh0ZW5kcyBQcm94eVJlc291cmNlT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgcGFyZW50IHJlc291cmNlIG9mIHRoaXMgcmVzb3VyY2UuIFlvdSBjYW4gZWl0aGVyIHBhc3MgYW5vdGhlclxuICAgKiBgUmVzb3VyY2VgIG9iamVjdCBvciBhIGBSZXN0QXBpYCBvYmplY3QgaGVyZS5cbiAgICovXG4gIHJlYWRvbmx5IHBhcmVudDogSVJlc291cmNlO1xufVxuXG4vKipcbiAqIERlZmluZXMgYSB7cHJveHkrfSBncmVlZHkgcmVzb3VyY2UgYW5kIGFuIEFOWSBtZXRob2Qgb24gYSByb3V0ZS5cbiAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FwaWdhdGV3YXkvbGF0ZXN0L2RldmVsb3Blcmd1aWRlL2FwaS1nYXRld2F5LXNldC11cC1zaW1wbGUtcHJveHkuaHRtbFxuICovXG5leHBvcnQgY2xhc3MgUHJveHlSZXNvdXJjZSBleHRlbmRzIFJlc291cmNlIHtcbiAgLyoqXG4gICAqIElmIGBwcm9wcy5hbnlNZXRob2RgIGlzIGB0cnVlYCwgdGhpcyB3aWxsIGJlIHRoZSByZWZlcmVuY2UgdG8gdGhlICdBTlknXG4gICAqIG1ldGhvZCBhc3NvY2lhdGVkIHdpdGggdGhpcyBwcm94eSByZXNvdXJjZS5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBhbnlNZXRob2Q/OiBNZXRob2Q7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IFByb3h5UmVzb3VyY2VQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCwge1xuICAgICAgcGFyZW50OiBwcm9wcy5wYXJlbnQsXG4gICAgICBwYXRoUGFydDogJ3twcm94eSt9JyxcbiAgICAgIGRlZmF1bHRJbnRlZ3JhdGlvbjogcHJvcHMuZGVmYXVsdEludGVncmF0aW9uLFxuICAgICAgZGVmYXVsdE1ldGhvZE9wdGlvbnM6IHByb3BzLmRlZmF1bHRNZXRob2RPcHRpb25zLFxuICAgIH0pO1xuXG4gICAgY29uc3QgYW55TWV0aG9kID0gcHJvcHMuYW55TWV0aG9kID8/IHRydWU7XG4gICAgaWYgKGFueU1ldGhvZCkge1xuICAgICAgdGhpcy5hbnlNZXRob2QgPSB0aGlzLmFkZE1ldGhvZCgnQU5ZJyk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGFkZE1ldGhvZChodHRwTWV0aG9kOiBzdHJpbmcsIGludGVncmF0aW9uPzogSW50ZWdyYXRpb24sIG9wdGlvbnM/OiBNZXRob2RPcHRpb25zKTogTWV0aG9kIHtcbiAgICAvLyBJbiBjYXNlIHR