UNPKG

antfarm

Version:

File automation framework for ants.

272 lines (270 loc) 34.1 kB
"use strict"; var __extends = (this && this.__extends) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; var nest_1 = require("./nest"); var s3FileJob_1 = require("../job/s3FileJob"); var AWS = require("aws-sdk"), _ = require("lodash"), async = require("async"), fs = require("fs"); var S3Nest = (function (_super) { __extends(S3Nest, _super); /** * Constructor * @param e * @param bucket AWS S3 bucket to watch. * @param keyPrefix Optional key prefix (sub-directory) to watch. * @param checkEvery Frequency of bucket checking, in minutes. * @param allowCreation Create the bucket:prefix if it does not exist. */ function S3Nest(e, bucket, keyPrefix, checkEvery, allowCreation) { if (checkEvery === void 0) { checkEvery = 5; } if (allowCreation === void 0) { allowCreation = false; } _super.call(this, e, "An S3 bucket"); var sn = this; sn.s3 = new AWS.S3(); sn.bucket = bucket; sn.keyPrefix = keyPrefix; sn.checkEvery = checkEvery; sn.checkEveryMs = checkEvery * 60000; sn.allowCreation = allowCreation; sn.verifyBucket(); } /** * Set hard-coded AWS credentials. * @param accessKeyId * @param secretAccessKey */ S3Nest.prototype.setCredentials = function (accessKeyId, secretAccessKey) { AWS.config.update({ accessKeyId: accessKeyId, secretAccessKey: secretAccessKey }); }; /** * Verify bucket and handle creation of bucket if need be. */ S3Nest.prototype.verifyBucket = function () { var sn = this; sn.headBucket(function (headSuccess) { if (!headSuccess) { if (sn.allowCreation) { sn.createBucket(function (createSuccess) { if (!createSuccess) { sn.e.log(3, "Bucket \"" + sn.bucket + "\" could not be created.", sn); } }); } else { sn.e.log(3, "Bucket \"" + sn.bucket + "\" does not exist and allowCreation is set to false.", sn); } } }); }; /** * Verify that the bucket is available and exists * @param callback */ S3Nest.prototype.headBucket = function (callback) { var sn = this; var params = { Bucket: sn.bucket }; sn.s3.headBucket(params, function (err, data) { if (err) { sn.e.log(2, "headBucket error: " + err, sn); callback(false); } else { // if (_.isEmpty(data)) { // sn.e.log(2, `headBucket empty response`, sn); // callback(true); // } else { // sn.e.log(0, `headBucket success: ${data}`, sn); // console.log(data); // callback(true); // } sn.e.log(0, "Bucket \"" + sn.bucket + "\" is available.", sn); callback(true); } }); }; S3Nest.prototype.createBucket = function (callback) { var sn = this; var params = { Bucket: sn.bucket, }; sn.s3.createBucket(params, function (err, data) { if (err) { sn.e.log(3, "createBucket error: " + err, sn); callback(false); } else { if (_.isEmpty(data)) { sn.e.log(2, "createBucket empty response", sn); callback(false); } else { sn.e.log(0, "createBucket success: " + data, sn); callback(true); } } }); }; S3Nest.prototype.load = function () { var sn = this; var params = { Bucket: sn.bucket, // ContinuationToken: 'STRING_VALUE', // Delimiter: 'STRING_VALUE', // EncodingType: 'url', // FetchOwner: true || false, // MaxKeys: 0, Prefix: sn.keyPrefix }; sn.s3.listObjectsV2(params, function (err, data) { if (err) { sn.e.log(3, "listObjectsV2: " + err, sn); } else { var contents_1 = data.Contents; // Download each file found if (contents_1.length > 0) { sn.e.log(0, "Found " + contents_1.length + " objects in \"" + sn.bucket + "/" + sn.keyPrefix + "\".", sn); async.eachSeries(contents_1, function (object, done) { // Create temp file sn.e.log(1, "S3 found file \"" + object.Key + "\".", sn); var job = new s3FileJob_1.S3FileJob(sn.e, object.Key); // Download and pipe to file var params = { Bucket: sn.bucket, Key: object.Key }; var file = require("fs").createWriteStream(job.path); sn.s3.getObject(params).createReadStream().pipe(file); sn.e.log(1, "Downloading \"" + object.Key + "\".", sn); file.on("close", function () { // Delete object sn.deleteObject(object.Key); sn.arrive(job); done(); }); }, function (err) { if (err) { sn.e.log(3, "Async series download error: \"" + err + "\".", sn); } sn.e.log(0, "Completed " + contents_1.length + " synchronous download(s).", sn); }); } } }); }; /** * Removes an object from an S3 bucket. * @param key */ S3Nest.prototype.deleteObject = function (key) { var sn = this; var params = { Bucket: sn.bucket, Key: key /* required */ }; sn.s3.deleteObject(params, function (err) { if (err) { sn.e.log(3, "S3 delete object error " + err, sn); } }); }; /** * Watch an S3 bucket. */ S3Nest.prototype.watch = function () { var sn = this; if (sn.checkEvery === 0) { sn.e.log(3, "Cannot watch this bucket. Check every (minutes) set to 0.", sn); } else { sn.e.log(1, "Watching S3 bucket.", sn); var count_1 = 0; setInterval(function () { count_1++; sn.e.log(1, "Re-checking S3 bucket, attempt " + count_1 + ".", sn); sn.load(); }, sn.checkEveryMs, count_1); } }; /** * Nest arrival * @param job */ S3Nest.prototype.arrive = function (job) { _super.prototype.arrive.call(this, job); }; /** * Upload a file to an S3 bucket. */ S3Nest.prototype.take = function (job, callback) { var sn = this; try { sn.uploadFile(job, function (s3Job) { callback(s3Job); }); } catch (e) { sn.e.log(3, "Take upload error, " + e, sn); } }; /** * Calculate the percent remaining from the httpUploadProgress event values. * @param total * @param loaded * @param part * @returns {number} */ S3Nest.prototype.calculateRemaining = function (total, loaded, part) { var sn = this; if (!isNaN(total) && !isNaN(loaded)) { var percentRemaining = Math.round((loaded / total) * 100); if (isNaN(percentRemaining) || percentRemaining > 100) { sn.e.log(3, "Error calculating percent remaining: " + percentRemaining + " (" + typeof percentRemaining + "), total: " + total + ", loaded: " + loaded + ".", sn); return 0; } else { return percentRemaining; } } else { return 0; } }; /** * Upload file to S3 * @param job {FileJob} FileJob to be uploaded. * @param callback Callback includes the S3FileJob parameter. */ S3Nest.prototype.uploadFile = function (job, callback) { var sn = this; var body = fs.createReadStream(job.path); var params = { Bucket: sn.bucket, Key: sn.keyPrefix + job.name, Body: body, ACL: "public-read" }; var percentUploaded = 0; sn.s3.upload(params). on("httpUploadProgress", function (evt) { // console.log("evt", evt); percentUploaded = sn.calculateRemaining(evt.total, evt.loaded, evt.part); sn.e.log(0, "Uploading \"" + evt.key + "\" - " + percentUploaded + "%", sn); }). send(function (err, data) { if (err) { sn.e.log(3, "S3 upload error: " + err, sn); } // Change job type to a S3FileJob var s3Job = job; s3Job.locallyAvailable = false; s3Job.path = data.Location; s3Job.bucket = data.Bucket; s3Job.key = data.Key; s3Job.eTag = data.ETag; callback(s3Job); }); }; return S3Nest; }(nest_1.Nest)); exports.S3Nest = S3Nest; //# sourceMappingURL=data:application/json;charset=utf8;base64,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LEVBQUUsR0FBRyxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDekUsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLGlCQUFjLEdBQUcsQ0FBQyxHQUFHLGFBQU8sZUFBZSxNQUFHLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDcEUsQ0FBQyxDQUFDO1lBQ0YsSUFBSSxDQUFDLFVBQVMsR0FBRyxFQUFFLElBQUk7WUFDbkIsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztnQkFDTixFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsc0JBQW9CLEdBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztZQUMvQyxDQUFDO1lBRUQsaUNBQWlDO1lBQ2pDLElBQUksS0FBSyxHQUFHLEdBQWdCLENBQUM7WUFDN0IsS0FBSyxDQUFDLGdCQUFnQixHQUFHLEtBQUssQ0FBQztZQUMvQixLQUFLLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUM7WUFDM0IsS0FBSyxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO1lBQzNCLEtBQUssQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQztZQUNyQixLQUFLLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7WUFFdkIsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3BCLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQztJQUVMLGFBQUM7QUFBRCxDQWpUQSxBQWlUQyxDQWpUMkIsV0FBSSxHQWlUL0I7QUFqVFksY0FBTSxTQWlUbEIsQ0FBQSIsImZpbGUiOiJsaWIvbmVzdC9zM05lc3QuanMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBOZXN0IH0gZnJvbSBcIi4vbmVzdFwiO1xuaW1wb3J0IHsgRmlsZUpvYiB9IGZyb20gXCIuLy4uL2pvYi9maWxlSm9iXCI7XG5pbXBvcnQgeyBFbnZpcm9ubWVudCB9IGZyb20gXCIuLi9lbnZpcm9ubWVudC9lbnZpcm9ubWVudFwiO1xuaW1wb3J0IHtTM0ZpbGVKb2J9IGZyb20gXCIuLi9qb2IvczNGaWxlSm9iXCI7XG5cbmNvbnN0ICAgQVdTID0gcmVxdWlyZShcImF3cy1zZGtcIiksXG4gICAgICAgIF8gPSByZXF1aXJlKFwibG9kYXNoXCIpLFxuICAgICAgICBhc3luYyA9IHJlcXVpcmUoXCJhc3luY1wiKSxcbiAgICAgICAgZnMgPSByZXF1aXJlKFwiZnNcIik7XG5cbmV4cG9ydCBjbGFzcyBTM05lc3QgZXh0ZW5kcyBOZXN0IHtcblxuICAgIHByb3RlY3RlZCBjbGllbnQ6IGFueTtcbiAgICBwcm90ZWN0ZWQgczM6IGFueTtcbiAgICBwcm90ZWN0ZWQgYnVja2V0OiBzdHJpbmc7XG4gICAgcHJvdGVjdGVkIGtleVByZWZpeDogc3RyaW5nO1xuICAgIHByb3RlY3RlZCBjaGVja0V2ZXJ5OiBudW1iZXI7XG4gICAgcHJvdGVjdGVkIGNoZWNrRXZlcnlNczogbnVtYmVyO1xuICAgIHByb3RlY3RlZCBhbGxvd0NyZWF0aW9uOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0b3JcbiAgICAgKiBAcGFyYW0gZVxuICAgICAqIEBwYXJhbSBidWNrZXQgICAgICAgICAgICBBV1MgUzMgYnVja2V0IHRvIHdhdGNoLlxuICAgICAqIEBwYXJhbSBrZXlQcmVmaXggICAgICAgICBPcHRpb25hbCBrZXkgcHJlZml4IChzdWItZGlyZWN0b3J5KSB0byB3YXRjaC5cbiAgICAgKiBAcGFyYW0gY2hlY2tFdmVyeSAgICAgICAgRnJlcXVlbmN5IG9mIGJ1Y2tldCBjaGVja2luZywgaW4gbWludXRlcy5cbiAgICAgKiBAcGFyYW0gYWxsb3dDcmVhdGlvbiAgICAgQ3JlYXRlIHRoZSBidWNrZXQ6cHJlZml4IGlmIGl0IGRvZXMgbm90IGV4aXN0LlxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBlOiBFbnZpcm9ubWVudCwgYnVja2V0OiBzdHJpbmcsIGtleVByZWZpeD86IHN0cmluZywgY2hlY2tFdmVyeTogbnVtYmVyID0gNSwgYWxsb3dDcmVhdGlvbjogYm9vbGVhbiA9IGZhbHNlXG4gICAgKSB7XG4gICAgICAgIHN1cGVyKGUsIFwiQW4gUzMgYnVja2V0XCIpO1xuICAgICAgICBsZXQgc24gPSB0aGlzO1xuICAgICAgICBzbi5zMyA9IG5ldyBBV1MuUzMoKTtcblxuICAgICAgICBzbi5idWNrZXQgPSBidWNrZXQ7XG4gICAgICAgIHNuLmtleVByZWZpeCA9IGtleVByZWZpeDtcbiAgICAgICAgc24uY2hlY2tFdmVyeSA9IGNoZWNrRXZlcnk7XG4gICAgICAgIHNuLmNoZWNrRXZlcnlNcyA9IGNoZWNrRXZlcnkgKiA2MDAwMDtcbiAgICAgICAgc24uYWxsb3dDcmVhdGlvbiA9IGFsbG93Q3JlYXRpb247XG5cbiAgICAgICAgc24udmVyaWZ5QnVja2V0KCk7XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBTZXQgaGFyZC1jb2RlZCBBV1MgY3JlZGVudGlhbHMuXG4gICAgICogQHBhcmFtIGFjY2Vzc0tleUlkXG4gICAgICogQHBhcmFtIHNlY3JldEFjY2Vzc0tleVxuICAgICAqL1xuICAgIHB1YmxpYyBzZXRDcmVkZW50aWFscyhhY2Nlc3NLZXlJZDogc3RyaW5nLCBzZWNyZXRBY2Nlc3NLZXk6IHN0cmluZykge1xuICAgICAgICBBV1MuY29uZmlnLnVwZGF0ZSh7YWNjZXNzS2V5SWQ6IGFjY2Vzc0tleUlkLCBzZWNyZXRBY2Nlc3NLZXk6IHNlY3JldEFjY2Vzc0tleX0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFZlcmlmeSBidWNrZXQgYW5kIGhhbmRsZSBjcmVhdGlvbiBvZiBidWNrZXQgaWYgbmVlZCBiZS5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgdmVyaWZ5QnVja2V0KCkge1xuICAgICAgICBsZXQgc24gPSB0aGlzO1xuICAgICAgICBzbi5oZWFkQnVja2V0KGhlYWRTdWNjZXNzID0+IHtcbiAgICAgICAgICAgIGlmICghaGVhZFN1Y2Nlc3MpIHtcbiAgICAgICAgICAgICAgICBpZiAoc24uYWxsb3dDcmVhdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBzbi5jcmVhdGVCdWNrZXQoY3JlYXRlU3VjY2VzcyA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNyZWF0ZVN1Y2Nlc3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbi5lLmxvZygzLCBgQnVja2V0IFwiJHtzbi5idWNrZXR9XCIgY291bGQgbm90IGJlIGNyZWF0ZWQuYCwgc24pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzbi5lLmxvZygzLCBgQnVja2V0IFwiJHtzbi5idWNrZXR9XCIgZG9lcyBub3QgZXhpc3QgYW5kIGFsbG93Q3JlYXRpb24gaXMgc2V0IHRvIGZhbHNlLmAsIHNuKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFZlcmlmeSB0aGF0IHRoZSBidWNrZXQgaXMgYXZhaWxhYmxlIGFuZCBleGlzdHNcbiAgICAgKiBAcGFyYW0gY2FsbGJhY2tcbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgaGVhZEJ1Y2tldChjYWxsYmFjaykge1xuICAgICAgICBsZXQgc24gPSB0aGlzO1xuXG4gICAgICAgIGxldCBwYXJhbXMgPSB7IEJ1Y2tldDogc24uYnVja2V0IH07XG5cbiAgICAgICAgc24uczMuaGVhZEJ1Y2tldChwYXJhbXMsIChlcnIsIGRhdGEpID0+IHtcbiAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICBzbi5lLmxvZygyLCBgaGVhZEJ1Y2tldCBlcnJvcjogJHtlcnJ9YCwgc24pO1xuICAgICAgICAgICAgICAgIGNhbGxiYWNrKGZhbHNlKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gaWYgKF8uaXNFbXB0eShkYXRhKSkge1xuICAgICAgICAgICAgICAgIC8vICAgICBzbi5lLmxvZygyLCBgaGVhZEJ1Y2tldCBlbXB0eSByZXNwb25zZWAsIHNuKTtcbiAgICAgICAgICAgICAgICAvLyAgICAgY2FsbGJhY2sodHJ1ZSk7XG4gICAgICAgICAgICAgICAgLy8gfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyAgICAgc24uZS5sb2coMCwgYGhlYWRCdWNrZXQgc3VjY2VzczogJHtkYXRhfWAsIHNuKTtcbiAgICAgICAgICAgICAgICAvLyAgICAgY29uc29sZS5sb2coZGF0YSk7XG4gICAgICAgICAgICAgICAgLy8gICAgIGNhbGxiYWNrKHRydWUpO1xuICAgICAgICAgICAgICAgIC8vIH1cbiAgICAgICAgICAgICAgICBzbi5lLmxvZygwLCBgQnVja2V0IFwiJHtzbi5idWNrZXR9XCIgaXMgYXZhaWxhYmxlLmAsIHNuKTtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayh0cnVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGNyZWF0ZUJ1Y2tldChjYWxsYmFjaykge1xuICAgICAgICBsZXQgc24gPSB0aGlzO1xuXG4gICAgICAgIGxldCBwYXJhbXMgPSB7XG4gICAgICAgICAgICBCdWNrZXQ6IHNuLmJ1Y2tldCwgLyogcmVxdWlyZWQgKi9cbiAgICAgICAgICAgIC8vIEFDTDogJ3ByaXZhdGUgfCBwdWJsaWMtcmVhZCB8IHB1YmxpYy1yZWFkLXdyaXRlIHwgYXV0aGVudGljYXRlZC1yZWFkJyxcbiAgICAgICAgICAgIC8vIENyZWF0ZUJ1Y2tldENvbmZpZ3VyYXRpb246IHtcbiAgICAgICAgICAgIC8vICAgICBMb2NhdGlvbkNvbnN0cmFpbnQ6ICdFVSB8IGV1LXdlc3QtMSB8IHVzLXdlc3QtMSB8IHVzLXdlc3QtMiB8IGFwLXNvdXRoLTEgfCBhcC1zb3V0aGVhc3QtMSB8IGFwLXNvdXRoZWFzdC0yIHwgYXAtbm9ydGhlYXN0LTEgfCBzYS1lYXN0LTEgfCBjbi1ub3J0aC0xIHwgZXUtY2VudHJhbC0xJ1xuICAgICAgICAgICAgLy8gfSxcbiAgICAgICAgICAgIC8vIEdyYW50RnVsbENvbnRyb2w6ICdTVFJJTkdfVkFMVUUnLFxuICAgICAgICAgICAgLy8gR3JhbnRSZWFkOiAnU1RSSU5HX1ZBTFVFJyxcbiAgICAgICAgICAgIC8vIEdyYW50UmVhZEFDUDogJ1NUUklOR19WQUxVRScsXG4gICAgICAgICAgICAvLyBHcmFudFdyaXRlOiAnU1RSSU5HX1ZBTFVFJyxcbiAgICAgICAgICAgIC8vIEdyYW50V3JpdGVBQ1A6ICdTVFJJTkdfVkFMVUUnXG4gICAgICAgIH07XG4gICAgICAgIHNuLnMzLmNyZWF0ZUJ1Y2tldChwYXJhbXMsIGZ1bmN0aW9uKGVyciwgZGF0YSkge1xuICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgIHNuLmUubG9nKDMsIGBjcmVhdGVCdWNrZXQgZXJyb3I6ICR7ZXJyfWAsIHNuKTtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhmYWxzZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChfLmlzRW1wdHkoZGF0YSkpIHtcbiAgICAgICAgICAgICAgICAgICAgc24uZS5sb2coMiwgYGNyZWF0ZUJ1Y2tldCBlbXB0eSByZXNwb25zZWAsIHNuKTtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2soZmFsc2UpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHNuLmUubG9nKDAsIGBjcmVhdGVCdWNrZXQgc3VjY2VzczogJHtkYXRhfWAsIHNuKTtcbiAgICAgICAgICAgICAgICAgICAgY2FsbGJhY2sodHJ1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgIH1cblxuICAgIHB1YmxpYyBsb2FkKCkge1xuICAgICAgICBsZXQgc24gPSB0aGlzO1xuXG4gICAgICAgIGxldCBwYXJhbXMgPSB7XG4gICAgICAgICAgICBCdWNrZXQ6IHNuLmJ1Y2tldCwgLyogcmVxdWlyZWQgKi9cbiAgICAgICAgICAgIC8vIENvbnRpbnVhdGlvblRva2VuOiAnU1RSSU5HX1ZBTFVFJyxcbiAgICAgICAgICAgIC8vIERlbGltaXRlcjogJ1NUUklOR19WQUxVRScsXG4gICAgICAgICAgICAvLyBFbmNvZGluZ1R5cGU6ICd1cmwnLFxuICAgICAgICAgICAgLy8gRmV0Y2hPd25lcjogdHJ1ZSB8fCBmYWxzZSxcbiAgICAgICAgICAgIC8vIE1heEtleXM6IDAsXG4gICAgICAgICAgICBQcmVmaXg6IHNuLmtleVByZWZpeFxuICAgICAgICB9O1xuXG4gICAgICAgIHNuLnMzLmxpc3RPYmplY3RzVjIocGFyYW1zLCAoZXJyLCBkYXRhKSA9PiB7XG4gICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgc24uZS5sb2coMywgYGxpc3RPYmplY3RzVjI6ICR7ZXJyfWAsIHNuKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbGV0IGNvbnRlbnRzID0gZGF0YS5Db250ZW50cztcblxuICAgICAgICAgICAgICAgIC8vIERvd25sb2FkIGVhY2ggZmlsZSBmb3VuZFxuICAgICAgICAgICAgICAgIGlmIChjb250ZW50cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHNuLmUubG9nKDAsIGBGb3VuZCAke2NvbnRlbnRzLmxlbmd0aH0gb2JqZWN0cyBpbiBcIiR7c24uYnVja2V0fS8ke3NuLmtleVByZWZpeH1cIi5gLCBzbik7XG5cbiAgICAgICAgICAgICAgICAgICAgYXN5bmMuZWFjaFNlcmllcyhjb250ZW50cywgKG9iamVjdCwgZG9uZSkgPT4ge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBDcmVhdGUgdGVtcCBmaWxlXG4gICAgICAgICAgICAgICAgICAgICAgICBzbi5lLmxvZygxLCBgUzMgZm91bmQgZmlsZSBcIiR7b2JqZWN0LktleX1cIi5gLCBzbik7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgam9iID0gbmV3IFMzRmlsZUpvYihzbi5lLCBvYmplY3QuS2V5KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRG93bmxvYWQgYW5kIHBpcGUgdG8gZmlsZVxuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHBhcmFtcyA9IHtCdWNrZXQ6IHNuLmJ1Y2tldCwgS2V5OiBvYmplY3QuS2V5fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCBmaWxlID0gcmVxdWlyZShcImZzXCIpLmNyZWF0ZVdyaXRlU3RyZWFtKGpvYi5wYXRoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNuLnMzLmdldE9iamVjdChwYXJhbXMpLmNyZWF0ZVJlYWRTdHJlYW0oKS5waXBlKGZpbGUpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBzbi5lLmxvZygxLCBgRG93bmxvYWRpbmcgXCIke29iamVjdC5LZXl9XCIuYCwgc24pO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmaWxlLm9uKFwiY2xvc2VcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIERlbGV0ZSBvYmplY3RcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbi5kZWxldGVPYmplY3Qob2JqZWN0LktleSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzbi5hcnJpdmUoam9iKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkb25lKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuXG4gICAgICAgICAgICAgICAgICAgIH0sIGVyciA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZXJyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc24uZS5sb2coMywgYEFzeW5jIHNlcmllcyBkb3dubG9hZCBlcnJvcjogXCIke2Vycn1cIi5gLCBzbik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBzbi5lLmxvZygwLCBgQ29tcGxldGVkICR7Y29udGVudHMubGVuZ3RofSBzeW5jaHJvbm91cyBkb3dubG9hZChzKS5gLCBzbik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhbiBvYmplY3QgZnJvbSBhbiBTMyBidWNrZXQuXG4gICAgICogQHBhcmFtIGtleVxuICAgICAqL1xuICAgIHByb3RlY3RlZCBkZWxldGVPYmplY3Qoa2V5KSB7XG4gICAgICAgIGxldCBzbiA9IHRoaXM7XG4gICAgICAgIGxldCBwYXJhbXMgPSB7XG4gICAgICAgICAgICBCdWNrZXQ6IHNuLmJ1Y2tldCwgLyogcmVxdWlyZWQgKi9cbiAgICAgICAgICAgIEtleToga2V5IC8qIHJlcXVpcmVkICovXG4gICAgICAgIH07XG4gICAgICAgIHNuLnMzLmRlbGV0ZU9iamVjdChwYXJhbXMsIGZ1bmN0aW9uKGVycikge1xuICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgIHNuLmUubG9nKDMsIGBTMyBkZWxldGUgb2JqZWN0IGVycm9yICR7ZXJyfWAsIHNuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXYXRjaCBhbiBTMyBidWNrZXQuXG4gICAgICovXG4gICAgcHVibGljIHdhdGNoKCkge1xuICAgICAgICBsZXQgc24gPSB0aGlzO1xuXG4gICAgICAgIGlmIChzbi5jaGVja0V2ZXJ5ID09PSAwKSB7XG4gICAgICAgICAgICBzbi5lLmxvZygzLCBcIkNhbm5vdCB3YXRjaCB0aGlzIGJ1Y2tldC4gQ2hlY2sgZXZlcnkgKG1pbnV0ZXMpIHNldCB0byAwLlwiLCBzbik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzbi5lLmxvZygxLCBcIldhdGNoaW5nIFMzIGJ1Y2tldC5cIiwgc24pO1xuXG4gICAgICAgICAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgICAgICAgICBzZXRJbnRlcnZhbChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBjb3VudCsrO1xuICAgICAgICAgICAgICAgIHNuLmUubG9nKDEsIGBSZS1jaGVja2luZyBTMyBidWNrZXQsIGF0dGVtcHQgJHtjb3VudH0uYCwgc24pO1xuICAgICAgICAgICAgICAgIHNuLmxvYWQoKTtcbiAgICAgICAgICAgIH0sIHNuLmNoZWNrRXZlcnlNcywgY291bnQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTmVzdCBhcnJpdmFsXG4gICAgICogQHBhcmFtIGpvYlxuICAgICAqL1xuICAgIHB1YmxpYyBhcnJpdmUoam9iOiBGaWxlSm9iKSB7XG4gICAgICAgIHN1cGVyLmFycml2ZShqb2IpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVwbG9hZCBhIGZpbGUgdG8gYW4gUzMgYnVja2V0LlxuICAgICAqL1xuICAgIHB1YmxpYyB0YWtlKGpvYjogRmlsZUpvYiwgY2FsbGJhY2s/OiBhbnkpIHtcbiAgICAgICAgbGV0IHNuID0gdGhpcztcblxuICAgICAgICB0cnkge1xuXG4gICAgICAgICAgICBzbi51cGxvYWRGaWxlKGpvYiwgKHMzSm9iOiBTM0ZpbGVKb2IpID0+IHtcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhzM0pvYik7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBzbi5lLmxvZygzLCBcIlRha2UgdXBsb2FkIGVycm9yLCBcIiArIGUsIHNuKTtcbiAgICAgICAgfVxuXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2FsY3VsYXRlIHRoZSBwZXJjZW50IHJlbWFpbmluZyBmcm9tIHRoZSBodHRwVXBsb2FkUHJvZ3Jlc3MgZXZlbnQgdmFsdWVzLlxuICAgICAqIEBwYXJhbSB0b3RhbFxuICAgICAqIEBwYXJhbSBsb2FkZWRcbiAgICAgKiBAcGFyYW0gcGFydFxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICovXG4gICAgcHJpdmF0ZSBjYWxjdWxhdGVSZW1haW5pbmcodG90YWw6IG51bWJlciwgbG9hZGVkOiBudW1iZXIsIHBhcnQ/OiBudW1iZXIpIHtcbiAgICAgICAgbGV0IHNuID0gdGhpcztcbiAgICAgICAgaWYgKCFpc05hTih0b3RhbCkgJiYgIWlzTmFOKGxvYWRlZCkpIHtcbiAgICAgICAgICAgIGxldCBwZXJjZW50UmVtYWluaW5nID0gTWF0aC5yb3VuZCgoIGxvYWRlZCAvIHRvdGFsKSAqIDEwMCk7XG4gICAgICAgICAgICBpZiAoaXNOYU4ocGVyY2VudFJlbWFpbmluZykgfHwgcGVyY2VudFJlbWFpbmluZyA+IDEwMCkge1xuICAgICAgICAgICAgICAgIHNuLmUubG9nKDMsIGBFcnJvciBjYWxjdWxhdGluZyBwZXJjZW50IHJlbWFpbmluZzogJHtwZXJjZW50UmVtYWluaW5nfSAoJHt0eXBlb2YgcGVyY2VudFJlbWFpbmluZ30pLCB0b3RhbDogJHt0b3RhbH0sIGxvYWRlZDogJHtsb2FkZWR9LmAsIHNuKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBlcmNlbnRSZW1haW5pbmc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVwbG9hZCBmaWxlIHRvIFMzXG4gICAgICogQHBhcmFtIGpvYiB7RmlsZUpvYn0gICAgIEZpbGVKb2IgdG8gYmUgdXBsb2FkZWQuXG4gICAgICogQHBhcmFtIGNhbGxiYWNrICAgICAgICAgIENhbGxiYWNrIGluY2x1ZGVzIHRoZSBTM0ZpbGVKb2IgcGFyYW1ldGVyLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCB1cGxvYWRGaWxlKGpvYjogRmlsZUpvYiwgY2FsbGJhY2s6IGFueSkge1xuICAgICAgICBsZXQgc24gPSB0aGlzO1xuICAgICAgICBsZXQgYm9keSA9IGZzLmNyZWF0ZVJlYWRTdHJlYW0oam9iLnBhdGgpO1xuICAgICAgICBsZXQgcGFyYW1zID0ge1xuICAgICAgICAgICAgQnVja2V0OiBzbi5idWNrZXQsXG4gICAgICAgICAgICBLZXk6IHNuLmtleVByZWZpeCArIGpvYi5uYW1lLFxuICAgICAgICAgICAgQm9keTogYm9keSxcbiAgICAgICAgICAgIEFDTDogXCJwdWJsaWMtcmVhZFwiXG4gICAgICAgIH07XG4gICAgICAgIGxldCBwZXJjZW50VXBsb2FkZWQgPSAwO1xuICAgICAgICBzbi5zMy51cGxvYWQocGFyYW1zKS5cbiAgICAgICAgb24oXCJodHRwVXBsb2FkUHJvZ3Jlc3NcIiwgZnVuY3Rpb24oZXZ0KSB7XG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcImV2dFwiLCBldnQpO1xuICAgICAgICAgICAgcGVyY2VudFVwbG9hZGVkID0gc24uY2FsY3VsYXRlUmVtYWluaW5nKGV2dC50b3RhbCwgZXZ0LmxvYWRlZCwgZXZ0LnBhcnQpO1xuICAgICAgICAgICAgc24uZS5sb2coMCwgYFVwbG9hZGluZyBcIiR7ZXZ0LmtleX1cIiAtICR7cGVyY2VudFVwbG9hZGVkfSVgLCBzbik7XG4gICAgICAgIH0pLlxuICAgICAgICBzZW5kKGZ1bmN0aW9uKGVyciwgZGF0YSkge1xuICAgICAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgICAgICAgIHNuLmUubG9nKDMsIGBTMyB1cGxvYWQgZXJyb3I6ICR7ZXJyfWAsIHNuKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ2hhbmdlIGpvYiB0eXBlIHRvIGEgUzNGaWxlSm9iXG4gICAgICAgICAgICBsZXQgczNKb2IgPSBqb2IgYXMgUzNGaWxlSm9iO1xuICAgICAgICAgICAgczNKb2IubG9jYWxseUF2YWlsYWJsZSA9IGZhbHNlO1xuICAgICAgICAgICAgczNKb2IucGF0aCA9IGRhdGEuTG9jYXRpb247XG4gICAgICAgICAgICBzM0pvYi5idWNrZXQgPSBkYXRhLkJ1Y2tldDtcbiAgICAgICAgICAgIHMzSm9iLmtleSA9IGRhdGEuS2V5O1xuICAgICAgICAgICAgczNKb2IuZVRhZyA9IGRhdGEuRVRhZztcblxuICAgICAgICAgICAgY2FsbGJhY2soczNKb2IpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbn0iXX0=