UNPKG

@atomictech/xlsx-write-stream

Version:

Stream huge amount of data into an XLSX generated file stream with minimum memory footprint.

170 lines (141 loc) 20.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _defaultsDeep = _interopRequireDefault(require("lodash/defaultsDeep")); var _isObject = _interopRequireDefault(require("lodash/isObject")); var _archiver = _interopRequireDefault(require("archiver")); var _stream = require("stream"); var templates = _interopRequireWildcard(require("./templates")); var _XLSXRowTransform = _interopRequireDefault(require("./XLSXRowTransform")); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * XLSX Write Stream base class */ class XLSXWriteStream extends _stream.Transform { /** * Create new stream transform that handles Array or Object as input chunks. * Be aware that first row chunk is determinant in the transform configuration process for further row chunks. * @class XLSXWriteStream * @extends Transform * @param {Object} [options] * @param {Boolean} [options.header=false] - Display the column names on the first line if the columns option is provided or discovered. * @param {Array|Object} [options.columns] - List of properties when records are provided as objects. * Work with records in the form of arrays based on index position; order matters. * Auto discovered in the first record when the user write objects, can refer to nested properties of the input JSON, see the `header` option on how to print columns names on the first line. * @param {Boolean} [options.format=true] - If set to false writer will not format cells with number, date, boolean and text. * @param {Object} [options.styleDefs] - If set you can overwrite default standard type styles by other standard ones or even define custom `formatCode`. * @param {Boolean} [options.immediateInitialization=false] - If set to true writer will initialize archive and start compressing xlsx common stuff immediately, adding subsequently a little memory and processor footprint. If not, initialization will be delayed to the first data processing. */ constructor(options) { super({ objectMode: true }); this.pipelineInitialized = false; this.initialized = false; this.arrayMode = null; this.options = (0, _defaultsDeep.default)({}, options, { header: false, format: true, immediateInitialization: false }); if (this.options.immediateInitialization) this._initializePipeline(); } _transform(chunk, encoding, callback) { if (!this.initialized) this._initialize(chunk); this.toXlsxRow.write(this.normalize(chunk), encoding, callback); } _initialize(chunk) { this._initializePipeline(); this._initializeHeader(chunk); if (chunk) { this.arrayMode = Array.isArray(chunk); this.normalize = chunk => this.columns.map(key => chunk[key]); } this.initialized = true; } /** * Initialize pipeline with xlsx archive common files */ _initializePipeline() { if (this.pipelineInitialized) return; this.zip = (0, _archiver.default)('zip', { forceUTC: true }); this.zip.catchEarlyExitAttached = true; // Common xlsx archive files (not editable) this.zip.append(templates.ContentTypes, { name: '[Content_Types].xml' }); this.zip.append(templates.Rels, { name: '_rels/.rels' }); this.zip.append(templates.Workbook, { name: 'xl/workbook.xml' }); this.zip.append(templates.WorkbookRels, { name: 'xl/_rels/workbook.xml.rels' }); // Style xlsx definitions (one time generation) const styles = new templates.Styles(this.options.styleDefs); this.zip.append(styles.render(), { name: 'xl/styles.xml' }); this.zip.on('data', data => this.push(data)).on('warning', err => this.emit('warning', err)).on('error', err => this.emit('error', err)); this.toXlsxRow = new _XLSXRowTransform.default({ format: this.options.format, styles }); this.sheetStream = new _stream.PassThrough(); this.sheetStream.write(templates.SheetHeader); this.toXlsxRow.pipe(this.sheetStream, { end: false }); this.zip.append(this.sheetStream, { name: 'xl/worksheets/sheet1.xml' }); this.pipelineInitialized = true; } _initializeHeader(chunk = []) { if (Array.isArray(chunk)) { this.columns = (this.options.columns ? this.options.columns : chunk).map((value, index) => index); if (Array.isArray(this.options.columns)) { this.header = [...this.options.columns]; } else if ((0, _isObject.default)(this.options.columns)) { this.header = [...Object.values(this.options.columns)]; } } else { if (Array.isArray(this.options.columns)) { this.header = [...this.options.columns]; this.columns = [...this.options.columns]; } else if ((0, _isObject.default)(this.options.columns)) { this.header = [...Object.values(this.options.columns)]; this.columns = [...Object.keys(this.options.columns)]; } else { // Init header and columns from chunk this.header = [...Object.keys(chunk)]; this.columns = [...Object.keys(chunk)]; } } if (this.options.header && this.header) { this.toXlsxRow.write(this.header); } } _final(callback) { if (!this.initialized) this._initialize(); this.toXlsxRow.end(); this.toXlsxRow.on('end', () => this._finalize().then(() => { callback(); })); } /** * Finalize the zip archive */ _finalize() { this.sheetStream.end(templates.SheetFooter); return this.zip.finalize(); } } exports.default = XLSXWriteStream; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9YTFNYV3JpdGVTdHJlYW0uanMiXSwibmFtZXMiOlsiWExTWFdyaXRlU3RyZWFtIiwiVHJhbnNmb3JtIiwiY29uc3RydWN0b3IiLCJvcHRpb25zIiwib2JqZWN0TW9kZSIsInBpcGVsaW5lSW5pdGlhbGl6ZWQiLCJpbml0aWFsaXplZCIsImFycmF5TW9kZSIsImhlYWRlciIsImZvcm1hdCIsImltbWVkaWF0ZUluaXRpYWxpemF0aW9uIiwiX2luaXRpYWxpemVQaXBlbGluZSIsIl90cmFuc2Zvcm0iLCJjaHVuayIsImVuY29kaW5nIiwiY2FsbGJhY2siLCJfaW5pdGlhbGl6ZSIsInRvWGxzeFJvdyIsIndyaXRlIiwibm9ybWFsaXplIiwiX2luaXRpYWxpemVIZWFkZXIiLCJBcnJheSIsImlzQXJyYXkiLCJjb2x1bW5zIiwibWFwIiwia2V5IiwiemlwIiwiZm9yY2VVVEMiLCJjYXRjaEVhcmx5RXhpdEF0dGFjaGVkIiwiYXBwZW5kIiwidGVtcGxhdGVzIiwiQ29udGVudFR5cGVzIiwibmFtZSIsIlJlbHMiLCJXb3JrYm9vayIsIldvcmtib29rUmVscyIsInN0eWxlcyIsIlN0eWxlcyIsInN0eWxlRGVmcyIsInJlbmRlciIsIm9uIiwiZGF0YSIsInB1c2giLCJlcnIiLCJlbWl0IiwiWExTWFJvd1RyYW5zZm9ybSIsInNoZWV0U3RyZWFtIiwiUGFzc1Rocm91Z2giLCJTaGVldEhlYWRlciIsInBpcGUiLCJlbmQiLCJ2YWx1ZSIsImluZGV4IiwiT2JqZWN0IiwidmFsdWVzIiwia2V5cyIsIl9maW5hbCIsIl9maW5hbGl6ZSIsInRoZW4iLCJTaGVldEZvb3RlciIsImZpbmFsaXplIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7Ozs7O0FBRUE7QUFDQTtBQUNBO0FBQ2UsTUFBTUEsZUFBTixTQUE4QkMsaUJBQTlCLENBQXdDO0FBQ3JEO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FB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QUFBQSxNQUFNLENBQUN6QyxRQUFELEVBQVc7QUFDZixRQUFJLENBQUMsS0FBS1QsV0FBVixFQUF1QixLQUFLVSxXQUFMO0FBQ3ZCLFNBQUtDLFNBQUwsQ0FBZWlDLEdBQWY7QUFDQSxTQUFLakMsU0FBTCxDQUFldUIsRUFBZixDQUFrQixLQUFsQixFQUF5QixNQUN2QixLQUFLaUIsU0FBTCxHQUFpQkMsSUFBakIsQ0FBc0IsTUFBTTtBQUMxQjNDLE1BQUFBLFFBQVE7QUFDVCxLQUZELENBREY7QUFLRDtBQUVEO0FBQ0Y7QUFDQTs7O0FBQ0UwQyxFQUFBQSxTQUFTLEdBQUc7QUFDVixTQUFLWCxXQUFMLENBQWlCSSxHQUFqQixDQUFxQnBCLFNBQVMsQ0FBQzZCLFdBQS9CO0FBQ0EsV0FBTyxLQUFLakMsR0FBTCxDQUFTa0MsUUFBVCxFQUFQO0FBQ0Q7O0FBNUhvRCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBkZWZhdWx0c0RlZXAgZnJvbSAnbG9kYXNoL2RlZmF1bHRzRGVlcCc7XG5pbXBvcnQgaXNPYmplY3QgZnJvbSAnbG9kYXNoL2lzT2JqZWN0JztcbmltcG9ydCBBcmNoaXZlciBmcm9tICdhcmNoaXZlcic7XG5pbXBvcnQgeyBUcmFuc2Zvcm0sIFBhc3NUaHJvdWdoIH0gZnJvbSAnc3RyZWFtJztcbmltcG9ydCAqIGFzIHRlbXBsYXRlcyBmcm9tICcuL3RlbXBsYXRlcyc7XG5pbXBvcnQgWExTWFJvd1RyYW5zZm9ybSBmcm9tICcuL1hMU1hSb3dUcmFuc2Zvcm0nO1xuXG4vKipcbiAqIFhMU1ggV3JpdGUgU3RyZWFtIGJhc2UgY2xhc3NcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgWExTWFdyaXRlU3RyZWFtIGV4dGVuZHMgVHJhbnNmb3JtIHtcbiAgLyoqXG4gICAqIENyZWF0ZSBuZXcgc3RyZWFtIHRyYW5zZm9ybSB0aGF0IGhhbmRsZXMgQXJyYXkgb3IgT2JqZWN0IGFzIGlucHV0IGNodW5rcy5cbiAgICogQmUgYXdhcmUgdGhhdCBmaXJzdCByb3cgY2h1bmsgaXMgZGV0ZXJtaW5hbnQgaW4gdGhlIHRyYW5zZm9ybSBjb25maWd1cmF0aW9uIHByb2Nlc3MgZm9yIGZ1cnRoZXIgcm93IGNodW5rcy5cbiAgICogQGNsYXNzIFhMU1hXcml0ZVN0cmVhbVxuICAgKiBAZXh0ZW5kcyBUcmFuc2Zvcm1cbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLmhlYWRlcj1mYWxzZV0gLSBEaXNwbGF5IHRoZSBjb2x1bW4gbmFtZXMgb24gdGhlIGZpcnN0IGxpbmUgaWYgdGhlIGNvbHVtbnMgb3B0aW9uIGlzIHByb3ZpZGVkIG9yIGRpc2NvdmVyZWQuXG4gICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBbb3B0aW9ucy5jb2x1bW5zXSAtIExpc3Qgb2YgcHJvcGVydGllcyB3aGVuIHJlY29yZHMgYXJlIHByb3ZpZGVkIGFzIG9iamVjdHMuXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFdvcmsgd2l0aCByZWNvcmRzIGluIHRoZSBmb3JtIG9mIGFycmF5cyBiYXNlZCBvbiBpbmRleCBwb3NpdGlvbjsgb3JkZXIgbWF0dGVycy5cbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXV0byBkaXNjb3ZlcmVkIGluIHRoZSBmaXJzdCByZWNvcmQgd2hlbiB0aGUgdXNlciB3cml0ZSBvYmplY3RzLCBjYW4gcmVmZXIgdG8gbmVzdGVkIHByb3BlcnRpZXMgb2YgdGhlIGlucHV0IEpTT04sIHNlZSB0aGUgYGhlYWRlcmAgb3B0aW9uIG9uIGhvdyB0byBwcmludCBjb2x1bW5zIG5hbWVzIG9uIHRoZSBmaXJzdCBsaW5lLlxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLmZvcm1hdD10cnVlXSAtIElmIHNldCB0byBmYWxzZSB3cml0ZXIgd2lsbCBub3QgZm9ybWF0IGNlbGxzIHdpdGggbnVtYmVyLCBkYXRlLCBib29sZWFuIGFuZCB0ZXh0LlxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnMuc3R5bGVEZWZzXSAtIElmIHNldCB5b3UgY2FuIG92ZXJ3cml0ZSBkZWZhdWx0IHN0YW5kYXJkIHR5cGUgc3R5bGVzIGJ5IG90aGVyIHN0YW5kYXJkIG9uZXMgb3IgZXZlbiBkZWZpbmUgY3VzdG9tIGBmb3JtYXRDb2RlYC5cbiAgICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5pbW1lZGlhdGVJbml0aWFsaXphdGlvbj1mYWxzZV0gLSBJZiBzZXQgdG8gdHJ1ZSB3cml0ZXIgd2lsbCBpbml0aWFsaXplIGFyY2hpdmUgYW5kIHN0YXJ0IGNvbXByZXNzaW5nIHhsc3ggY29tbW9uIHN0dWZmIGltbWVkaWF0ZWx5LCBhZGRpbmcgc3Vic2VxdWVudGx5IGEgbGl0dGxlIG1lbW9yeSBhbmQgcHJvY2Vzc29yIGZvb3RwcmludC4gSWYgbm90LCBpbml0aWFsaXphdGlvbiB3aWxsIGJlIGRlbGF5ZWQgdG8gdGhlIGZpcnN0IGRhdGEgcHJvY2Vzc2luZy5cbiAgICovXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHtcbiAgICBzdXBlcih7IG9iamVjdE1vZGU6IHRydWUgfSk7XG5cbiAgICB0aGlzLnBpcGVsaW5lSW5pdGlhbGl6ZWQgPSBmYWxzZTtcbiAgICB0aGlzLmluaXRpYWxpemVkID0gZmFsc2U7XG4gICAgdGhpcy5hcnJheU1vZGUgPSBudWxsO1xuXG4gICAgdGhpcy5vcHRpb25zID0gZGVmYXVsdHNEZWVwKHt9LCBvcHRpb25zLCB7IGhlYWRlcjogZmFsc2UsIGZvcm1hdDogdHJ1ZSwgaW1tZWRpYXRlSW5pdGlhbGl6YXRpb246IGZhbHNlIH0pO1xuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5pbW1lZGlhdGVJbml0aWFsaXphdGlvbikgdGhpcy5faW5pdGlhbGl6ZVBpcGVsaW5lKCk7XG4gIH1cblxuICBfdHJhbnNmb3JtKGNodW5rLCBlbmNvZGluZywgY2FsbGJhY2spIHtcbiAgICBpZiAoIXRoaXMuaW5pdGlhbGl6ZWQpIHRoaXMuX2luaXRpYWxpemUoY2h1bmspO1xuXG4gICAgdGhpcy50b1hsc3hSb3cud3JpdGUodGhpcy5ub3JtYWxpemUoY2h1bmspLCBlbmNvZGluZywgY2FsbGJhY2spO1xuICB9XG5cbiAgX2luaXRpYWxpemUoY2h1bmspIHtcbiAgICB0aGlzLl9pbml0aWFsaXplUGlwZWxpbmUoKTtcbiAgICB0aGlzLl9pbml0aWFsaXplSGVhZGVyKGNodW5rKTtcblxuICAgIGlmIChjaHVuaykge1xuICAgICAgdGhpcy5hcnJheU1vZGUgPSBBcnJheS5pc0FycmF5KGNodW5rKTtcbiAgICAgIHRoaXMubm9ybWFsaXplID0gY2h1bmsgPT4gdGhpcy5jb2x1bW5zLm1hcChrZXkgPT4gY2h1bmtba2V5XSk7XG4gICAgfVxuXG4gICAgdGhpcy5pbml0aWFsaXplZCA9IHRydWU7XG4gIH1cblxuICAvKipcbiAgICogSW5pdGlhbGl6ZSBwaXBlbGluZSB3aXRoIHhsc3ggYXJjaGl2ZSBjb21tb24gZmlsZXNcbiAgICovXG4gIF9pbml0aWFsaXplUGlwZWxpbmUoKSB7XG4gICAgaWYgKHRoaXMucGlwZWxpbmVJbml0aWFsaXplZCkgcmV0dXJuO1xuXG4gICAgdGhpcy56aXAgPSBBcmNoaXZlcignemlwJywgeyBmb3JjZVVUQzogdHJ1ZSB9KTtcbiAgICB0aGlzLnppcC5jYXRjaEVhcmx5RXhpdEF0dGFjaGVkID0gdHJ1ZTtcblxuICAgIC8vIENvbW1vbiB4bHN4IGFyY2hpdmUgZmlsZXMgKG5vdCBlZGl0YWJsZSlcbiAgICB0aGlzLnppcC5hcHBlbmQodGVtcGxhdGVzLkNvbnRlbnRUeXBlcywgeyBuYW1lOiAnW0NvbnRlbnRfVHlwZXNdLnhtbCcgfSk7XG4gICAgdGhpcy56aXAuYXBwZW5kKHRlbXBsYXRlcy5SZWxzLCB7IG5hbWU6ICdfcmVscy8ucmVscycgfSk7XG4gICAgdGhpcy56aXAuYXBwZW5kKHRlbXBsYXRlcy5Xb3JrYm9vaywgeyBuYW1lOiAneGwvd29ya2Jvb2sueG1sJyB9KTtcbiAgICB0aGlzLnppcC5hcHBlbmQodGVtcGxhdGVzLldvcmtib29rUmVscywgeyBuYW1lOiAneGwvX3JlbHMvd29ya2Jvb2sueG1sLnJlbHMnIH0pO1xuXG4gICAgLy8gU3R5bGUgeGxzeCBkZWZpbml0aW9ucyAob25lIHRpbWUgZ2VuZXJhdGlvbilcbiAgICBjb25zdCBzdHlsZXMgPSBuZXcgdGVtcGxhdGVzLlN0eWxlcyh0aGlzLm9wdGlvbnMuc3R5bGVEZWZzKTtcbiAgICB0aGlzLnppcC5hcHBlbmQoc3R5bGVzLnJlbmRlcigpLCB7IG5hbWU6ICd4bC9zdHlsZXMueG1sJyB9KTtcblxuICAgIHRoaXMuemlwXG4gICAgICAub24oJ2RhdGEnLCBkYXRhID0+IHRoaXMucHVzaChkYXRhKSlcbiAgICAgIC5vbignd2FybmluZycsIGVyciA9PiB0aGlzLmVtaXQoJ3dhcm5pbmcnLCBlcnIpKVxuICAgICAgLm9uKCdlcnJvcicsIGVyciA9PiB0aGlzLmVtaXQoJ2Vycm9yJywgZXJyKSk7XG5cbiAgICB0aGlzLnRvWGxzeFJvdyA9IG5ldyBYTFNYUm93VHJhbnNmb3JtKHsgZm9ybWF0OiB0aGlzLm9wdGlvbnMuZm9ybWF0LCBzdHlsZXMgfSk7XG4gICAgdGhpcy5zaGVldFN0cmVhbSA9IG5ldyBQYXNzVGhyb3VnaCgpO1xuICAgIHRoaXMuc2hlZXRTdHJlYW0ud3JpdGUodGVtcGxhdGVzLlNoZWV0SGVhZGVyKTtcbiAgICB0aGlzLnRvWGxzeFJvdy5waXBlKHRoaXMuc2hlZXRTdHJlYW0sIHsgZW5kOiBmYWxzZSB9KTtcbiAgICB0aGlzLnppcC5hcHBlbmQodGhpcy5zaGVldFN0cmVhbSwge1xuICAgICAgbmFtZTogJ3hsL3dvcmtzaGVldHMvc2hlZXQxLnhtbCdcbiAgICB9KTtcblxuICAgIHRoaXMucGlwZWxpbmVJbml0aWFsaXplZCA9IHRydWU7XG4gIH1cblxuICBfaW5pdGlhbGl6ZUhlYWRlcihjaHVuayA9IFtdKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY2h1bmspKSB7XG4gICAgICB0aGlzLmNvbHVtbnMgPSAodGhpcy5vcHRpb25zLmNvbHVtbnMgPyB0aGlzLm9wdGlvbnMuY29sdW1ucyA6IGNodW5rKS5tYXAoKHZhbHVlLCBpbmRleCkgPT4gaW5kZXgpO1xuXG4gICAgICBpZiAoQXJyYXkuaXNBcnJheSh0aGlzLm9wdGlvbnMuY29sdW1ucykpIHtcbiAgICAgICAgdGhpcy5oZWFkZXIgPSBbLi4udGhpcy5vcHRpb25zLmNvbHVtbnNdO1xuICAgICAgfSBlbHNlIGlmIChpc09iamVjdCh0aGlzLm9wdGlvbnMuY29sdW1ucykpIHtcbiAgICAgICAgdGhpcy5oZWFkZXIgPSBbLi4uT2JqZWN0LnZhbHVlcyh0aGlzLm9wdGlvbnMuY29sdW1ucyldO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheSh0aGlzLm9wdGlvbnMuY29sdW1ucykpIHtcbiAgICAgICAgdGhpcy5oZWFkZXIgPSBbLi4udGhpcy5vcHRpb25zLmNvbHVtbnNdO1xuICAgICAgICB0aGlzLmNvbHVtbnMgPSBbLi4udGhpcy5vcHRpb25zLmNvbHVtbnNdO1xuICAgICAgfSBlbHNlIGlmIChpc09iamVjdCh0aGlzLm9wdGlvbnMuY29sdW1ucykpIHtcbiAgICAgICAgdGhpcy5oZWFkZXIgPSBbLi4uT2JqZWN0LnZhbHVlcyh0aGlzLm9wdGlvbnMuY29sdW1ucyldO1xuICAgICAgICB0aGlzLmNvbHVtbnMgPSBbLi4uT2JqZWN0LmtleXModGhpcy5vcHRpb25zLmNvbHVtbnMpXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIEluaXQgaGVhZGVyIGFuZCBjb2x1bW5zIGZyb20gY2h1bmtcbiAgICAgICAgdGhpcy5oZWFkZXIgPSBbLi4uT2JqZWN0LmtleXMoY2h1bmspXTtcbiAgICAgICAgdGhpcy5jb2x1bW5zID0gWy4uLk9iamVjdC5rZXlzKGNodW5rKV07XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5oZWFkZXIgJiYgdGhpcy5oZWFkZXIpIHtcbiAgICAgIHRoaXMudG9YbHN4Um93LndyaXRlKHRoaXMuaGVhZGVyKTtcbiAgICB9XG4gIH1cblxuICBfZmluYWwoY2FsbGJhY2spIHtcbiAgICBpZiAoIXRoaXMuaW5pdGlhbGl6ZWQpIHRoaXMuX2luaXRpYWxpemUoKTtcbiAgICB0aGlzLnRvWGxzeFJvdy5lbmQoKTtcbiAgICB0aGlzLnRvWGxzeFJvdy5vbignZW5kJywgKCkgPT5cbiAgICAgIHRoaXMuX2ZpbmFsaXplKCkudGhlbigoKSA9PiB7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogRmluYWxpemUgdGhlIHppcCBhcmNoaXZlXG4gICAqL1xuICBfZmluYWxpemUoKSB7XG4gICAgdGhpcy5zaGVldFN0cmVhbS5lbmQodGVtcGxhdGVzLlNoZWV0Rm9vdGVyKTtcbiAgICByZXR1cm4gdGhpcy56aXAuZmluYWxpemUoKTtcbiAgfVxufVxuIl19