UNPKG

@aws-cdk/aws-bedrock-agentcore-alpha

Version:

The CDK Construct Library for Amazon Bedrock

333 lines 46.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ValidationError = void 0; exports.validateStringField = validateStringField; exports.validateFieldPattern = validateFieldPattern; exports.validateOpenApiSchema = validateOpenApiSchema; const aws_cdk_lib_1 = require("aws-cdk-lib"); /** * Error thrown when validation fails * @internal */ class ValidationError extends Error { constructor(message) { super(message); this.name = 'ValidationError'; } } exports.ValidationError = ValidationError; /** * Validates the length of a string field against minimum and maximum constraints. * @param value - The string value to validate * @param fieldName - Name of the field being validated (for error messages) * @param minLength - Minimum allowed length (defaults to 0) * @param maxLength - Maximum allowed length * @returns true if validation passes * @throws Error if validation fails with current length information * @internal */ function validateStringField(params) { const errors = []; // Handle null/undefined values if (params.value == null) { return errors; // Skip validation for null/undefined values } // Skip validation if value is an unresolved token if (aws_cdk_lib_1.Token.isUnresolved(params.value)) { return errors; } // Now safe to access .length since we know it's not a token const currentLength = params.value.length; if (params.value.length > params.maxLength) { errors.push(`The field ${params.fieldName} is ${currentLength} characters long but must be less than or equal to ${params.maxLength} characters`); } if (params.value.length < params.minLength) { errors.push(`The field ${params.fieldName} is ${currentLength} characters long but must be at least ${params.minLength} characters`); } return errors; } /** * Validates a string field against a regex pattern. * @param value - The string value to validate * @param fieldName - Name of the field being validated (for error messages) * @param pattern - Regular expression pattern to test against * @param customMessage - Optional custom error message * @returns true if validation passes * @throws Error if validation fails with detailed message * @internal */ function validateFieldPattern(value, fieldName, pattern, customMessage) { const errors = []; // Handle null/undefined values if (value == null) { return errors; // Skip validation for null/undefined values } // Evaluate only if it is not an unresolved Token if (!aws_cdk_lib_1.Token.isUnresolved(value)) { // Verify type if (typeof value !== 'string') { errors.push(`Expected string for ${fieldName}, got ${typeof value}`); return errors; // Return early if value is not a string } // Validate specified regex if (!(pattern instanceof RegExp)) { errors.push('Pattern must be a valid regular expression'); return errors; // Return early if pattern is not a RegExp } // Pattern validation (only if value is string and pattern is RegExp) if (!pattern.test(value)) { const defaultMessage = `The field ${fieldName} with value "${value}" does not match the required pattern ${pattern}`; errors.push(customMessage || defaultMessage); } } return errors; } /** * Parses OpenAPI schema JSON and validates format * @internal */ function parseOpenApiJson(schema, schemaName, errors) { try { return JSON.parse(schema); } catch (e) { errors.push(`${schemaName} must be in JSON format. YAML is not supported. Error: ${e instanceof Error ? e.message : String(e)}`); return null; } } /** * Validates OpenAPI version (3.0.x or 3.1.x) * @internal */ function validateOpenApiVersion(schemaObj, schemaName, errors) { if (!schemaObj.openapi) { errors.push(`${schemaName} must include an 'openapi' field specifying the version`); } else { const version = schemaObj.openapi; if (typeof version !== 'string') { errors.push(`${schemaName} 'openapi' field must be a string`); } else if (!version.startsWith('3.0.') && !version.startsWith('3.1.')) { errors.push(`${schemaName} version ${version} is not supported. Only OpenAPI 3.0.x and 3.1.x are supported`); } } } /** * Validates server URLs * @internal */ function validateServerUrls(schemaObj, schemaName, errors) { if (!schemaObj.servers || !Array.isArray(schemaObj.servers) || schemaObj.servers.length === 0) { errors.push(`${schemaName} must include at least one server with a valid URL`); } else { schemaObj.servers.forEach((server, index) => { if (!server.url || typeof server.url !== 'string') { errors.push(`${schemaName} server[${index}] must have a valid URL`); } else { // Check if URL contains a protocol separator if (!server.url.includes('://')) { errors.push(`${schemaName} server[${index}] URL must contain a protocol (e.g., http:// or https://)`); } else { // Check if it starts with http or https (case-insensitive) // Allow template variables like {protocol}:// const protocolEnd = server.url.indexOf('://'); const protocol = server.url.substring(0, protocolEnd); // If protocol doesn't contain template variables, validate it if (!protocol.includes('{')) { if (protocol.toLowerCase() !== 'http' && protocol.toLowerCase() !== 'https') { errors.push(`${schemaName} server[${index}] URL must use HTTP or HTTPS protocol`); } } // If protocol contains template variables, skip validation (will be validated at runtime) } } }); } } /** * Validates paths and operations * @internal */ function validatePathsAndOperations(schemaObj, schemaName, errors) { if (!schemaObj.paths || typeof schemaObj.paths !== 'object') { errors.push(`${schemaName} must include a 'paths' object`); } else { const operationsMissingId = []; const unsupportedMediaTypes = new Set(); const pathsWithComplexSerializers = []; Object.entries(schemaObj.paths).forEach(([path, pathItem]) => { // Check for complex path parameter serializers if (path.includes('{;') || path.includes('{?') || path.includes('{*}')) { pathsWithComplexSerializers.push(path); } if (pathItem && typeof pathItem === 'object') { // Check each HTTP method const httpMethods = ['get', 'post', 'put', 'delete', 'patch', 'head', 'options']; httpMethods.forEach(method => { if (pathItem[method]) { const operation = pathItem[method]; // Check for operationId (REQUIRED) if (!operation.operationId) { operationsMissingId.push(`${method.toUpperCase()} ${path}`); } // Check request body media types if (operation.requestBody?.content) { Object.keys(operation.requestBody.content).forEach(mediaType => { if (mediaType !== 'application/json' && mediaType !== 'application/xml' && mediaType !== 'multipart/form-data' && mediaType !== 'application/x-www-form-urlencoded') { unsupportedMediaTypes.add(mediaType); } }); } // Check response media types if (operation.responses) { Object.values(operation.responses).forEach((response) => { if (response.content) { Object.keys(response.content).forEach(mediaType => { if (mediaType !== 'application/json' && mediaType !== 'application/xml') { unsupportedMediaTypes.add(mediaType); } }); } }); } // Check for complex parameter serializers if (operation.parameters) { operation.parameters.forEach((param, idx) => { if (param.style && ['matrix', 'label', 'deepObject'].includes(param.style)) { errors.push(`${schemaName} ${method.toUpperCase()} ${path} parameter[${idx}] uses unsupported serialization style: ${param.style}`); } }); } } }); } }); if (operationsMissingId.length > 0) { errors.push(`${schemaName} operations must include 'operationId' field. Missing in: ${operationsMissingId.join(', ')}`); } if (pathsWithComplexSerializers.length > 0) { errors.push(`${schemaName} contains unsupported complex path parameter serializers in: ${pathsWithComplexSerializers.join(', ')}`); } if (unsupportedMediaTypes.size > 0) { const mediaTypesList = Array.from(unsupportedMediaTypes).join(', '); errors.push(`${schemaName} uses unsupported media types: ${mediaTypesList}. Only application/json, application/xml, multipart/form-data, and application/x-www-form-urlencoded are supported`); } } } /** * Recursive helper to check for unsupported schema composition (oneOf, anyOf, allOf) * @internal */ function checkSchemaComposition(obj, schemaName, errors, path = '') { if (!obj || typeof obj !== 'object') return; // Check current level for unsupported keywords if ('oneOf' in obj) { errors.push(`${schemaName} contains unsupported 'oneOf' schema composition at ${path || 'root'}`); } if ('anyOf' in obj) { errors.push(`${schemaName} contains unsupported 'anyOf' schema composition at ${path || 'root'}`); } if ('allOf' in obj) { errors.push(`${schemaName} contains unsupported 'allOf' schema composition at ${path || 'root'}`); } // Recursively check nested objects Object.entries(obj).forEach(([key, value]) => { if (key !== 'oneOf' && key !== 'anyOf' && key !== 'allOf' && value && typeof value === 'object') { const newPath = path ? `${path}.${key}` : key; if (Array.isArray(value)) { value.forEach((item, index) => { checkSchemaComposition(item, schemaName, errors, `${newPath}[${index}]`); }); } else { checkSchemaComposition(value, schemaName, errors, newPath); } } }); } /** * Validates schema composition (checks for unsupported oneOf, anyOf, allOf) * @internal */ function validateSchemaComposition(schemaObj, schemaName, errors) { // Check components/definitions for unsupported schema composition if (schemaObj.components?.schemas) { checkSchemaComposition(schemaObj.components.schemas, schemaName, errors, 'components.schemas'); } if (schemaObj.definitions) { checkSchemaComposition(schemaObj.definitions, schemaName, errors, 'definitions'); } // Check paths for unsupported schema composition if (schemaObj.paths) { checkSchemaComposition(schemaObj.paths, schemaName, errors, 'paths'); } } /** * Validates security schemes * @internal */ function validateSecuritySchemes(schemaObj, schemaName, errors) { if (schemaObj.security && Array.isArray(schemaObj.security) && schemaObj.security.length > 0) { errors.push(`${schemaName} contains security schemes at the OpenAPI specification level. Authentication must be configured using the Gateway's outbound authorization configuration instead`); } } /** * Validates callbacks and webhooks * @internal */ function validateCallbacksAndWebhooks(schemaObj, schemaName, errors) { // Check for callbacks in operations if (schemaObj.paths) { Object.entries(schemaObj.paths).forEach(([path, pathItem]) => { if (pathItem && typeof pathItem === 'object') { Object.values(pathItem).forEach((operation) => { if (operation && typeof operation === 'object') { if (operation.callbacks) { errors.push(`${schemaName} contains unsupported 'callbacks' in path ${path}`); } } }); } }); } // Check for webhooks if (schemaObj.webhooks) { errors.push(`${schemaName} contains unsupported 'webhooks'`); } } /** * Validates an OpenAPI schema against Gateway requirements * Based on AWS documentation: https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/gateway-schema-openapi.html * * @param params - The validation parameters * @returns Array of validation error messages (empty if valid) * @internal */ function validateOpenApiSchema(params) { const errors = []; const { schema, schemaName = 'OpenAPI schema' } = params; if (aws_cdk_lib_1.Token.isUnresolved(schema)) { return errors; } const schemaObj = parseOpenApiJson(schema, schemaName, errors); if (!schemaObj) return errors; validateOpenApiVersion(schemaObj, schemaName, errors); validateServerUrls(schemaObj, schemaName, errors); validatePathsAndOperations(schemaObj, schemaName, errors); validateSchemaComposition(schemaObj, schemaName, errors); validateSecuritySchemes(schemaObj, schemaName, errors); validateCallbacksAndWebhooks(schemaObj, schemaName, errors); return errors; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdGlvbi1oZWxwZXJzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsidmFsaWRhdGlvbi1oZWxwZXJzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQWdDQSxrREE2QkM7QUFZRCxvREFrQ0M7QUEyUUQsc0RBa0JDO0FBeFlELDZDQUFvQztBQUVwQzs7O0dBR0c7QUFDSCxNQUFhLGVBQWdCLFNBQVEsS0FBSztJQUN4QyxZQUFZLE9BQWU7UUFDekIsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2YsSUFBSSxDQUFDLElBQUksR0FBRyxpQkFBaUIsQ0FBQztLQUMvQjtDQUNGO0FBTEQsMENBS0M7QUFXRDs7Ozs7Ozs7O0dBU0c7QUFDSCxTQUFnQixtQkFBbUIsQ0FBQyxNQUE4QjtJQUNoRSxNQUFNLE1BQU0sR0FBYSxFQUFFLENBQUM7SUFFNUIsK0JBQStCO0lBQy9CLElBQUksTUFBTSxDQUFDLEtBQUssSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUN6QixPQUFPLE1BQU0sQ0FBQyxDQUFDLDRDQUE0QztJQUM3RCxDQUFDO0lBRUQsa0RBQWtEO0lBQ2xELElBQUksbUJBQUssQ0FBQyxZQUFZLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDckMsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUVELDREQUE0RDtJQUM1RCxNQUFNLGFBQWEsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQztJQUUxQyxJQUFJLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUMzQyxNQUFNLENBQUMsSUFBSSxDQUNULGFBQWEsTUFBTSxDQUFDLFNBQVMsT0FBTyxhQUFhLHNEQUFzRCxNQUFNLENBQUMsU0FBUyxhQUFhLENBQ3JJLENBQUM7SUFDSixDQUFDO0lBRUQsSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUMsU0FBUyxFQUFFLENB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RCxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgVG9rZW4gfSBmcm9tICdhd3MtY2RrLWxpYic7XG5cbi8qKlxuICogRXJyb3IgdGhyb3duIHdoZW4gdmFsaWRhdGlvbiBmYWlsc1xuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBjbGFzcyBWYWxpZGF0aW9uRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKG1lc3NhZ2U6IHN0cmluZykge1xuICAgIHN1cGVyKG1lc3NhZ2UpO1xuICAgIHRoaXMubmFtZSA9ICdWYWxpZGF0aW9uRXJyb3InO1xuICB9XG59XG5pbnRlcmZhY2UgSW50ZXJ2YWxWYWxpZGF0aW9uIHtcbiAgZmllbGROYW1lOiBzdHJpbmc7XG4gIG1pbkxlbmd0aDogbnVtYmVyO1xuICBtYXhMZW5ndGg6IG51bWJlcjtcbn1cblxuaW50ZXJmYWNlIFN0cmluZ0xlbmd0aFZhbGlkYXRpb24gZXh0ZW5kcyBJbnRlcnZhbFZhbGlkYXRpb24ge1xuICB2YWx1ZTogc3RyaW5nO1xufVxuXG4vKipcbiAqIFZhbGlkYXRlcyB0aGUgbGVuZ3RoIG9mIGEgc3RyaW5nIGZpZWxkIGFnYWluc3QgbWluaW11bSBhbmQgbWF4aW11bSBjb25zdHJhaW50cy5cbiAqIEBwYXJhbSB2YWx1ZSAtIFRoZSBzdHJpbmcgdmFsdWUgdG8gdmFsaWRhdGVcbiAqIEBwYXJhbSBmaWVsZE5hbWUgLSBOYW1lIG9mIHRoZSBmaWVsZCBiZWluZyB2YWxpZGF0ZWQgKGZvciBlcnJvciBtZXNzYWdlcylcbiAqIEBwYXJhbSBtaW5MZW5ndGggLSBNaW5pbXVtIGFsbG93ZWQgbGVuZ3RoIChkZWZhdWx0cyB0byAwKVxuICogQHBhcmFtIG1heExlbmd0aCAtIE1heGltdW0gYWxsb3dlZCBsZW5ndGhcbiAqIEByZXR1cm5zIHRydWUgaWYgdmFsaWRhdGlvbiBwYXNzZXNcbiAqIEB0aHJvd3MgRXJyb3IgaWYgdmFsaWRhdGlvbiBmYWlscyB3aXRoIGN1cnJlbnQgbGVuZ3RoIGluZm9ybWF0aW9uXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlU3RyaW5nRmllbGQocGFyYW1zOiBTdHJpbmdMZW5ndGhWYWxpZGF0aW9uKTogc3RyaW5nW10ge1xuICBjb25zdCBlcnJvcnM6IHN0cmluZ1tdID0gW107XG5cbiAgLy8gSGFuZGxlIG51bGwvdW5kZWZpbmVkIHZhbHVlc1xuICBpZiAocGFyYW1zLnZhbHVlID09IG51bGwpIHtcbiAgICByZXR1cm4gZXJyb3JzOyAvLyBTa2lwIHZhbGlkYXRpb24gZm9yIG51bGwvdW5kZWZpbmVkIHZhbHVlc1xuICB9XG5cbiAgLy8gU2tpcCB2YWxpZGF0aW9uIGlmIHZhbHVlIGlzIGFuIHVucmVzb2x2ZWQgdG9rZW5cbiAgaWYgKFRva2VuLmlzVW5yZXNvbHZlZChwYXJhbXMudmFsdWUpKSB7XG4gICAgcmV0dXJuIGVycm9ycztcbiAgfVxuXG4gIC8vIE5vdyBzYWZlIHRvIGFjY2VzcyAubGVuZ3RoIHNpbmNlIHdlIGtub3cgaXQncyBub3QgYSB0b2tlblxuICBjb25zdCBjdXJyZW50TGVuZ3RoID0gcGFyYW1zLnZhbHVlLmxlbmd0aDtcblxuICBpZiAocGFyYW1zLnZhbHVlLmxlbmd0aCA+IHBhcmFtcy5tYXhMZW5ndGgpIHtcbiAgICBlcnJvcnMucHVzaChcbiAgICAgIGBUaGUgZmllbGQgJHtwYXJhbXMuZmllbGROYW1lfSBpcyAke2N1cnJlbnRMZW5ndGh9IGNoYXJhY3RlcnMgbG9uZyBidXQgbXVzdCBiZSBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gJHtwYXJhbXMubWF4TGVuZ3RofSBjaGFyYWN0ZXJzYCxcbiAgICApO1xuICB9XG5cbiAgaWYgKHBhcmFtcy52YWx1ZS5sZW5ndGggPCBwYXJhbXMubWluTGVuZ3RoKSB7XG4gICAgZXJyb3JzLnB1c2goXG4gICAgICBgVGhlIGZpZWxkICR7cGFyYW1zLmZpZWxkTmFtZX0gaXMgJHtjdXJyZW50TGVuZ3RofSBjaGFyYWN0ZXJzIGxvbmcgYnV0IG11c3QgYmUgYXQgbGVhc3QgJHtwYXJhbXMubWluTGVuZ3RofSBjaGFyYWN0ZXJzYCxcbiAgICApO1xuICB9XG5cbiAgcmV0dXJuIGVycm9ycztcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgYSBzdHJpbmcgZmllbGQgYWdhaW5zdCBhIHJlZ2V4IHBhdHRlcm4uXG4gKiBAcGFyYW0gdmFsdWUgLSBUaGUgc3RyaW5nIHZhbHVlIHRvIHZhbGlkYXRlXG4gKiBAcGFyYW0gZmllbGROYW1lIC0gTmFtZSBvZiB0aGUgZmllbGQgYmVpbmcgdmFsaWRhdGVkIChmb3IgZXJyb3IgbWVzc2FnZXMpXG4gKiBAcGFyYW0gcGF0dGVybiAtIFJlZ3VsYXIgZXhwcmVzc2lvbiBwYXR0ZXJuIHRvIHRlc3QgYWdhaW5zdFxuICogQHBhcmFtIGN1c3RvbU1lc3NhZ2UgLSBPcHRpb25hbCBjdXN0b20gZXJyb3IgbWVzc2FnZVxuICogQHJldHVybnMgdHJ1ZSBpZiB2YWxpZGF0aW9uIHBhc3Nlc1xuICogQHRocm93cyBFcnJvciBpZiB2YWxpZGF0aW9uIGZhaWxzIHdpdGggZGV0YWlsZWQgbWVzc2FnZVxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZUZpZWxkUGF0dGVybihcbiAgdmFsdWU6IHN0cmluZyxcbiAgZmllbGROYW1lOiBzdHJpbmcsXG4gIHBhdHRlcm46IFJlZ0V4cCxcbiAgY3VzdG9tTWVzc2FnZT86IHN0cmluZyxcbik6IHN0cmluZ1tdIHtcbiAgY29uc3QgZXJyb3JzOiBzdHJpbmdbXSA9IFtdO1xuXG4gIC8vIEhhbmRsZSBudWxsL3VuZGVmaW5lZCB2YWx1ZXNcbiAgaWYgKHZhbHVlID09IG51bGwpIHtcbiAgICByZXR1cm4gZXJyb3JzOyAvLyBTa2lwIHZhbGlkYXRpb24gZm9yIG51bGwvdW5kZWZpbmVkIHZhbHVlc1xuICB9XG5cbiAgLy8gRXZhbHVhdGUgb25seSBpZiBpdCBpcyBub3QgYW4gdW5yZXNvbHZlZCBUb2tlblxuICBpZiAoIVRva2VuLmlzVW5yZXNvbHZlZCh2YWx1ZSkpIHtcbiAgICAvLyBWZXJpZnkgdHlwZVxuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICBlcnJvcnMucHVzaChgRXhwZWN0ZWQgc3RyaW5nIGZvciAke2ZpZWxkTmFtZX0sIGdvdCAke3R5cGVvZiB2YWx1ZX1gKTtcbiAgICAgIHJldHVybiBlcnJvcnM7IC8vIFJldHVybiBlYXJseSBpZiB2YWx1ZSBpcyBub3QgYSBzdHJpbmdcbiAgICB9XG4gICAgLy8gVmFsaWRhdGUgc3BlY2lmaWVkIHJlZ2V4XG4gICAgaWYgKCEocGF0dGVybiBpbnN0YW5jZW9mIFJlZ0V4cCkpIHtcbiAgICAgIGVycm9ycy5wdXNoKCdQYXR0ZXJuIG11c3QgYmUgYSB2YWxpZCByZWd1bGFyIGV4cHJlc3Npb24nKTtcbiAgICAgIHJldHVybiBlcnJvcnM7IC8vIFJldHVybiBlYXJseSBpZiBwYXR0ZXJuIGlzIG5vdCBhIFJlZ0V4cFxuICAgIH1cblxuICAgIC8vIFBhdHRlcm4gdmFsaWRhdGlvbiAob25seSBpZiB2YWx1ZSBpcyBzdHJpbmcgYW5kIHBhdHRlcm4gaXMgUmVnRXhwKVxuICAgIGlmICghcGF0dGVybi50ZXN0KHZhbHVlKSkge1xuICAgICAgY29uc3QgZGVmYXVsdE1lc3NhZ2UgPSBgVGhlIGZpZWxkICR7ZmllbGROYW1lfSB3aXRoIHZhbHVlIFwiJHt2YWx1ZX1cIiBkb2VzIG5vdCBtYXRjaCB0aGUgcmVxdWlyZWQgcGF0dGVybiAke3BhdHRlcm59YDtcbiAgICAgIGVycm9ycy5wdXNoKGN1c3RvbU1lc3NhZ2UgfHwgZGVmYXVsdE1lc3NhZ2UpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBlcnJvcnM7XG59XG5cbi8qKlxuICogQGludGVybmFsXG4gKi9cbmV4cG9ydCB0eXBlIFZhbGlkYXRpb25GbjxUPiA9IChwYXJhbTogVCkgPT4gc3RyaW5nW107XG5cbi8qKlxuICogT3BlbkFQSSBzY2hlbWEgdmFsaWRhdGlvbiBwYXJhbWV0ZXJzXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBPcGVuQXBpU2NoZW1hVmFsaWRhdGlvblBhcmFtcyB7XG4gIC8qKlxuICAgKiBUaGUgT3BlbkFQSSBzY2hlbWEgdG8gdmFsaWRhdGUgKGFzIGEgc3RyaW5nKVxuICAgKi9cbiAgc2NoZW1hOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIE9wdGlvbmFsIG5hbWUgZm9yIHRoZSBzY2hlbWEgKGZvciBlcnJvciBtZXNzYWdlcylcbiAgICovXG4gIHNjaGVtYU5hbWU/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogUGFyc2VzIE9wZW5BUEkgc2NoZW1hIEpTT04gYW5kIHZhbGlkYXRlcyBmb3JtYXRcbiAqIEBpbnRlcm5hbFxuICovXG5mdW5jdGlvbiBwYXJzZU9wZW5BcGlKc29uKHNjaGVtYTogc3RyaW5nLCBzY2hlbWFOYW1lOiBzdHJpbmcsIGVycm9yczogc3RyaW5nW10pOiBhbnkgfCBudWxsIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gSlNPTi5wYXJzZShzY2hlbWEpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgZXJyb3JzLnB1c2goYCR7c2NoZW1hTmFtZX0gbXVzdCBiZSBpbiBKU09OIGZvcm1hdC4gWUFNTCBpcyBub3Qgc3VwcG9ydGVkLiBFcnJvcjogJHtlIGluc3RhbmNlb2YgRXJyb3IgPyBlLm1lc3NhZ2UgOiBTdHJpbmcoZSl9YCk7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbn1cblxuLyoqXG4gKiBWYWxpZGF0ZXMgT3BlbkFQSSB2ZXJzaW9uICgzLjAueCBvciAzLjEueClcbiAqIEBpbnRlcm5hbFxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZU9wZW5BcGlWZXJzaW9uKHNjaGVtYU9iajogYW55LCBzY2hlbWFOYW1lOiBzdHJpbmcsIGVycm9yczogc3RyaW5nW10pOiB2b2lkIHtcbiAgaWYgKCFzY2hlbWFPYmoub3BlbmFwaSkge1xuICAgIGVycm9ycy5wdXNoKGAke3NjaGVtYU5hbWV9IG11c3QgaW5jbHVkZSBhbiAnb3BlbmFwaScgZmllbGQgc3BlY2lmeWluZyB0aGUgdmVyc2lvbmApO1xuICB9IGVsc2Uge1xuICAgIGNvbnN0IHZlcnNpb24gPSBzY2hlbWFPYmoub3BlbmFwaTtcbiAgICBpZiAodHlwZW9mIHZlcnNpb24gIT09ICdzdHJpbmcnKSB7XG4gICAgICBlcnJvcnMucHVzaChgJHtzY2hlbWFOYW1lfSAnb3BlbmFwaScgZmllbGQgbXVzdCBiZSBhIHN0cmluZ2ApO1xuICAgIH0gZWxzZSBpZiAoIXZlcnNpb24uc3RhcnRzV2l0aCgnMy4wLicpICYmICF2ZXJzaW9uLnN0YXJ0c1dpdGgoJzMuMS4nKSkge1xuICAgICAgZXJyb3JzLnB1c2goYCR7c2NoZW1hTmFtZX0gdmVyc2lvbiAke3ZlcnNpb259IGlzIG5vdCBzdXBwb3J0ZWQuIE9ubHkgT3BlbkFQSSAzLjAueCBhbmQgMy4xLnggYXJlIHN1cHBvcnRlZGApO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIFZhbGlkYXRlcyBzZXJ2ZXIgVVJMc1xuICogQGludGVybmFsXG4gKi9cbmZ1bmN0aW9uIHZhbGlkYXRlU2VydmVyVXJscyhzY2hlbWFPYmo6IGFueSwgc2NoZW1hTmFtZTogc3RyaW5nLCBlcnJvcnM6IHN0cmluZ1tdKTogdm9pZCB7XG4gIGlmICghc2NoZW1hT2JqLnNlcnZlcnMgfHwgIUFycmF5LmlzQXJyYXkoc2NoZW1hT2JqLnNlcnZlcnMpIHx8IHNjaGVtYU9iai5zZXJ2ZXJzLmxlbmd0aCA9PT0gMCkge1xuICAgIGVycm9ycy5wdXNoKGAke3NjaGVtYU5hbWV9IG11c3QgaW5jbHVkZSBhdCBsZWFzdCBvbmUgc2VydmVyIHdpdGggYSB2YWxpZCBVUkxgKTtcbiAgfSBlbHNlIHtcbiAgICBzY2hlbWFPYmouc2VydmVycy5mb3JFYWNoKChzZXJ2ZXI6IGFueSwgaW5kZXg6IG51bWJlcikgPT4ge1xuICAgICAgaWYgKCFzZXJ2ZXIudXJsIHx8IHR5cGVvZiBzZXJ2ZXIudXJsICE9PSAnc3RyaW5nJykge1xuICAgICAgICBlcnJvcnMucHVzaChgJHtzY2hlbWFOYW1lfSBzZXJ2ZXJbJHtpbmRleH1dIG11c3QgaGF2ZSBhIHZhbGlkIFVSTGApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gQ2hlY2sgaWYgVVJMIGNvbnRhaW5zIGEgcHJvdG9jb2wgc2VwYXJhdG9yXG4gICAgICAgIGlmICghc2VydmVyLnVybC5pbmNsdWRlcygnOi8vJykpIHtcbiAgICAgICAgICBlcnJvcnMucHVzaChgJHtzY2hlbWFOYW1lfSBzZXJ2ZXJbJHtpbmRleH1dIFVSTCBtdXN0IGNvbnRhaW4gYSBwcm90b2NvbCAoZS5nLiwgaHR0cDovLyBvciBodHRwczovLylgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBDaGVjayBpZiBpdCBzdGFydHMgd2l0aCBodHRwIG9yIGh0dHBzIChjYXNlLWluc2Vuc2l0aXZlKVxuICAgICAgICAgIC8vIEFsbG93IHRlbXBsYXRlIHZhcmlhYmxlcyBsaWtlIHtwcm90b2NvbH06Ly9cbiAgICAgICAgICBjb25zdCBwcm90b2NvbEVuZCA9IHNlcnZlci51cmwuaW5kZXhPZignOi8vJyk7XG4gICAgICAgICAgY29uc3QgcHJvdG9jb2wgPSBzZXJ2ZXIudXJsLnN1YnN0cmluZygwLCBwcm90b2NvbEVuZCk7XG5cbiAgICAgICAgICAvLyBJZiBwcm90b2NvbCBkb2Vzbid0IGNvbnRhaW4gdGVtcGxhdGUgdmFyaWFibGVzLCB2YWxpZGF0ZSBpdFxuICAgICAgICAgIGlmICghcHJvdG9jb2wuaW5jbHVkZXMoJ3snKSkge1xuICAgICAgICAgICAgaWYgKHByb3RvY29sLnRvTG93ZXJDYXNlKCkgIT09ICdodHRwJyAmJiBwcm90b2NvbC50b0xvd2VyQ2FzZSgpICE9PSAnaHR0cHMnKSB7XG4gICAgICAgICAgICAgIGVycm9ycy5wdXNoKGAke3NjaGVtYU5hbWV9IHNlcnZlclske2luZGV4fV0gVVJMIG11c3QgdXNlIEhUVFAgb3IgSFRUUFMgcHJvdG9jb2xgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gSWYgcHJvdG9jb2wgY29udGFpbnMgdGVtcGxhdGUgdmFyaWFibGVzLCBza2lwIHZhbGlkYXRpb24gKHdpbGwgYmUgdmFsaWRhdGVkIGF0IHJ1bnRpbWUpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxufVxuXG4vKipcbiAqIFZhbGlkYXRlcyBwYXRocyBhbmQgb3BlcmF0aW9uc1xuICogQGludGVybmFsXG4gKi9cbmZ1bmN0aW9uIHZhbGlkYXRlUGF0aHNBbmRPcGVyYXRpb25zKHNjaGVtYU9iajogYW55LCBzY2hlbWFOYW1lOiBzdHJpbmcsIGVycm9yczogc3RyaW5nW10pOiB2b2lkIHtcbiAgaWYgKCFzY2hlbWFPYmoucGF0aHMgfHwgdHlwZW9mIHNjaGVtYU9iai5wYXRocyAhPT0gJ29iamVjdCcpIHtcbiAgICBlcnJvcnMucHVzaChgJHtzY2hlbWFOYW1lfSBtdXN0IGluY2x1ZGUgYSAncGF0aHMnIG9iamVjdGApO1xuICB9IGVsc2Uge1xuICAgIGNvbnN0IG9wZXJhdGlvbnNNaXNzaW5nSWQ6IHN0cmluZ1tdID0gW107XG4gICAgY29uc3QgdW5zdXBwb3J0ZWRNZWRpYVR5cGVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gICAgY29uc3QgcGF0aHNXaXRoQ29tcGxleFNlcmlhbGl6ZXJzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgT2JqZWN0LmVudHJpZXMoc2NoZW1hT2JqLnBhdGhzKS5mb3JFYWNoKChbcGF0aCwgcGF0aEl0ZW1dOiBbc3RyaW5nLCBhbnldKSA9PiB7XG4gICAgICAvLyBDaGVjayBmb3IgY29tcGxleCBwYXRoIHBhcmFtZXRlciBzZXJpYWxpemVyc1xuICAgICAgaWYgKHBhdGguaW5jbHVkZXMoJ3s7JykgfHwgcGF0aC5pbmNsdWRlcygnez8nKSB8fCBwYXRoLmluY2x1ZGVzKCd7Kn0nKSkge1xuICAgICAgICBwYXRoc1dpdGhDb21wbGV4U2VyaWFsaXplcnMucHVzaChwYXRoKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHBhdGhJdGVtICYmIHR5cGVvZiBwYXRoSXRlbSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgLy8gQ2hlY2sgZWFjaCBIVFRQIG1ldGhvZFxuICAgICAgICBjb25zdCBodHRwTWV0aG9kcyA9IFsnZ2V0JywgJ3Bvc3QnLCAncHV0JywgJ2RlbGV0ZScsICdwYXRjaCcsICdoZWFkJywgJ29wdGlvbnMnXTtcbiAgICAgICAgaHR0cE1ldGhvZHMuZm9yRWFjaChtZXRob2QgPT4ge1xuICAgICAgICAgIGlmIChwYXRoSXRlbVttZXRob2RdKSB7XG4gICAgICAgICAgICBjb25zdCBvcGVyYXRpb24gPSBwYXRoSXRlbVttZXRob2RdO1xuXG4gICAgICAgICAgICAvLyBDaGVjayBmb3Igb3BlcmF0aW9uSWQgKFJFUVVJUkVEKVxuICAgICAgICAgICAgaWYgKCFvcGVyYXRpb24ub3BlcmF0aW9uSWQpIHtcbiAgICAgICAgICAgICAgb3BlcmF0aW9uc01pc3NpbmdJZC5wdXNoKGAke21ldGhvZC50b1VwcGVyQ2FzZSgpfSAke3BhdGh9YCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENoZWNrIHJlcXVlc3QgYm9keSBtZWRpYSB0eXBlc1xuICAgICAgICAgICAgaWYgKG9wZXJhdGlvbi5yZXF1ZXN0Qm9keT8uY29udGVudCkge1xuICAgICAgICAgICAgICBPYmplY3Qua2V5cyhvcGVyYXRpb24ucmVxdWVzdEJvZHkuY29udGVudCkuZm9yRWFjaChtZWRpYVR5cGUgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChtZWRpYVR5cGUgIT09ICdhcHBsaWNhdGlvbi9qc29uJyAmJlxuICAgICAgICAgICAgICAgICAgICBtZWRpYVR5cGUgIT09ICdhcHBsaWNhdGlvbi94bWwnICYmXG4gICAgICAgICAgICAgICAgICAgIG1lZGlhVHlwZSAhPT0gJ211bHRpcGFydC9mb3JtLWRhdGEnICYmXG4gICAgICAgICAgICAgICAgICAgIG1lZGlhVHlwZSAhPT0gJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCcpIHtcbiAgICAgICAgICAgICAgICAgIHVuc3VwcG9ydGVkTWVkaWFUeXBlcy5hZGQobWVkaWFUeXBlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDaGVjayByZXNwb25zZSBtZWRpYSB0eXBlc1xuICAgICAgICAgICAgaWYgKG9wZXJhdGlvbi5yZXNwb25zZXMpIHtcbiAgICAgICAgICAgICAgT2JqZWN0LnZhbHVlcyhvcGVyYXRpb24ucmVzcG9uc2VzKS5mb3JFYWNoKChyZXNwb25zZTogYW55KSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlLmNvbnRlbnQpIHtcbiAgICAgICAgICAgICAgICAgIE9iamVjdC5rZXlzKHJlc3BvbnNlLmNvbnRlbnQpLmZvckVhY2gobWVkaWFUeXBlID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1lZGlhVHlwZSAhPT0gJ2FwcGxpY2F0aW9uL2pzb24nICYmXG4gICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVR5cGUgIT09ICdhcHBsaWNhdGlvbi94bWwnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgdW5zdXBwb3J0ZWRNZWRpYVR5cGVzLmFkZChtZWRpYVR5cGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDaGVjayBmb3IgY29tcGxleCBwYXJhbWV0ZXIgc2VyaWFsaXplcnNcbiAgICAgICAgICAgIGlmIChvcGVyYXRpb24ucGFyYW1ldGVycykge1xuICAgICAgICAgICAgICBvcGVyYXRpb24ucGFyYW1ldGVycy5mb3JFYWNoKChwYXJhbTogYW55LCBpZHg6IG51bWJlcikgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChwYXJhbS5zdHlsZSAmJiBbJ21hdHJpeCcsICdsYWJlbCcsICdkZWVwT2JqZWN0J10uaW5jbHVkZXMocGFyYW0uc3R5bGUpKSB7XG4gICAgICAgICAgICAgICAgICBlcnJvcnMucHVzaChgJHtzY2hlbWFOYW1lfSAke21ldGhvZC50b1VwcGVyQ2FzZSgpfSAke3BhdGh9IHBhcmFtZXRlclske2lkeH1dIHVzZXMgdW5zdXBwb3J0ZWQgc2VyaWFsaXphdGlvbiBzdHlsZTogJHtwYXJhbS5zdHlsZX1gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpZiAob3BlcmF0aW9uc01pc3NpbmdJZC5sZW5ndGggPiAwKSB7XG4gICAgICBlcnJvcnMucHVzaChgJHtzY2hlbWFOYW1lfSBvcGVyYXRpb25zIG11c3QgaW5jbHVkZSAnb3BlcmF0aW9uSWQnIGZpZWxkLiBNaXNzaW5nIGluOiAke29wZXJhdGlvbnNNaXNzaW5nSWQuam9pbignLCAnKX1gKTtcbiAgICB9XG5cbiAgICBpZiAocGF0aHNXaXRoQ29tcGxleFNlcmlhbGl6ZXJzLmxlbmd0aCA+IDApIHtcbiAgICAgIGVycm9ycy5wdXNoKGAke3NjaGVtYU5hbWV9IGNvbnRhaW5zIHVuc3VwcG9ydGVkIGNvbXBsZXggcGF0aCBwYXJhbWV0ZXIgc2VyaWFsaXplcnMgaW46ICR7cGF0aHNXaXRoQ29tcGxleFNlcmlhbGl6ZXJzLmpvaW4oJywgJyl9YCk7XG4gICAgfVxuXG4gICAgaWYgKHVuc3VwcG9ydGVkTWVkaWFUeXBlcy5zaXplID4gMCkge1xuICAgICAgY29uc3QgbWVkaWFUeXBlc0xpc3QgPSBBcnJheS5mcm9tKHVuc3VwcG9ydGVkTWVkaWFUeXBlcykuam9pbignLCAnKTtcbiAgICAgIGVycm9ycy5wdXNoKGAke3NjaGVtYU5hbWV9IHVzZXMgdW5zdXBwb3J0ZWQgbWVkaWEgdHlwZXM6ICR7bWVkaWFUeXBlc0xpc3R9LiBPbmx5IGFwcGxpY2F0aW9uL2pzb24sIGFwcGxpY2F0aW9uL3htbCwgbXVsdGlwYXJ0L2Zvcm0tZGF0YSwgYW5kIGFwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCBhcmUgc3VwcG9ydGVkYCk7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogUmVjdXJzaXZlIGhlbHBlciB0byBjaGVjayBmb3IgdW5zdXBwb3J0ZWQgc2NoZW1hIGNvbXBvc2l0aW9uIChvbmVPZiwgYW55T2YsIGFsbE9mKVxuICogQGludGVybmFsXG4gKi9cbmZ1bmN0aW9uIGNoZWNrU2NoZW1hQ29tcG9zaXRpb24ob2JqOiBhbnksIHNjaGVtYU5hbWU6IHN0cmluZywgZXJyb3JzOiBzdHJpbmdbXSwgcGF0aDogc3RyaW5nID0gJycpOiB2b2lkIHtcbiAgaWYgKCFvYmogfHwgdHlwZW9mIG9iaiAhPT0gJ29iamVjdCcpIHJldHVybjtcblxuICAvLyBDaGVjayBjdXJyZW50IGxldmVsIGZvciB1bnN1cHBvcnRlZCBrZXl3b3Jkc1xuICBpZiAoJ29uZU9mJyBpbiBvYmopIHtcbiAgICBlcnJvcnMucHVzaChgJHtzY2hlbWFOYW1lfSBjb250YWlucyB1bnN1cHBvcnRlZCAnb25lT2YnIHNjaGVtYSBjb21wb3NpdGlvbiBhdCAke3BhdGggfHwgJ3Jvb3QnfWApO1xuICB9XG4gIGlmICgnYW55T2YnIGluIG9iaikge1xuICAgIGVycm9ycy5wdXNoKGAke3NjaGVtYU5hbWV9IGNvbnRhaW5zIHVuc3VwcG9ydGVkICdhbnlPZicgc2NoZW1hIGNvbXBvc2l0aW9uIGF0ICR7cGF0aCB8fCAncm9vdCd9YCk7XG4gIH1cbiAgaWYgKCdhbGxPZicgaW4gb2JqKSB7XG4gICAgZXJyb3JzLnB1c2goYCR7c2NoZW1hTmFtZX0gY29udGFpbnMgdW5zdXBwb3J0ZWQgJ2FsbE9mJyBzY2hlbWEgY29tcG9zaXRpb24gYXQgJHtwYXRoIHx8ICdyb290J31gKTtcbiAgfVxuXG4gIC8vIFJlY3Vyc2l2ZWx5IGNoZWNrIG5lc3RlZCBvYmplY3RzXG4gIE9iamVjdC5lbnRyaWVzKG9iaikuZm9yRWFjaCgoW2tleSwgdmFsdWVdKSA9PiB7XG4gICAgaWYgKGtleSAhPT0gJ29uZU9mJyAmJiBrZXkgIT09ICdhbnlPZicgJiYga2V5ICE9PSAnYWxsT2YnICYmIHZhbHVlICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgIGNvbnN0IG5ld1BhdGggPSBwYXRoID8gYCR7cGF0aH0uJHtrZXl9YCA6IGtleTtcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgICB2YWx1ZS5mb3JFYWNoKChpdGVtLCBpbmRleCkgPT4ge1xuICAgICAgICAgIGNoZWNrU2NoZW1hQ29tcG9zaXRpb24oaXRlbSwgc2NoZW1hTmFtZSwgZXJyb3JzLCBgJHtuZXdQYXRofVske2luZGV4fV1gKTtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjaGVja1NjaGVtYUNvbXBvc2l0aW9uKHZhbHVlLCBzY2hlbWFOYW1lLCBlcnJvcnMsIG5ld1BhdGgpO1xuICAgICAgfVxuICAgIH1cbiAgfSk7XG59XG5cbi8qKlxuICogVmFsaWRhdGVzIHNjaGVtYSBjb21wb3NpdGlvbiAoY2hlY2tzIGZvciB1bnN1cHBvcnRlZCBvbmVPZiwgYW55T2YsIGFsbE9mKVxuICogQGludGVybmFsXG4gKi9cbmZ1bmN0aW9uIHZhbGlkYXRlU2NoZW1hQ29tcG9zaXRpb24oc2NoZW1hT2JqOiBhbnksIHNjaGVtYU5hbWU6IHN0cmluZywgZXJyb3JzOiBzdHJpbmdbXSk6IHZvaWQge1xuICAvLyBDaGVjayBjb21wb25lbnRzL2RlZmluaXRpb25zIGZvciB1bnN1cHBvcnRlZCBzY2hlbWEgY29tcG9zaXRpb25cbiAgaWYgKHNjaGVtYU9iai5jb21wb25lbnRzPy5zY2hlbWFzKSB7XG4gICAgY2hlY2tTY2hlbWFDb21wb3NpdGlvbihzY2hlbWFPYmouY29tcG9uZW50cy5zY2hlbWFzLCBzY2hlbWFOYW1lLCBlcnJvcnMsICdjb21wb25lbnRzLnNjaGVtYXMnKTtcbiAgfVxuICBpZiAoc2NoZW1hT2JqLmRlZmluaXRpb25zKSB7XG4gICAgY2hlY2tTY2hlbWFDb21wb3NpdGlvbihzY2hlbWFPYmouZGVmaW5pdGlvbnMsIHNjaGVtYU5hbWUsIGVycm9ycywgJ2RlZmluaXRpb25zJyk7XG4gIH1cblxuICAvLyBDaGVjayBwYXRocyBmb3IgdW5zdXBwb3J0ZWQgc2NoZW1hIGNvbXBvc2l0aW9uXG4gIGlmIChzY2hlbWFPYmoucGF0aHMpIHtcbiAgICBjaGVja1NjaGVtYUNvbXBvc2l0aW9uKHNjaGVtYU9iai5wYXRocywgc2NoZW1hTmFtZSwgZXJyb3JzLCAncGF0aHMnKTtcbiAgfVxufVxuXG4vKipcbiAqIFZhbGlkYXRlcyBzZWN1cml0eSBzY2hlbWVzXG4gKiBAaW50ZXJuYWxcbiAqL1xuZnVuY3Rpb24gdmFsaWRhdGVTZWN1cml0eVNjaGVtZXMoc2NoZW1hT2JqOiBhbnksIHNjaGVtYU5hbWU6IHN0cmluZywgZXJyb3JzOiBzdHJpbmdbXSk6IHZvaWQge1xuICBpZiAoc2NoZW1hT2JqLnNlY3VyaXR5ICYmIEFycmF5LmlzQXJyYXkoc2NoZW1hT2JqLnNlY3VyaXR5KSAmJiBzY2hlbWFPYmouc2VjdXJpdHkubGVuZ3RoID4gMCkge1xuICAgIGVycm9ycy5wdXNoKGAke3NjaGVtYU5hbWV9IGNvbnRhaW5zIHNlY3VyaXR5IHNjaGVtZXMgYXQgdGhlIE9wZW5BUEkgc3BlY2lmaWNhdGlvbiBsZXZlbC4gQXV0aGVudGljYXRpb24gbXVzdCBiZSBjb25maWd1cmVkIHVzaW5nIHRoZSBHYXRld2F5J3Mgb3V0Ym91bmQgYXV0aG9yaXphdGlvbiBjb25maWd1cmF0aW9uIGluc3RlYWRgKTtcbiAgfVxufVxuXG4vKipcbiAqIFZhbGlkYXRlcyBjYWxsYmFja3MgYW5kIHdlYmhvb2tzXG4gKiBAaW50ZXJuYWxcbiAqL1xuZnVuY3Rpb24gdmFsaWRhdGVDYWxsYmFja3NBbmRXZWJob29rcyhzY2hlbWFPYmo6IGFueSwgc2NoZW1hTmFtZTogc3RyaW5nLCBlcnJvcnM6IHN0cmluZ1tdKTogdm9pZCB7XG4gIC8vIENoZWNrIGZvciBjYWxsYmFja3MgaW4gb3BlcmF0aW9uc1xuICBpZiAoc2NoZW1hT2JqLnBhdGhzKSB7XG4gICAgT2JqZWN0LmVudHJpZXMoc2NoZW1hT2JqLnBhdGhzKS5mb3JFYWNoKChbcGF0aCwgcGF0aEl0ZW1dOiBbc3RyaW5nLCBhbnldKSA9PiB7XG4gICAgICBpZiAocGF0aEl0ZW0gJiYgdHlwZW9mIHBhdGhJdGVtID09PSAnb2JqZWN0Jykge1xuICAgICAgICBPYmplY3QudmFsdWVzKHBhdGhJdGVtKS5mb3JFYWNoKChvcGVyYXRpb246IGFueSkgPT4ge1xuICAgICAgICAgIGlmIChvcGVyYXRpb24gJiYgdHlwZW9mIG9wZXJhdGlvbiA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIGlmIChvcGVyYXRpb24uY2FsbGJhY2tzKSB7XG4gICAgICAgICAgICAgIGVycm9ycy5wdXNoKGAke3NjaGVtYU5hbWV9IGNvbnRhaW5zIHVuc3VwcG9ydGVkICdjYWxsYmFja3MnIGluIHBhdGggJHtwYXRofWApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvLyBDaGVjayBmb3Igd2ViaG9va3NcbiAgaWYgKHNjaGVtYU9iai53ZWJob29rcykge1xuICAgIGVycm9ycy5wdXNoKGAke3NjaGVtYU5hbWV9IGNvbnRhaW5zIHVuc3VwcG9ydGVkICd3ZWJob29rcydgKTtcbiAgfVxufVxuXG4vKipcbiAqIFZhbGlkYXRlcyBhbiBPcGVuQVBJIHNjaGVtYSBhZ2FpbnN0IEdhdGV3YXkgcmVxdWlyZW1lbnRzXG4gKiBCYXNlZCBvbiBBV1MgZG9jdW1lbnRhdGlvbjogaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2JlZHJvY2stYWdlbnRjb3JlL2xhdGVzdC9kZXZndWlkZS9nYXRld2F5LXNjaGVtYS1vcGVuYXBpLmh0bWxcbiAqXG4gKiBAcGFyYW0gcGFyYW1zIC0gVGhlIHZhbGlkYXRpb24gcGFyYW1ldGVyc1xuICogQHJldHVybnMgQXJyYXkgb2YgdmFsaWRhdGlvbiBlcnJvciBtZXNzYWdlcyAoZW1wdHkgaWYgdmFsaWQpXG4gKiBAaW50ZXJuYWxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlT3BlbkFwaVNjaGVtYShwYXJhbXM6IE9wZW5BcGlTY2hlbWFWYWxpZGF0aW9uUGFyYW1zKTogc3RyaW5nW10ge1xuICBjb25zdCBlcnJvcnM6IHN0cmluZ1tdID0gW107XG4gIGNvbnN0IHsgc2NoZW1hLCBzY2hlbWFOYW1lID0gJ09wZW5BUEkgc2NoZW1hJyB9ID0gcGFyYW1zO1xuXG4gIGlmIChUb2tlbi5pc1VucmVzb2x2ZWQoc2NoZW1hKSkge1xuICAgIHJldHVybiBlcnJvcnM7XG4gIH1cbiAgY29uc3Qgc2NoZW1hT2JqID0gcGFyc2VPcGVuQXBpSnNvbihzY2hlbWEsIHNjaGVtYU5hbWUsIGVycm9ycyk7XG4gIGlmICghc2NoZW1hT2JqKSByZXR1cm4gZXJyb3JzO1xuXG4gIHZhbGlkYXRlT3BlbkFwaVZlcnNpb24oc2NoZW1hT2JqLCBzY2hlbWFOYW1lLCBlcnJvcnMpO1xuICB2YWxpZGF0ZVNlcnZlclVybHMoc2NoZW1hT2JqLCBzY2hlbWFOYW1lLCBlcnJvcnMpO1xuICB2YWxpZGF0ZVBhdGhzQW5kT3BlcmF0aW9ucyhzY2hlbWFPYmosIHNjaGVtYU5hbWUsIGVycm9ycyk7XG4gIHZhbGlkYXRlU2NoZW1hQ29tcG9zaXRpb24oc2NoZW1hT2JqLCBzY2hlbWFOYW1lLCBlcnJvcnMpO1xuICB2YWxpZGF0ZVNlY3VyaXR5U2NoZW1lcyhzY2hlbWFPYmosIHNjaGVtYU5hbWUsIGVycm9ycyk7XG4gIHZhbGlkYXRlQ2FsbGJhY2tzQW5kV2ViaG9va3Moc2NoZW1hT2JqLCBzY2hlbWFOYW1lLCBlcnJvcnMpO1xuXG4gIHJldHVybiBlcnJvcnM7XG59XG4iXX0=