UNPKG

cdk-nextjs-standalone

Version:

Deploy a NextJS app to AWS using CDK and OpenNext.

345 lines 49.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.handler = void 0; /* eslint-disable import/no-extraneous-dependencies */ const node_fs_1 = require("node:fs"); const node_os_1 = require("node:os"); const node_path_1 = require("node:path"); const node_stream_1 = require("node:stream"); const client_s3_1 = require("@aws-sdk/client-s3"); const lib_storage_1 = require("@aws-sdk/lib-storage"); // @ts-ignore jsii doesn't support esModuleInterop // eslint-disable-next-line no-duplicate-imports const jszip_1 = require("jszip"); const micromatch = require("micromatch"); const mime = require("mime-types"); const JSZip = jszip_1.default; const s3 = new client_s3_1.S3Client({}); const handler = async (event, context) => { debug({ event }); let responseStatus = 'SUCCESS'; try { if (event.RequestType === 'Create' || event.RequestType === 'Update') { const props = getProperties(event); let tmpDir = ''; const { assetsTmpDir, sourceDirPath, sourceZipFilePath } = initDirectories(); tmpDir = assetsTmpDir; debug('Downloading zip'); await downloadFile({ bucket: props.sourceBucketName, key: props.sourceKeyPrefix, localDestinationPath: sourceZipFilePath, }); debug('Extracting zip'); await extractZip({ sourceZipFilePath, destinationDirPath: sourceDirPath }); const filePaths = listFilePaths(sourceDirPath); if (props.substitutionConfig && Object.keys(props.substitutionConfig).length) { debug('Replacing environment variables: ' + JSON.stringify(props.substitutionConfig)); substitute({ config: props.substitutionConfig, filePaths }); } // must find old object keys before uploading new objects so we know which objects to prune const oldObjectKeys = await listOldObjectKeys({ bucketName: props.destinationBucketName, keyPrefix: props.destinationKeyPrefix, }); if (!props.zip) { debug('Uploading objects to: ' + props.destinationBucketName); await uploadObjects({ bucket: props.destinationBucketName, keyPrefix: props.destinationKeyPrefix, filePaths, baseLocalDir: sourceDirPath, putConfig: props.putConfig, queueSize: props.queueSize, }); if (props.prune) { debug('Emptying/pruning bucket: ' + props.destinationBucketName); await pruneBucket({ bucketName: props.destinationBucketName, filePaths, baseLocalDir: sourceDirPath, keyPrefix: props.destinationKeyPrefix, oldObjectKeys, }); } } else { debug('Uploading zip to: ' + props.destinationBucketName); const zipBuffer = await zipObjects({ tmpDir: sourceDirPath }); await uploadZip({ zipBuffer, bucket: props.destinationBucketName, keyPrefix: props.destinationKeyPrefix, }); } if (tmpDir.length) { debug('Removing temp directory'); (0, node_fs_1.rmSync)(tmpDir, { force: true, recursive: true }); } responseStatus = 'SUCCESS'; } } catch (err) { console.error(err); responseStatus = 'FAILED'; } await cfnResponse({ event, context, responseStatus }); }; exports.handler = handler; function debug(value) { if (process.env.DEBUG) console.log(JSON.stringify(value, null, 2)); } function getProperties(event) { const props = event.ResourceProperties; return { ...props, prune: props.prune === 'true', zip: props.zip === 'true', }; } function initDirectories() { const assetsTmpDir = (0, node_fs_1.mkdtempSync)((0, node_path_1.resolve)((0, node_os_1.tmpdir)(), 'assets-')); const sourceZipDirPath = (0, node_path_1.resolve)(assetsTmpDir, 'source-zip'); (0, node_fs_1.mkdirSync)(sourceZipDirPath); const sourceZipFilePath = (0, node_path_1.resolve)(sourceZipDirPath, 'temp.zip'); // trailing slash expected by adm-zip's `extractAllTo` method const sourceDirPath = (0, node_path_1.resolve)(assetsTmpDir, 'source') + '/'; (0, node_fs_1.mkdirSync)(sourceDirPath); return { assetsTmpDir, sourceZipFilePath, sourceDirPath }; } async function downloadFile({ bucket, key, localDestinationPath, }) { const data = await s3.send(new client_s3_1.GetObjectCommand({ Bucket: bucket, Key: key })); return new Promise(async (resolve, reject) => { const body = data.Body; if (body instanceof node_stream_1.Readable) { const writeStream = (0, node_fs_1.createWriteStream)(localDestinationPath); body .pipe(writeStream) .on('error', (err) => reject(err)) .on('close', () => resolve(null)); } }); } async function extractZip({ sourceZipFilePath, destinationDirPath, }) { const zipBuffer = (0, node_fs_1.readFileSync)(sourceZipFilePath); const archive = await JSZip.loadAsync(zipBuffer); for (const [zipRelativePath, zipObject] of Object.entries(archive.files)) { if (!zipObject.dir) { const absPath = (0, node_path_1.resolve)(destinationDirPath, zipRelativePath); const pathDirname = (0, node_path_1.dirname)(absPath); if (!(0, node_fs_1.existsSync)(pathDirname)) { (0, node_fs_1.mkdirSync)(pathDirname, { recursive: true }); } const fileContents = await zipObject.async('nodebuffer'); let isSymLink = false; const unixPermissions = zipObject?.unixPermissions; if (typeof unixPermissions === 'number') { // https://github.com/twolfson/grunt-zip/pull/52/files // eslint-disable-next-line no-bitwise isSymLink = (unixPermissions & 0xf000) === 0xa000; } if (isSymLink) { (0, node_fs_1.symlinkSync)(fileContents, absPath); } else { (0, node_fs_1.writeFileSync)(absPath, fileContents); } } } } /** * Given path of directory, returns array of all file paths within directory */ function listFilePaths(dirPath) { const filePaths = []; const directory = (0, node_fs_1.readdirSync)(dirPath, { withFileTypes: true }); for (const d of directory) { const filePath = (0, node_path_1.resolve)(dirPath, d.name); if (d.isDirectory()) { filePaths.push(...listFilePaths(filePath)); } else { filePaths.push(filePath); } } return filePaths; } function substitute({ filePaths, config }) { const findRegExp = new RegExp(Object.keys(config).join('|'), 'g'); for (const filePath of filePaths) { if (filePath.includes('node_modules')) continue; const fileContents = (0, node_fs_1.readFileSync)(filePath, { encoding: 'utf8' }); const newFileContents = fileContents.replace(findRegExp, (matched) => { const matchedEnvVar = config[matched]; if (matchedEnvVar) { return matchedEnvVar; } else { console.warn(`Could not find matched value: ${matched} in environment object. Substituting ''`); return ''; } }); if (fileContents !== newFileContents) { (0, node_fs_1.writeFileSync)(filePath, newFileContents); } } } async function listOldObjectKeys({ bucketName, keyPrefix, }) { const oldObjectKeys = []; let nextToken = undefined; do { const cmd = { Bucket: bucketName, Prefix: keyPrefix }; if (nextToken) { cmd.ContinuationToken = nextToken; } const res = await s3.send(new client_s3_1.ListObjectsV2Command(cmd)); const contents = res.Contents; nextToken = res.NextContinuationToken; if (contents?.length) { for (const { Key: key } of contents) { if (key) { oldObjectKeys.push(key); } } } } while (nextToken); return oldObjectKeys; } /** * Create S3 Key given local path */ function createS3Key({ keyPrefix, path, baseLocalDir }) { const objectKeyParts = []; if (keyPrefix) objectKeyParts.push(keyPrefix); objectKeyParts.push((0, node_path_1.relative)(baseLocalDir, path)); return (0, node_path_1.join)(...objectKeyParts); } async function* chunkArray(array, chunkSize) { for (let i = 0; i < array.length; i += chunkSize) { yield array.slice(i, i + chunkSize); } } async function uploadObjects({ bucket, keyPrefix, filePaths, baseLocalDir, putConfig = {}, queueSize, }) { for await (const filePathChunk of chunkArray(filePaths, 100)) { const putObjectInputs = filePathChunk.map((path) => { const contentType = mime.lookup(path) || undefined; const putObjectOptions = getPutObjectOptions({ path, putConfig }); const key = createS3Key({ keyPrefix, path, baseLocalDir }); return { ContentType: contentType, ...putObjectOptions, Bucket: bucket, Key: key, Body: (0, node_fs_1.createReadStream)(path), }; }); // Call put objects serially, prevents XAmzContentSHA256Mismatch errors // This seems to be a bug within the lib storage package, I have opened an issue here: https://github.com/aws/aws-sdk-js-v3/issues/6940 await putObjectInputs.reduce(async (acc, params) => { await acc; const opts = { client: s3, params, }; if (queueSize) { opts.queueSize = queueSize; } const upload = new lib_storage_1.Upload(opts); console.log('uploading', params); return upload.done(); }, Promise.resolve(null)); } } /** * Zips objects taking into account symlinks * @see https://github.com/Stuk/jszip/issues/386#issuecomment-634773343 */ function zipObjects({ tmpDir }) { const zip = new JSZip(); const filePaths = listFilePaths(tmpDir); for (const filePath of filePaths) { const relativePath = (0, node_path_1.relative)(tmpDir, filePath); const stat = (0, node_fs_1.lstatSync)(filePath); if (stat.isSymbolicLink()) { zip.file(relativePath, (0, node_fs_1.readlinkSync)(filePath), { dir: stat.isDirectory(), unixPermissions: parseInt('120755', 8), }); } else { zip.file(relativePath, (0, node_fs_1.readFileSync)(filePath), { dir: stat.isDirectory(), unixPermissions: stat.mode }); } } return zip.generateAsync({ type: 'nodebuffer', platform: 'UNIX', compression: 'STORE', }); } async function uploadZip({ bucket, keyPrefix, zipBuffer, }) { return s3.send(new client_s3_1.PutObjectCommand({ Bucket: bucket, Key: keyPrefix, Body: zipBuffer, ContentType: 'application/zip', })); } function getPutObjectOptions({ path, putConfig = {}, }) { let putObjectOptions = {}; for (const [key, value] of Object.entries(putConfig)) { if (micromatch.isMatch(path, key)) { putObjectOptions = { ...putObjectOptions, ...value }; } } return putObjectOptions; } async function pruneBucket({ bucketName, filePaths, baseLocalDir, keyPrefix, oldObjectKeys, }) { const newObjectKeys = filePaths.map((path) => createS3Key({ keyPrefix, path, baseLocalDir })); // find old objects that are not currently in new objects to prune. const oldObjectKeysToBeDeleted = []; for (const key of oldObjectKeys) { if (!newObjectKeys.includes(key)) { oldObjectKeysToBeDeleted.push(key); } } if (oldObjectKeysToBeDeleted.length) { const deletePromises = []; // AWS limits S3 delete commands to 1000 keys per call const deleteCommandLimit = 1000; for (let i = 0; i < oldObjectKeysToBeDeleted.length; i += deleteCommandLimit) { const objectChunk = oldObjectKeysToBeDeleted.slice(i, i + deleteCommandLimit); deletePromises.push(s3.send(new client_s3_1.DeleteObjectsCommand({ Bucket: bucketName, Delete: { Objects: objectChunk.map((k) => ({ Key: k })) }, }))); } await Promise.all(deletePromises); debug(`Objects pruned in ${bucketName}: ${oldObjectKeysToBeDeleted.join(', ')}`); } else { debug(`No objects to prune`); } } /** * Inspired by: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-lambda-function-code-cfnresponsemodule.html */ function cfnResponse(props) { const body = JSON.stringify({ Status: props.responseStatus, Reason: 'See the details in CloudWatch Log Stream: ' + props.context.logStreamName, PhysicalResourceId: props.physicalResourceId || props.context.logStreamName, StackId: props.event.StackId, RequestId: props.event.RequestId, LogicalResourceId: props.event.LogicalResourceId, Data: props.responseData, }); return fetch(props.event.ResponseURL, { method: 'PUT', body, headers: { 'content-type': '', 'content-length': body.length.toString() }, }); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmV4dGpzLWJ1Y2tldC1kZXBsb3ltZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xhbWJkYXMvbmV4dGpzLWJ1Y2tldC1kZXBsb3ltZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHNEQUFzRDtBQUN0RCxxQ0FhaUI7QUFDakIscUNBQWlDO0FBQ2pDLHlDQUE0RTtBQUM1RSw2Q0FBdUM7QUFDdkMsa0RBUTRCO0FBQzVCLHNEQUF1RDtBQUd2RCxrREFBa0Q7QUFDbEQsZ0RBQWdEO0FBQ2hELGlDQUEyQjtBQUMzQix5Q0FBeUM7QUFDekMsbUNBQW1DO0FBRW5DLE1BQU0sS0FBSyxHQUFHLGVBQW1CLENBQUM7QUFFbEMsTUFBTSxFQUFFLEdBQUcsSUFBSSxvQkFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBRXJCLE1BQU0sT0FBTyxHQUF3QyxLQUFLLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRSxFQUFFO0lBQ25GLEtBQUssQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7SUFDakIsSUFBSSxjQUFjLEdBQXlCLFNBQVMsQ0FBQztJQUNyRCxJQUFJLENBQUM7UUFDSCxJQUFJLEtBQUssQ0FBQyxXQUFXLEtBQUssUUFBUSxJQUFJLEtBQUssQ0FBQyxXQUFXLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDckUsTUFBTSxLQUFLLEdBQUcsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ25DLElBQUksTUFBTSxHQUFHLEVBQUUsQ0FBQztZQUNoQixNQUFNLEVBQUUsWUFBWSxFQUFFLGFBQWEsRUFBRSxpQkFBaUIsRUFBRSxHQUFHLGVBQWUsRUFBRSxDQUFDO1lBQzdFLE1BQU0sR0FBRyxZQUFZLENBQUM7WUFDdEIsS0FBSyxDQUFDLGlCQUFpQixDQUFDLENBQUM7WUFDekIsTUFBTSxZQUFZLENBQUM7Z0JBQ2pCLE1BQU0sRUFBRSxLQUFLLENBQUMsZ0JBQWdCO2dCQUM5QixHQUFHLEVBQUUsS0FBSyxDQUFDLGVB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RSxFQUFFLEVBQUUsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUUsRUFBRTtLQUMxRSxDQUFDLENBQUM7QUFDTCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgaW1wb3J0L25vLWV4dHJhbmVvdXMtZGVwZW5kZW5jaWVzICovXG5pbXBvcnQge1xuICBjcmVhdGVSZWFkU3RyZWFtLFxuICBjcmVhdGVXcml0ZVN0cmVhbSxcbiAgZXhpc3RzU3luYyxcbiAgbHN0YXRTeW5jLFxuICBta2RpclN5bmMsXG4gIG1rZHRlbXBTeW5jLFxuICByZWFkZGlyU3luYyxcbiAgcmVhZEZpbGVTeW5jLFxuICByZWFkbGlua1N5bmMsXG4gIHJtU3luYyxcbiAgc3ltbGlua1N5bmMsXG4gIHdyaXRlRmlsZVN5bmMsXG59IGZyb20gJ25vZGU6ZnMnO1xuaW1wb3J0IHsgdG1wZGlyIH0gZnJvbSAnbm9kZTpvcyc7XG5pbXBvcnQgeyBkaXJuYW1lLCBqb2luLCByZWxhdGl2ZSwgcmVzb2x2ZSBhcyByZXNvbHZlUGF0aCB9IGZyb20gJ25vZGU6cGF0aCc7XG5pbXBvcnQgeyBSZWFkYWJsZSB9IGZyb20gJ25vZGU6c3RyZWFtJztcbmltcG9ydCB7XG4gIERlbGV0ZU9iamVjdHNDb21tYW5kLFxuICBHZXRPYmplY3RDb21tYW5kLFxuICBMaXN0T2JqZWN0c1YyQ29tbWFuZCxcbiAgdHlwZSBMaXN0T2JqZWN0c1YyQ29tbWFuZElucHV0LFxuICBQdXRPYmplY3RDb21tYW5kLFxuICB0eXBlIFB1dE9iamVjdENvbW1hbmRJbnB1dCxcbiAgUzNDbGllbnQsXG59IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1zMyc7XG5pbXBvcnQgeyBPcHRpb25zLCBVcGxvYWQgfSBmcm9tICdAYXdzLXNkay9saWItc3RvcmFnZSc7XG5pbXBvcnQgdHlwZSB7IENsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VIYW5kbGVyIH0gZnJvbSAnYXdzLWxhbWJkYSc7XG5pbXBvcnQgdHlwZSAqIGFzIEpTWmlwVHlwZSBmcm9tICdqc3ppcCc7XG4vLyBAdHMtaWdub3JlIGpzaWkgZG9lc24ndCBzdXBwb3J0IGVzTW9kdWxlSW50ZXJvcFxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWR1cGxpY2F0ZS1pbXBvcnRzXG5pbXBvcnQgX0pTWmlwIGZyb20gJ2pzemlwJztcbmltcG9ydCAqIGFzIG1pY3JvbWF0Y2ggZnJvbSAnbWljcm9tYXRjaCc7XG5pbXBvcnQgKiBhcyBtaW1lIGZyb20gJ21pbWUtdHlwZXMnO1xuaW1wb3J0IHR5cGUgeyBDdXN0b21SZXNvdXJjZVByb3BlcnRpZXMsIE5leHRqc0J1Y2tldERlcGxveW1lbnRQcm9wcyB9IGZyb20gJy4uL05leHRqc0J1Y2tldERlcGxveW1lbnQnO1xuY29uc3QgSlNaaXAgPSBfSlNaaXAgYXMgSlNaaXBUeXBlO1xuXG5jb25zdCBzMyA9IG5ldyBTM0NsaWVudCh7fSk7XG5cbmV4cG9ydCBjb25zdCBoYW5kbGVyOiBDbG91ZEZvcm1hdGlvbkN1c3RvbVJlc291cmNlSGFuZGxlciA9IGFzeW5jIChldmVudCwgY29udGV4dCkgPT4ge1xuICBkZWJ1Zyh7IGV2ZW50IH0pO1xuICBsZXQgcmVzcG9uc2VTdGF0dXM6ICdTVUNDRVNTJyB8ICdGQUlMRUQnID0gJ1NVQ0NFU1MnO1xuICB0cnkge1xuICAgIGlmIChldmVudC5SZXF1ZXN0VHlwZSA9PT0gJ0NyZWF0ZScgfHwgZXZlbnQuUmVxdWVzdFR5cGUgPT09ICdVcGRhdGUnKSB7XG4gICAgICBjb25zdCBwcm9wcyA9IGdldFByb3BlcnRpZXMoZXZlbnQpO1xuICAgICAgbGV0IHRtcERpciA9ICcnO1xuICAgICAgY29uc3QgeyBhc3NldHNUbXBEaXIsIHNvdXJjZURpclBhdGgsIHNvdXJjZVppcEZpbGVQYXRoIH0gPSBpbml0RGlyZWN0b3JpZXMoKTtcbiAgICAgIHRtcERpciA9IGFzc2V0c1RtcERpcjtcbiAgICAgIGRlYnVnKCdEb3dubG9hZGluZyB6aXAnKTtcbiAgICAgIGF3YWl0IGRvd25sb2FkRmlsZSh7XG4gICAgICAgIGJ1Y2tldDogcHJvcHMuc291cmNlQnVja2V0TmFtZSxcbiAgICAgICAga2V5OiBwcm9wcy5zb3VyY2VLZXlQcmVmaXgsXG4gICAgICAgIGxvY2FsRGVzdGluYXRpb25QYXRoOiBzb3VyY2VaaXBGaWxlUGF0aCxcbiAgICAgIH0pO1xuICAgICAgZGVidWcoJ0V4dHJhY3RpbmcgemlwJyk7XG4gICAgICBhd2FpdCBleHRyYWN0WmlwKHsgc291cmNlWmlwRmlsZVBhdGgsIGRlc3RpbmF0aW9uRGlyUGF0aDogc291cmNlRGlyUGF0aCB9KTtcbiAgICAgIGNvbnN0IGZpbGVQYXRocyA9IGxpc3RGaWxlUGF0aHMoc291cmNlRGlyUGF0aCk7XG4gICAgICBpZiAocHJvcHMuc3Vic3RpdHV0aW9uQ29uZmlnICYmIE9iamVjdC5rZXlzKHByb3BzLnN1YnN0aXR1dGlvbkNvbmZpZykubGVuZ3RoKSB7XG4gICAgICAgIGRlYnVnKCdSZXBsYWNpbmcgZW52aXJvbm1lbnQgdmFyaWFibGVzOiAnICsgSlNPTi5zdHJpbmdpZnkocHJvcHMuc3Vic3RpdHV0aW9uQ29uZmlnKSk7XG4gICAgICAgIHN1YnN0aXR1dGUoeyBjb25maWc6IHByb3BzLnN1YnN0aXR1dGlvbkNvbmZpZywgZmlsZVBhdGhzIH0pO1xuICAgICAgfVxuICAgICAgLy8gbXVzdCBmaW5kIG9sZCBvYmplY3Qga2V5cyBiZWZvcmUgdXBsb2FkaW5nIG5ldyBvYmplY3RzIHNvIHdlIGtub3cgd2hpY2ggb2JqZWN0cyB0byBwcnVuZVxuICAgICAgY29uc3Qgb2xkT2JqZWN0S2V5cyA9IGF3YWl0IGxpc3RPbGRPYmplY3RLZXlzKHtcbiAgICAgICAgYnVja2V0TmFtZTogcHJvcHMuZGVzdGluYXRpb25CdWNrZXROYW1lLFxuICAgICAgICBrZXlQcmVmaXg6IHByb3BzLmRlc3RpbmF0aW9uS2V5UHJlZml4LFxuICAgICAgfSk7XG4gICAgICBpZiAoIXByb3BzLnppcCkge1xuICAgICAgICBkZWJ1ZygnVXBsb2FkaW5nIG9iamVjdHMgdG86ICcgKyBwcm9wcy5kZXN0aW5hdGlvbkJ1Y2tldE5hbWUpO1xuICAgICAgICBhd2FpdCB1cGxvYWRPYmplY3RzKHtcbiAgICAgICAgICBidWNrZXQ6IHByb3BzLmRlc3RpbmF0aW9uQnVja2V0TmFtZSxcbiAgICAgICAgICBrZXlQcmVmaXg6IHByb3BzLmRlc3RpbmF0aW9uS2V5UHJlZml4LFxuICAgICAgICAgIGZpbGVQYXRocyxcbiAgICAgICAgICBiYXNlTG9jYWxEaXI6IHNvdXJjZURpclBhdGgsXG4gICAgICAgICAgcHV0Q29uZmlnOiBwcm9wcy5wdXRDb25maWcsXG4gICAgICAgICAgcXVldWVTaXplOiBwcm9wcy5xdWV1ZVNpemUsXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAocHJvcHMucHJ1bmUpIHtcbiAgICAgICAgICBkZWJ1ZygnRW1wdHlpbmcvcHJ1bmluZyBidWNrZXQ6ICcgKyBwcm9wcy5kZXN0aW5hdGlvbkJ1Y2tldE5hbWUpO1xuICAgICAgICAgIGF3YWl0IHBydW5lQnVja2V0KHtcbiAgICAgICAgICAgIGJ1Y2tldE5hbWU6IHByb3BzLmRlc3RpbmF0aW9uQnVja2V0TmFtZSxcbiAgICAgICAgICAgIGZpbGVQYXRocyxcbiAgICAgICAgICAgIGJhc2VMb2NhbERpcjogc291cmNlRGlyUGF0aCxcbiAgICAgICAgICAgIGtleVByZWZpeDogcHJvcHMuZGVzdGluYXRpb25LZXlQcmVmaXgsXG4gICAgICAgICAgICBvbGRPYmplY3RLZXlzLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkZWJ1ZygnVXBsb2FkaW5nIHppcCB0bzogJyArIHByb3BzLmRlc3RpbmF0aW9uQnVja2V0TmFtZSk7XG4gICAgICAgIGNvbnN0IHppcEJ1ZmZlciA9IGF3YWl0IHppcE9iamVjdHMoeyB0bXBEaXI6IHNvdXJjZURpclBhdGggfSk7XG4gICAgICAgIGF3YWl0IHVwbG9hZFppcCh7XG4gICAgICAgICAgemlwQnVmZmVyLFxuICAgICAgICAgIGJ1Y2tldDogcHJvcHMuZGVzdGluYXRpb25CdWNrZXROYW1lLFxuICAgICAgICAgIGtleVByZWZpeDogcHJvcHMuZGVzdGluYXRpb25LZXlQcmVmaXgsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgaWYgKHRtcERpci5sZW5ndGgpIHtcbiAgICAgICAgZGVidWcoJ1JlbW92aW5nIHRlbXAgZGlyZWN0b3J5Jyk7XG4gICAgICAgIHJtU3luYyh0bXBEaXIsIHsgZm9yY2U6IHRydWUsIHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICAgIH1cbiAgICAgIHJlc3BvbnNlU3RhdHVzID0gJ1NVQ0NFU1MnO1xuICAgIH1cbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgY29uc29sZS5lcnJvcihlcnIpO1xuICAgIHJlc3BvbnNlU3RhdHVzID0gJ0ZBSUxFRCc7XG4gIH1cbiAgYXdhaXQgY2ZuUmVzcG9uc2UoeyBldmVudCwgY29udGV4dCwgcmVzcG9uc2VTdGF0dXMgfSk7XG59O1xuXG5mdW5jdGlvbiBkZWJ1Zyh2YWx1ZTogdW5rbm93bikge1xuICBpZiAocHJvY2Vzcy5lbnYuREVCVUcpIGNvbnNvbGUubG9nKEpTT04uc3RyaW5naWZ5KHZhbHVlLCBudWxsLCAyKSk7XG59XG5cbmZ1bmN0aW9uIGdldFByb3BlcnRpZXMoZXZlbnQ6IFBhcmFtZXRlcnM8Q2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUhhbmRsZXI+WzBdKSB7XG4gIGNvbnN0IHByb3BzID0gZXZlbnQuUmVzb3VyY2VQcm9wZXJ0aWVzO1xuICByZXR1cm4ge1xuICAgIC4uLnByb3BzLFxuICAgIHBydW5lOiBwcm9wcy5wcnVuZSA9PT0gJ3RydWUnLFxuICAgIHppcDogcHJvcHMuemlwID09PSAndHJ1ZScsXG4gIH0gYXMgQ3VzdG9tUmVzb3VyY2VQcm9wZXJ0aWVzICYgeyBTZXJ2aWNlVG9rZW46IHN0cmluZyB9O1xufVxuXG5mdW5jdGlvbiBpbml0RGlyZWN0b3JpZXMoKSB7XG4gIGNvbnN0IGFzc2V0c1RtcERpciA9IG1rZHRlbXBTeW5jKHJlc29sdmVQYXRoKHRtcGRpcigpLCAnYXNzZXRzLScpKTtcbiAgY29uc3Qgc291cmNlWmlwRGlyUGF0aCA9IHJlc29sdmVQYXRoKGFzc2V0c1RtcERpciwgJ3NvdXJjZS16aXAnKTtcbiAgbWtkaXJTeW5jKHNvdXJjZVppcERpclBhdGgpO1xuICBjb25zdCBzb3VyY2VaaXBGaWxlUGF0aCA9IHJlc29sdmVQYXRoKHNvdXJjZVppcERpclBhdGgsICd0ZW1wLnppcCcpO1xuICAvLyB0cmFpbGluZyBzbGFzaCBleHBlY3RlZCBieSBhZG0temlwJ3MgYGV4dHJhY3RBbGxUb2AgbWV0aG9kXG4gIGNvbnN0IHNvdXJjZURpclBhdGggPSByZXNvbHZlUGF0aChhc3NldHNUbXBEaXIsICdzb3VyY2UnKSArICcvJztcbiAgbWtkaXJTeW5jKHNvdXJjZURpclBhdGgpO1xuICByZXR1cm4geyBhc3NldHNUbXBEaXIsIHNvdXJjZVppcEZpbGVQYXRoLCBzb3VyY2VEaXJQYXRoIH07XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGRvd25sb2FkRmlsZSh7XG4gIGJ1Y2tldCxcbiAga2V5LFxuICBsb2NhbERlc3RpbmF0aW9uUGF0aCxcbn06IHtcbiAgYnVja2V0OiBzdHJpbmc7XG4gIGtleT86IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgbG9jYWxEZXN0aW5hdGlvblBhdGg6IHN0cmluZztcbn0pIHtcbiAgY29uc3QgZGF0YSA9IGF3YWl0IHMzLnNlbmQobmV3IEdldE9iamVjdENvbW1hbmQoeyBCdWNrZXQ6IGJ1Y2tldCwgS2V5OiBrZXkgfSkpO1xuICByZXR1cm4gbmV3IFByb21pc2UoYXN5bmMgKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIGNvbnN0IGJvZHkgPSBkYXRhLkJvZHk7XG4gICAgaWYgKGJvZHkgaW5zdGFuY2VvZiBSZWFkYWJsZSkge1xuICAgICAgY29uc3Qgd3JpdGVTdHJlYW0gPSBjcmVhdGVXcml0ZVN0cmVhbShsb2NhbERlc3RpbmF0aW9uUGF0aCk7XG4gICAgICBib2R5XG4gICAgICAgIC5waXBlKHdyaXRlU3RyZWFtKVxuICAgICAgICAub24oJ2Vycm9yJywgKGVycikgPT4gcmVqZWN0KGVycikpXG4gICAgICAgIC5vbignY2xvc2UnLCAoKSA9PiByZXNvbHZlKG51bGwpKTtcbiAgICB9XG4gIH0pO1xufVxuXG5hc3luYyBmdW5jdGlvbiBleHRyYWN0WmlwKHtcbiAgc291cmNlWmlwRmlsZVBhdGgsXG4gIGRlc3RpbmF0aW9uRGlyUGF0aCxcbn06IHtcbiAgc291cmNlWmlwRmlsZVBhdGg6IHN0cmluZztcbiAgZGVzdGluYXRpb25EaXJQYXRoOiBzdHJpbmc7XG59KSB7XG4gIGNvbnN0IHppcEJ1ZmZlciA9IHJlYWRGaWxlU3luYyhzb3VyY2VaaXBGaWxlUGF0aCk7XG4gIGNvbnN0IGFyY2hpdmUgPSBhd2FpdCBKU1ppcC5sb2FkQXN5bmMoemlwQnVmZmVyKTtcbiAgZm9yIChjb25zdCBbemlwUmVsYXRpdmVQYXRoLCB6aXBPYmplY3RdIG9mIE9iamVjdC5lbnRyaWVzKGFyY2hpdmUuZmlsZXMpKSB7XG4gICAgaWYgKCF6aXBPYmplY3QuZGlyKSB7XG4gICAgICBjb25zdCBhYnNQYXRoID0gcmVzb2x2ZVBhdGgoZGVzdGluYXRpb25EaXJQYXRoLCB6aXBSZWxhdGl2ZVBhdGgpO1xuICAgICAgY29uc3QgcGF0aERpcm5hbWUgPSBkaXJuYW1lKGFic1BhdGgpO1xuICAgICAgaWYgKCFleGlzdHNTeW5jKHBhdGhEaXJuYW1lKSkge1xuICAgICAgICBta2RpclN5bmMocGF0aERpcm5hbWUsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuICAgICAgfVxuICAgICAgY29uc3QgZmlsZUNvbnRlbnRzID0gYXdhaXQgemlwT2JqZWN0LmFzeW5jKCdub2RlYnVmZmVyJyk7XG4gICAgICBsZXQgaXNTeW1MaW5rID0gZmFsc2U7XG4gICAgICBjb25zdCB1bml4UGVybWlzc2lvbnMgPSB6aXBPYmplY3Q/LnVuaXhQZXJtaXNzaW9ucztcbiAgICAgIGlmICh0eXBlb2YgdW5peFBlcm1pc3Npb25zID09PSAnbnVtYmVyJykge1xuICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vdHdvbGZzb24vZ3J1bnQtemlwL3B1bGwvNTIvZmlsZXNcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWJpdHdpc2VcbiAgICAgICAgaXNTeW1MaW5rID0gKHVuaXhQZXJtaXNzaW9ucyAmIDB4ZjAwMCkgPT09IDB4YTAwMDtcbiAgICAgIH1cbiAgICAgIGlmIChpc1N5bUxpbmspIHtcbiAgICAgICAgc3ltbGlua1N5bmMoZmlsZUNvbnRlbnRzLCBhYnNQYXRoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHdyaXRlRmlsZVN5bmMoYWJzUGF0aCwgZmlsZUNvbnRlbnRzKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBHaXZlbiBwYXRoIG9mIGRpcmVjdG9yeSwgcmV0dXJucyBhcnJheSBvZiBhbGwgZmlsZSBwYXRocyB3aXRoaW4gZGlyZWN0b3J5XG4gKi9cbmZ1bmN0aW9uIGxpc3RGaWxlUGF0aHMoZGlyUGF0aDogc3RyaW5nKTogc3RyaW5nW10ge1xuICBjb25zdCBmaWxlUGF0aHM6IHN0cmluZ1tdID0gW107XG4gIGNvbnN0IGRpcmVjdG9yeSA9IHJlYWRkaXJTeW5jKGRpclBhdGgsIHsgd2l0aEZpbGVUeXBlczogdHJ1ZSB9KTtcbiAgZm9yIChjb25zdCBkIG9mIGRpcmVjdG9yeSkge1xuICAgIGNvbnN0IGZpbGVQYXRoID0gcmVzb2x2ZVBhdGgoZGlyUGF0aCwgZC5uYW1lKTtcbiAgICBpZiAoZC5pc0RpcmVjdG9yeSgpKSB7XG4gICAgICBmaWxlUGF0aHMucHVzaCguLi5saXN0RmlsZVBhdGhzKGZpbGVQYXRoKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGZpbGVQYXRocy5wdXNoKGZpbGVQYXRoKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGZpbGVQYXRocztcbn1cblxuZnVuY3Rpb24gc3Vic3RpdHV0ZSh7IGZpbGVQYXRocywgY29uZmlnIH06IHsgZmlsZVBhdGhzOiBzdHJpbmdbXTsgY29uZmlnOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IH0pIHtcbiAgY29uc3QgZmluZFJlZ0V4cCA9IG5ldyBSZWdFeHAoT2JqZWN0LmtleXMoY29uZmlnKS5qb2luKCd8JyksICdnJyk7XG4gIGZvciAoY29uc3QgZmlsZVBhdGggb2YgZmlsZVBhdGhzKSB7XG4gICAgaWYgKGZpbGVQYXRoLmluY2x1ZGVzKCdub2RlX21vZHVsZXMnKSkgY29udGludWU7XG4gICAgY29uc3QgZmlsZUNvbnRlbnRzID0gcmVhZEZpbGVTeW5jKGZpbGVQYXRoLCB7IGVuY29kaW5nOiAndXRmOCcgfSk7XG4gICAgY29uc3QgbmV3RmlsZUNvbnRlbnRzID0gZmlsZUNvbnRlbnRzLnJlcGxhY2UoZmluZFJlZ0V4cCwgKG1hdGNoZWQpID0+IHtcbiAgICAgIGNvbnN0IG1hdGNoZWRFbnZWYXIgPSBjb25maWdbbWF0Y2hlZF07XG4gICAgICBpZiAobWF0Y2hlZEVudlZhcikge1xuICAgICAgICByZXR1cm4gbWF0Y2hlZEVudlZhcjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUud2FybihgQ291bGQgbm90IGZpbmQgbWF0Y2hlZCB2YWx1ZTogJHttYXRjaGVkfSBpbiBlbnZpcm9ubWVudCBvYmplY3QuIFN1YnN0aXR1dGluZyAnJ2ApO1xuICAgICAgICByZXR1cm4gJyc7XG4gICAgICB9XG4gICAgfSk7XG4gICAgaWYgKGZpbGVDb250ZW50cyAhPT0gbmV3RmlsZUNvbnRlbnRzKSB7XG4gICAgICB3cml0ZUZpbGVTeW5jKGZpbGVQYXRoLCBuZXdGaWxlQ29udGVudHMpO1xuICAgIH1cbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBsaXN0T2xkT2JqZWN0S2V5cyh7XG4gIGJ1Y2tldE5hbWUsXG4gIGtleVByZWZpeCxcbn06IHtcbiAgYnVja2V0TmFtZTogc3RyaW5nO1xuICBrZXlQcmVmaXg/OiBzdHJpbmc7XG59KTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICBjb25zdCBvbGRPYmplY3RLZXlzOiBzdHJpbmdbXSA9IFtdO1xuICBsZXQgbmV4dFRva2VuOiBzdHJpbmcgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gIGRvIHtcbiAgICBjb25zdCBjbWQ6IExpc3RPYmplY3RzVjJDb21tYW5kSW5wdXQgPSB7IEJ1Y2tldDogYnVja2V0TmFtZSwgUHJlZml4OiBrZXlQcmVmaXggfTtcbiAgICBpZiAobmV4dFRva2VuKSB7XG4gICAgICBjbWQuQ29udGludWF0aW9uVG9rZW4gPSBuZXh0VG9rZW47XG4gICAgfVxuICAgIGNvbnN0IHJlcyA9IGF3YWl0IHMzLnNlbmQobmV3IExpc3RPYmplY3RzVjJDb21tYW5kKGNtZCkpO1xuICAgIGNvbnN0IGNvbnRlbnRzID0gcmVzLkNvbnRlbnRzO1xuICAgIG5leHRUb2tlbiA9IHJlcy5OZXh0Q29udGludWF0aW9uVG9rZW47XG4gICAgaWYgKGNvbnRlbnRzPy5sZW5ndGgpIHtcbiAgICAgIGZvciAoY29uc3QgeyBLZXk6IGtleSB9IG9mIGNvbnRlbnRzKSB7XG4gICAgICAgIGlmIChrZXkpIHtcbiAgICAgICAgICBvbGRPYmplY3RLZXlzLnB1c2goa2V5KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfSB3aGlsZSAobmV4dFRva2VuKTtcbiAgcmV0dXJuIG9sZE9iamVjdEtleXM7XG59XG5cbi8qKlxuICogQ3JlYXRlIFMzIEtleSBnaXZlbiBsb2NhbCBwYXRoXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZVMzS2V5KHsga2V5UHJlZml4LCBwYXRoLCBiYXNlTG9jYWxEaXIgfTogeyBrZXlQcmVmaXg/OiBzdHJpbmc7IHBhdGg6IHN0cmluZzsgYmFzZUxvY2FsRGlyOiBzdHJpbmcgfSkge1xuICBjb25zdCBvYmplY3RLZXlQYXJ0czogc3RyaW5nW10gPSBbXTtcbiAgaWYgKGtleVByZWZpeCkgb2JqZWN0S2V5UGFydHMucHVzaChrZXlQcmVmaXgpO1xuICBvYmplY3RLZXlQYXJ0cy5wdXNoKHJlbGF0aXZlKGJhc2VMb2NhbERpciwgcGF0aCkpO1xuICByZXR1cm4gam9pbiguLi5vYmplY3RLZXlQYXJ0cyk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uKiBjaHVua0FycmF5KGFycmF5OiBzdHJpbmdbXSwgY2h1bmtTaXplOiBudW1iZXIpIHtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkgKz0gY2h1bmtTaXplKSB7XG4gICAgeWllbGQgYXJyYXkuc2xpY2UoaSwgaSArIGNodW5rU2l6ZSk7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gdXBsb2FkT2JqZWN0cyh7XG4gIGJ1Y2tldCxcbiAga2V5UHJlZml4LFxuICBmaWxlUGF0aHMsXG4gIGJhc2VMb2NhbERpcixcbiAgcHV0Q29uZmlnID0ge30sXG4gIHF1ZXVlU2l6ZSxcbn06IHtcbiAgYnVja2V0OiBDdXN0b21SZXNvdXJjZVByb3BlcnRpZXNbJ2Rlc3RpbmF0aW9uQnVja2V0TmFtZSddO1xuICBrZXlQcmVmaXg/OiBDdXN0b21SZXNvdXJjZVByb3BlcnRpZXNbJ2Rlc3RpbmF0aW9uS2V5UHJlZml4J107XG4gIGZpbGVQYXRoczogc3RyaW5nW107XG4gIGJhc2VMb2NhbERpcjogc3RyaW5nO1xuICBwdXRDb25maWc6IEN1c3RvbVJlc291cmNlUHJvcGVydGllc1sncHV0Q29uZmlnJ107XG4gIHF1ZXVlU2l6ZTogQ3VzdG9tUmVzb3VyY2VQcm9wZXJ0aWVzWydxdWV1ZVNpemUnXTtcbn0pIHtcbiAgZm9yIGF3YWl0IChjb25zdCBmaWxlUGF0aENodW5rIG9mIGNodW5rQXJyYXkoZmlsZVBhdGhzLCAxMDApKSB7XG4gICAgY29uc3QgcHV0T2JqZWN0SW5wdXRzOiBQdXRPYmplY3RDb21tYW5kSW5wdXRbXSA9IGZpbGVQYXRoQ2h1bmsubWFwKChwYXRoKSA9PiB7XG4gICAgICBjb25zdCBjb250ZW50VHlwZSA9IG1pbWUubG9va3VwKHBhdGgpIHx8IHVuZGVmaW5lZDtcbiAgICAgIGNvbnN0IHB1dE9iamVjdE9wdGlvbnMgPSBnZXRQdXRPYmplY3RPcHRpb25zKHsgcGF0aCwgcHV0Q29uZmlnIH0pO1xuICAgICAgY29uc3Qga2V5ID0gY3JlYXRlUzNLZXkoeyBrZXlQcmVmaXgsIHBhdGgsIGJhc2VMb2NhbERpciB9KTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIENvbnRlbnRUeXBlOiBjb250ZW50VHlwZSxcbiAgICAgICAgLi4ucHV0T2JqZWN0T3B0aW9ucyxcbiAgICAgICAgQnVja2V0OiBidWNrZXQsXG4gICAgICAgIEtleToga2V5LFxuICAgICAgICBCb2R5OiBjcmVhdGVSZWFkU3RyZWFtKHBhdGgpLFxuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8vIENhbGwgcHV0IG9iamVjdHMgc2VyaWFsbHksIHByZXZlbnRzIFhBbXpDb250ZW50U0hBMjU2TWlzbWF0Y2ggZXJyb3JzXG4gICAgLy8gVGhpcyBzZWVtcyB0byBiZSBhIGJ1ZyB3aXRoaW4gdGhlIGxpYiBzdG9yYWdlIHBhY2thZ2UsIEkgaGF2ZSBvcGVuZWQgYW4gaXNzdWUgaGVyZTogaHR0cHM6Ly9naXRodWIuY29tL2F3cy9hd3Mtc2RrLWpzLXYzL2lzc3Vlcy82OTQwXG4gICAgYXdhaXQgcHV0T2JqZWN0SW5wdXRzLnJlZHVjZShhc3luYyAoYWNjLCBwYXJhbXMpID0+IHtcbiAgICAgIGF3YWl0IGFjYztcbiAgICAgIGNvbnN0IG9wdHM6IE9wdGlvbnMgPSB7XG4gICAgICAgIGNsaWVudDogczMsXG4gICAgICAgIHBhcmFtcyxcbiAgICAgIH07XG4gICAgICBpZiAocXVldWVTaXplKSB7XG4gICAgICAgIG9wdHMucXVldWVTaXplID0gcXVldWVTaXplO1xuICAgICAgfVxuICAgICAgY29uc3QgdXBsb2FkID0gbmV3IFVwbG9hZChvcHRzKTtcbiAgICAgIGNvbnNvbGUubG9nKCd1cGxvYWRpbmcnLCBwYXJhbXMpO1xuICAgICAgcmV0dXJuIHVwbG9hZC5kb25lKCk7XG4gICAgfSwgUHJvbWlzZS5yZXNvbHZlPGFueT4obnVsbCkpO1xuICB9XG59XG5cbi8qKlxuICogWmlwcyBvYmplY3RzIHRha2luZyBpbnRvIGFjY291bnQgc3ltbGlua3NcbiAqIEBzZWUgaHR0cHM6Ly9naXRodWIuY29tL1N0dWsvanN6aXAvaXNzdWVzLzM4NiNpc3N1ZWNvbW1lbnQtNjM0NzczMzQzXG4gKi9cbmZ1bmN0aW9uIHppcE9iamVjdHMoeyB0bXBEaXIgfTogeyB0bXBEaXI6IHN0cmluZyB9KTogUHJvbWlzZTxCdWZmZXI+IHtcbiAgY29uc3QgemlwID0gbmV3IEpTWmlwKCk7XG4gIGNvbnN0IGZpbGVQYXRocyA9IGxpc3RGaWxlUGF0aHModG1wRGlyKTtcbiAgZm9yIChjb25zdCBmaWxlUGF0aCBvZiBmaWxlUGF0aHMpIHtcbiAgICBjb25zdCByZWxhdGl2ZVBhdGggPSByZWxhdGl2ZSh0bXBEaXIsIGZpbGVQYXRoKTtcbiAgICBjb25zdCBzdGF0ID0gbHN0YXRTeW5jKGZpbGVQYXRoKTtcbiAgICBpZiAoc3RhdC5pc1N5bWJvbGljTGluaygpKSB7XG4gICAgICB6aXAuZmlsZShyZWxhdGl2ZVBhdGgsIHJlYWRsaW5rU3luYyhmaWxlUGF0aCksIHtcbiAgICAgICAgZGlyOiBzdGF0LmlzRGlyZWN0b3J5KCksXG4gICAgICAgIHVuaXhQZXJtaXNzaW9uczogcGFyc2VJbnQoJzEyMDc1NScsIDgpLFxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHppcC5maWxlKHJlbGF0aXZlUGF0aCwgcmVhZEZpbGVTeW5jKGZpbGVQYXRoKSwgeyBkaXI6IHN0YXQuaXNEaXJlY3RvcnkoKSwgdW5peFBlcm1pc3Npb25zOiBzdGF0Lm1vZGUgfSk7XG4gICAgfVxuICB9XG4gIHJldHVybiB6aXAuZ2VuZXJhdGVBc3luYyh7XG4gICAgdHlwZTogJ25vZGVidWZmZXInLFxuICAgIHBsYXRmb3JtOiAnVU5JWCcsXG4gICAgY29tcHJlc3Npb246ICdTVE9SRScsXG4gIH0pO1xufVxuXG5hc3luYyBmdW5jdGlvbiB1cGxvYWRaaXAoe1xuICBidWNrZXQsXG4gIGtleVByZWZpeCxcbiAgemlwQnVmZmVyLFxufToge1xuICBidWNrZXQ6IEN1c3RvbVJlc291cmNlUHJvcGVydGllc1snZGVzdGluYXRpb25CdWNrZXROYW1lJ107XG4gIGtleVByZWZpeD86IEN1c3RvbVJlc291cmNlUHJvcGVydGllc1snZGVzdGluYXRpb25LZXlQcmVmaXgnXTtcbiAgemlwQnVmZmVyOiBCdWZmZXI7XG59KSB7XG4gIHJldHVybiBzMy5zZW5kKFxuICAgIG5ldyBQdXRPYmplY3RDb21tYW5kKHtcbiAgICAgIEJ1Y2tldDogYnVja2V0LFxuICAgICAgS2V5OiBrZXlQcmVmaXgsXG4gICAgICBCb2R5OiB6aXBCdWZmZXIsXG4gICAgICBDb250ZW50VHlwZTogJ2FwcGxpY2F0aW9uL3ppcCcsXG4gICAgfSlcbiAgKTtcbn1cblxuZnVuY3Rpb24gZ2V0UHV0T2JqZWN0T3B0aW9ucyh7XG4gIHBhdGgsXG4gIHB1dENvbmZpZyA9IHt9LFxufToge1xuICBwYXRoOiBzdHJpbmc7XG4gIHB1dENvbmZpZzogTmV4dGpzQnVja2V0RGVwbG95bWVudFByb3BzWydwdXRDb25maWcnXTtcbn0pOiBQYXJ0aWFsPFB1dE9iamVjdENvbW1hbmRJbnB1dD4ge1xuICBsZXQgcHV0T2JqZWN0T3B0aW9uczogUGFydGlhbDxQdXRPYmplY3RDb21tYW5kSW5wdXQ+ID0ge307XG4gIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKHB1dENvbmZpZykpIHtcbiAgICBpZiAobWljcm9tYXRjaC5pc01hdGNoKHBhdGgsIGtleSkpIHtcbiAgICAgIHB1dE9iamVjdE9wdGlvbnMgPSB7IC4uLnB1dE9iamVjdE9wdGlvbnMsIC4uLnZhbHVlIH07XG4gICAgfVxuICB9XG4gIHJldHVybiBwdXRPYmplY3RPcHRpb25zO1xufVxuXG5hc3luYyBmdW5jdGlvbiBwcnVuZUJ1Y2tldCh7XG4gIGJ1Y2tldE5hbWUsXG4gIGZpbGVQYXRocyxcbiAgYmFzZUxvY2FsRGlyLFxuICBrZXlQcmVmaXgsXG4gIG9sZE9iamVjdEtleXMsXG59OiB7XG4gIGJ1Y2tldE5hbWU6IHN0cmluZztcbiAgZmlsZVBhdGhzOiBzdHJpbmdbXTtcbiAgYmFzZUxvY2FsRGlyOiBzdHJpbmc7XG4gIGtleVByZWZpeD86IHN0cmluZztcbiAgb2xkT2JqZWN0S2V5czogc3RyaW5nW107XG59KSB7XG4gIGNvbnN0IG5ld09iamVjdEtleXMgPSBmaWxlUGF0aHMubWFwKChwYXRoKSA9PiBjcmVhdGVTM0tleSh7IGtleVByZWZpeCwgcGF0aCwgYmFzZUxvY2FsRGlyIH0pKTtcbiAgLy8gZmluZCBvbGQgb2JqZWN0cyB0aGF0IGFyZSBub3QgY3VycmVudGx5IGluIG5ldyBvYmplY3RzIHRvIHBydW5lLlxuICBjb25zdCBvbGRPYmplY3RLZXlzVG9CZURlbGV0ZWQ6IHN0cmluZ1tdID0gW107XG4gIGZvciAoY29uc3Qga2V5IG9mIG9sZE9iamVjdEtleXMpIHtcbiAgICBpZiAoIW5ld09iamVjdEtleXMuaW5jbHVkZXMoa2V5KSkge1xuICAgICAgb2xkT2JqZWN0S2V5c1RvQmVEZWxldGVkLnB1c2goa2V5KTtcbiAgICB9XG4gIH1cbiAgaWYgKG9sZE9iamVjdEtleXNUb0JlRGVsZXRlZC5sZW5ndGgpIHtcbiAgICBjb25zdCBkZWxldGVQcm9taXNlcyA9IFtdO1xuXG4gICAgLy8gQVdTIGxpbWl0cyBTMyBkZWxldGUgY29tbWFuZHMgdG8gMTAwMCBrZXlzIHBlciBjYWxsXG4gICAgY29uc3QgZGVsZXRlQ29tbWFuZExpbWl0ID0gMTAwMDtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb2xkT2JqZWN0S2V5c1RvQmVEZWxldGVkLmxlbmd0aDsgaSArPSBkZWxldGVDb21tYW5kTGltaXQpIHtcbiAgICAgIGNvbnN0IG9iamVjdENodW5rID0gb2xkT2JqZWN0S2V5c1RvQmVEZWxldGVkLnNsaWNlKGksIGkgKyBkZWxldGVDb21tYW5kTGltaXQpO1xuXG4gICAgICBkZWxldGVQcm9taXNlcy5wdXNoKFxuICAgICAgICBzMy5zZW5kKFxuICAgICAgICAgIG5ldyBEZWxldGVPYmplY3RzQ29tbWFuZCh7XG4gICAgICAgICAgICBCdWNrZXQ6IGJ1Y2tldE5hbWUsXG4gICAgICAgICAgICBEZWxldGU6IHsgT2JqZWN0czogb2JqZWN0Q2h1bmsubWFwKChrKSA9PiAoeyBLZXk6IGsgfSkpIH0sXG4gICAgICAgICAgfSlcbiAgICAgICAgKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBhd2FpdCBQcm9taXNlLmFsbChkZWxldGVQcm9taXNlcyk7XG5cbiAgICBkZWJ1ZyhgT2JqZWN0cyBwcnVuZWQgaW4gJHtidWNrZXROYW1lfTogJHtvbGRPYmplY3RLZXlzVG9CZURlbGV0ZWQuam9pbignLCAnKX1gKTtcbiAgfSBlbHNlIHtcbiAgICBkZWJ1ZyhgTm8gb2JqZWN0cyB0byBwcnVuZWApO1xuICB9XG59XG5cbmludGVyZmFjZSBDZm5SZXNwb25zZVByb3BzIHtcbiAgZXZlbnQ6IFBhcmFtZXRlcnM8Q2xvdWRGb3JtYXRpb25DdXN0b21SZXNvdXJjZUhhbmRsZXI+WzBdO1xuICBjb250ZXh0OiBQYXJhbWV0ZXJzPENsb3VkRm9ybWF0aW9uQ3VzdG9tUmVzb3VyY2VIYW5kbGVyPlsxXTtcbiAgcmVzcG9uc2VTdGF0dXM6ICdTVUNDRVNTJyB8ICdGQUlMRUQnO1xuICByZXNwb25zZURhdGE/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICBwaHlzaWNhbFJlc291cmNlSWQ/OiBzdHJpbmc7XG59XG4vKipcbiAqIEluc3BpcmVkIGJ5OiBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9jZm4tbGFtYmRhLWZ1bmN0aW9uLWNvZGUtY2ZucmVzcG9uc2Vtb2R1bGUuaHRtbFxuICovXG5mdW5jdGlvbiBjZm5SZXNwb25zZShwcm9wczogQ2ZuUmVzcG9uc2VQcm9wcykge1xuICBjb25zdCBib2R5ID0gSlNPTi5zdHJpbmdpZnkoe1xuICAgIFN0YXR1czogcHJvcHMucmVzcG9uc2VTdGF0dXMsXG4gICAgUmVhc29uOiAnU2VlIHRoZSBkZXRhaWxzIGluIENsb3VkV2F0Y2ggTG9nIFN0cmVhbTogJyArIHByb3BzLmNvbnRleHQubG9nU3RyZWFtTmFtZSxcbiAgICBQaHlzaWNhbFJlc291cmNlSWQ6IHByb3BzLnBoeXNpY2FsUmVzb3VyY2VJZCB8fCBwcm9wcy5jb250ZXh0LmxvZ1N0cmVhbU5hbWUsXG4gICAgU3RhY2tJZDogcHJvcHMuZXZlbnQuU3RhY2tJZCxcbiAgICBSZXF1ZXN0SWQ6IHByb3BzLmV2ZW50LlJlcXVlc3RJZCxcbiAgICBMb2dpY2FsUmVzb3VyY2VJZDogcHJvcHMuZXZlbnQuTG9naWNhbFJlc291cmNlSWQsXG4gICAgRGF0YTogcHJvcHMucmVzcG9uc2VEYXRhLFxuICB9KTtcbiAgcmV0dXJuIGZldGNoKHByb3BzLmV2ZW50LlJlc3BvbnNlVVJMLCB7XG4gICAgbWV0aG9kOiAnUFVUJyxcbiAgICBib2R5LFxuICAgIGhlYWRlcnM6IHsgJ2NvbnRlbnQtdHlwZSc6ICcnLCAnY29udGVudC1sZW5ndGgnOiBib2R5Lmxlbmd0aC50b1N0cmluZygpIH0sXG4gIH0pO1xufVxuIl19