@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
JavaScript
"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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9YTFNYV3JpdGVTdHJlYW0uanMiXSwibmFtZXMiOlsiWExTWFdyaXRlU3RyZWFtIiwiVHJhbnNmb3JtIiwiY29uc3RydWN0b3IiLCJvcHRpb25zIiwib2JqZWN0TW9kZSIsInBpcGVsaW5lSW5pdGlhbGl6ZWQiLCJpbml0aWFsaXplZCIsImFycmF5TW9kZSIsImhlYWRlciIsImZvcm1hdCIsImltbWVkaWF0ZUluaXRpYWxpemF0aW9uIiwiX2luaXRpYWxpemVQaXBlbGluZSIsIl90cmFuc2Zvcm0iLCJjaHVuayIsImVuY29kaW5nIiwiY2FsbGJhY2siLCJfaW5pdGlhbGl6ZSIsInRvWGxzeFJvdyIsIndyaXRlIiwibm9ybWFsaXplIiwiX2luaXRpYWxpemVIZWFkZXIiLCJBcnJheSIsImlzQXJyYXkiLCJjb2x1bW5zIiwibWFwIiwia2V5IiwiemlwIiwiZm9yY2VVVEMiLCJjYXRjaEVhcmx5RXhpdEF0dGFjaGVkIiwiYXBwZW5kIiwidGVtcGxhdGVzIiwiQ29udGVudFR5cGVzIiwibmFtZSIsIlJlbHMiLCJXb3JrYm9vayIsIldvcmtib29rUmVscyIsInN0eWxlcyIsIlN0eWxlcyIsInN0eWxlRGVmcyIsInJlbmRlciIsIm9uIiwiZGF0YSIsInB1c2giLCJlcnIiLCJlbWl0IiwiWExTWFJvd1RyYW5zZm9ybSIsInNoZWV0U3RyZWFtIiwiUGFzc1Rocm91Z2giLCJTaGVldEhlYWRlciIsInBpcGUiLCJlbmQiLCJ2YWx1ZSIsImluZGV4IiwiT2JqZWN0IiwidmFsdWVzIiwia2V5cyIsIl9maW5hbCIsIl9maW5hbGl6ZSIsInRoZW4iLCJTaGVldEZvb3RlciIsImZpbmFsaXplIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBQUE7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7O0FBQ0E7Ozs7Ozs7O0FBRUE7QUFDQTtBQUNBO0FBQ2UsTUFBTUEsZUFBTixTQUE4QkMsaUJBQTlCLENBQXdDO0FBQ3JEO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDRUMsRUFBQUEsV0FBVyxDQUFDQyxPQUFELEVBQVU7QUFDbkIsVUFBTTtBQUFFQyxNQUFBQSxVQUFVLEVBQUU7QUFBZCxLQUFOO0FBRUEsU0FBS0MsbUJBQUwsR0FBMkIsS0FBM0I7QUFDQSxTQUFLQyxXQUFMLEdBQW1CLEtBQW5CO0FBQ0EsU0FBS0MsU0FBTCxHQUFpQixJQUFqQjtBQUVBLFNBQUtKLE9BQUwsR0FBZSwyQkFBYSxFQUFiLEVBQWlCQSxPQUFqQixFQUEwQjtBQUFFSyxNQUFBQSxNQUFNLEVBQUUsS0FBVjtBQUFpQkMsTUFBQUEsTUFBTSxFQUFFLElBQXpCO0FBQStCQyxNQUFBQSx1QkFBdUIsRUFBRTtBQUF4RCxLQUExQixDQUFmO0FBRUEsUUFBSSxLQUFLUCxPQUFMLENBQWFPLHVCQUFqQixFQUEwQyxLQUFLQyxtQkFBTDtBQUMzQzs7QUFFREMsRUFBQUEsVUFBVSxDQUFDQyxLQUFELEVBQVFDLFFBQVIsRUFBa0JDLFFBQWxCLEVBQTRCO0FBQ3BDLFFBQUksQ0FBQyxLQUFLVCxXQUFWLEVBQXVCLEtBQUtVLFdBQUwsQ0FBaUJILEtBQWpCO0FBRXZCLFNBQUtJLFNBQUwsQ0FBZUMsS0FBZixDQUFxQixLQUFLQyxTQUFMLENBQWVOLEtBQWYsQ0FBckIsRUFBNENDLFFBQTVDLEVBQXNEQyxRQUF0RDtBQUNEOztBQUVEQyxFQUFBQSxXQUFXLENBQUNILEtBQUQsRUFBUTtBQUNqQixTQUFLRixtQkFBTDs7QUFDQSxTQUFLUyxpQkFBTCxDQUF1QlAsS0FBdkI7O0FBRUEsUUFBSUEsS0FBSixFQUFXO0FBQ1QsV0FBS04sU0FBTCxHQUFpQmMsS0FBSyxDQUFDQyxPQUFOLENBQWNULEtBQWQsQ0FBakI7O0FBQ0EsV0FBS00sU0FBTCxHQUFpQk4sS0FBSyxJQUFJLEtBQUtVLE9BQUwsQ0FBYUMsR0FBYixDQUFpQkMsR0FBRyxJQUFJWixLQUFLLENBQUNZLEdBQUQsQ0FBN0IsQ0FBMUI7QUFDRDs7QUFFRCxTQUFLbkIsV0FBTCxHQUFtQixJQUFuQjtBQUNEO0FBRUQ7QUFDRjtBQUNBOzs7QUFDRUssRUFBQUEsbUJBQW1CLEdBQUc7QUFDcEIsUUFBSSxLQUFLTixtQkFBVCxFQUE4QjtBQUU5QixTQUFLcUIsR0FBTCxHQUFXLHVCQUFTLEtBQVQsRUFBZ0I7QUFBRUMsTUFBQUEsUUFBUSxFQUFFO0FBQVosS0FBaEIsQ0FBWDtBQUNBLFNBQUtELEdBQUwsQ0FBU0Usc0JBQVQsR0FBa0MsSUFBbEMsQ0FKb0IsQ0FNcEI7O0FBQ0EsU0FBS0YsR0FBTCxDQUFTRyxNQUFULENBQWdCQyxTQUFTLENBQUNDLFlBQTFCLEVBQXdDO0FBQUVDLE1BQUFBLElBQUksRUFBRTtBQUFSLEtBQXhDO0FBQ0EsU0FBS04sR0FBTCxDQUFTRyxNQUFULENBQWdCQyxTQUFTLENBQUNHLElBQTFCLEVBQWdDO0FBQUVELE1BQUFBLElBQUksRUFBRTtBQUFSLEtBQWhDO0FBQ0EsU0FBS04sR0FBTCxDQUFTRyxNQUFULENBQWdCQyxTQUFTLENBQUNJLFFBQTFCLEVBQW9DO0FBQUVGLE1BQUFBLElBQUksRUFBRTtBQUFSLEtBQXBDO0FBQ0EsU0FBS04sR0FBTCxDQUFTRyxNQUFULENBQWdCQyxTQUFTLENBQUNLLFlBQTFCLEVBQXdDO0FBQUVILE1BQUFBLElBQUksRUFBRTtBQUFSLEtBQXhDLEVBVm9CLENBWXBCOztBQUNBLFVBQU1JLE1BQU0sR0FBRyxJQUFJTixTQUFTLENBQUNPLE1BQWQsQ0FBcUIsS0FBS2xDLE9BQUwsQ0FBYW1DLFNBQWxDLENBQWY7QUFDQSxTQUFLWixHQUFMLENBQVNHLE1BQVQsQ0FBZ0JPLE1BQU0sQ0FBQ0csTUFBUCxFQUFoQixFQUFpQztBQUFFUCxNQUFBQSxJQUFJLEVBQUU7QUFBUixLQUFqQztBQUVBLFNBQUtOLEdBQUwsQ0FDR2MsRUFESCxDQUNNLE1BRE4sRUFDY0MsSUFBSSxJQUFJLEtBQUtDLElBQUwsQ0FBVUQsSUFBVixDQUR0QixFQUVHRCxFQUZILENBRU0sU0FGTixFQUVpQkcsR0FBRyxJQUFJLEtBQUtDLElBQUwsQ0FBVSxTQUFWLEVBQXFCRCxHQUFyQixDQUZ4QixFQUdHSCxFQUhILENBR00sT0FITixFQUdlRyxHQUFHLElBQUksS0FBS0MsSUFBTCxDQUFVLE9BQVYsRUFBbUJELEdBQW5CLENBSHRCO0FBS0EsU0FBSzFCLFNBQUwsR0FBaUIsSUFBSTRCLHlCQUFKLENBQXFCO0FBQUVwQyxNQUFBQSxNQUFNLEVBQUUsS0FBS04sT0FBTCxDQUFhTSxNQUF2QjtBQUErQjJCLE1BQUFBO0FBQS9CLEtBQXJCLENBQWpCO0FBQ0EsU0FBS1UsV0FBTCxHQUFtQixJQUFJQyxtQkFBSixFQUFuQjtBQUNBLFNBQUtELFdBQUwsQ0FBaUI1QixLQUFqQixDQUF1QlksU0FBUyxDQUFDa0IsV0FBakM7QUFDQSxTQUFLL0IsU0FBTCxDQUFlZ0MsSUFBZixDQUFvQixLQUFLSCxXQUF6QixFQUFzQztBQUFFSSxNQUFBQSxHQUFHLEVBQUU7QUFBUCxLQUF0QztBQUNBLFNBQUt4QixHQUFMLENBQVNHLE1BQVQsQ0FBZ0IsS0FBS2lCLFdBQXJCLEVBQWtDO0FBQ2hDZCxNQUFBQSxJQUFJLEVBQUU7QUFEMEIsS0FBbEM7QUFJQSxTQUFLM0IsbUJBQUwsR0FBMkIsSUFBM0I7QUFDRDs7QUFFRGUsRUFBQUEsaUJBQWlCLENBQUNQLEtBQUssR0FBRyxFQUFULEVBQWE7QUFDNUIsUUFBSVEsS0FBSyxDQUFDQyxPQUFOLENBQWNULEtBQWQsQ0FBSixFQUEwQjtBQUN4QixXQUFLVSxPQUFMLEdBQWUsQ0FBQyxLQUFLcEIsT0FBTCxDQUFhb0IsT0FBYixHQUF1QixLQUFLcEIsT0FBTCxDQUFhb0IsT0FBcEMsR0FBOENWLEtBQS9DLEVBQXNEVyxHQUF0RCxDQUEwRCxDQUFDMkIsS0FBRCxFQUFRQyxLQUFSLEtBQWtCQSxLQUE1RSxDQUFmOztBQUVBLFVBQUkvQixLQUFLLENBQUNDLE9BQU4sQ0FBYyxLQUFLbkIsT0FBTCxDQUFhb0IsT0FBM0IsQ0FBSixFQUF5QztBQUN2QyxhQUFLZixNQUFMLEdBQWMsQ0FBQyxHQUFHLEtBQUtMLE9BQUwsQ0FBYW9CLE9BQWpCLENBQWQ7QUFDRCxPQUZELE1BRU8sSUFBSSx1QkFBUyxLQUFLcEIsT0FBTCxDQUFhb0IsT0FBdEIsQ0FBSixFQUFvQztBQUN6QyxhQUFLZixNQUFMLEdBQWMsQ0FBQyxHQUFHNkMsTUFBTSxDQUFDQyxNQUFQLENBQWMsS0FBS25ELE9BQUwsQ0FBYW9CLE9BQTNCLENBQUosQ0FBZDtBQUNEO0FBQ0YsS0FSRCxNQVFPO0FBQ0wsVUFBSUYsS0FBSyxDQUFDQyxPQUFOLENBQWMsS0FBS25CLE9BQUwsQ0FBYW9CLE9BQTNCLENBQUosRUFBeUM7QUFDdkMsYUFBS2YsTUFBTCxHQUFjLENBQUMsR0FBRyxLQUFLTCxPQUFMLENBQWFvQixPQUFqQixDQUFkO0FBQ0EsYUFBS0EsT0FBTCxHQUFlLENBQUMsR0FBRyxLQUFLcEIsT0FBTCxDQUFhb0IsT0FBakIsQ0FBZjtBQUNELE9BSEQsTUFHTyxJQUFJLHVCQUFTLEtBQUtwQixPQUFMLENBQWFvQixPQUF0QixDQUFKLEVBQW9DO0FBQ3pDLGFBQUtmLE1BQUwsR0FBYyxDQUFDLEdBQUc2QyxNQUFNLENBQUNDLE1BQVAsQ0FBYyxLQUFLbkQsT0FBTCxDQUFhb0IsT0FBM0IsQ0FBSixDQUFkO0FBQ0EsYUFBS0EsT0FBTCxHQUFlLENBQUMsR0FBRzhCLE1BQU0sQ0FBQ0UsSUFBUCxDQUFZLEtBQUtwRCxPQUFMLENBQWFvQixPQUF6QixDQUFKLENBQWY7QUFDRCxPQUhNLE1BR0E7QUFDTDtBQUNBLGFBQUtmLE1BQUwsR0FBYyxDQUFDLEdBQUc2QyxNQUFNLENBQUNFLElBQVAsQ0FBWTFDLEtBQVosQ0FBSixDQUFkO0FBQ0EsYUFBS1UsT0FBTCxHQUFlLENBQUMsR0FBRzhCLE1BQU0sQ0FBQ0UsSUFBUCxDQUFZMUMsS0FBWixDQUFKLENBQWY7QUFDRDtBQUNGOztBQUVELFFBQUksS0FBS1YsT0FBTCxDQUFhSyxNQUFiLElBQXVCLEtBQUtBLE1BQWhDLEVBQXdDO0FBQ3RDLFdBQUtTLFNBQUwsQ0FBZUMsS0FBZixDQUFxQixLQUFLVixNQUExQjtBQUNEO0FBQ0Y7O0FBRURnRCxFQUFBQSxNQUFNLENBQUN6QyxRQUFELEVBQVc7QUFDZixRQUFJLENBQUMsS0FBS1QsV0FBVixFQUF1QixLQUFLVSxXQUFMO0FBQ3ZCLFNBQUtDLFNBQUwsQ0FBZWlDLEdBQWY7QUFDQSxTQUFLakMsU0FBTCxDQUFldUIsRUFBZixDQUFrQixLQUFsQixFQUF5QixNQUN2QixLQUFLaUIsU0FBTCxHQUFpQkMsSUFBakIsQ0FBc0IsTUFBTTtBQUMxQjNDLE1BQUFBLFFBQVE7QUFDVCxLQUZELENBREY7QUFLRDtBQUVEO0FBQ0Y7QUFDQTs7O0FBQ0UwQyxFQUFBQSxTQUFTLEdBQUc7QUFDVixTQUFLWCxXQUFMLENBQWlCSSxHQUFqQixDQUFxQnBCLFNBQVMsQ0FBQzZCLFdBQS9CO0FBQ0EsV0FBTyxLQUFLakMsR0FBTCxDQUFTa0MsUUFBVCxFQUFQO0FBQ0Q7O0FBNUhvRCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBkZWZhdWx0c0RlZXAgZnJvbSAnbG9kYXNoL2RlZmF1bHRzRGVlcCc7XG5pbXBvcnQgaXNPYmplY3QgZnJvbSAnbG9kYXNoL2lzT2JqZWN0JztcbmltcG9ydCBBcmNoaXZlciBmcm9tICdhcmNoaXZlcic7XG5pbXBvcnQgeyBUcmFuc2Zvcm0sIFBhc3NUaHJvdWdoIH0gZnJvbSAnc3RyZWFtJztcbmltcG9ydCAqIGFzIHRlbXBsYXRlcyBmcm9tICcuL3RlbXBsYXRlcyc7XG5pbXBvcnQgWExTWFJvd1RyYW5zZm9ybSBmcm9tICcuL1hMU1hSb3dUcmFuc2Zvcm0nO1xuXG4vKipcbiAqIFhMU1ggV3JpdGUgU3RyZWFtIGJhc2UgY2xhc3NcbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgWExTWFdyaXRlU3RyZWFtIGV4dGVuZHMgVHJhbnNmb3JtIHtcbiAgLyoqXG4gICAqIENyZWF0ZSBuZXcgc3RyZWFtIHRyYW5zZm9ybSB0aGF0IGhhbmRsZXMgQXJyYXkgb3IgT2JqZWN0IGFzIGlucHV0IGNodW5rcy5cbiAgICogQmUgYXdhcmUgdGhhdCBmaXJzdCByb3cgY2h1bmsgaXMgZGV0ZXJtaW5hbnQgaW4gdGhlIHRyYW5zZm9ybSBjb25maWd1cmF0aW9uIHByb2Nlc3MgZm9yIGZ1cnRoZXIgcm93IGNodW5rcy5cbiAgICogQGNsYXNzIFhMU1hXcml0ZVN0cmVhbVxuICAgKiBAZXh0ZW5kcyBUcmFuc2Zvcm1cbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zXVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLmhlYWRlcj1mYWxzZV0gLSBEaXNwbGF5IHRoZSBjb2x1bW4gbmFtZXMgb24gdGhlIGZpcnN0IGxpbmUgaWYgdGhlIGNvbHVtbnMgb3B0aW9uIGlzIHByb3ZpZGVkIG9yIGRpc2NvdmVyZWQuXG4gICAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fSBbb3B0aW9ucy5jb2x1bW5zXSAtIExpc3Qgb2YgcHJvcGVydGllcyB3aGVuIHJlY29yZHMgYXJlIHByb3ZpZGVkIGFzIG9iamVjdHMuXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFdvcmsgd2l0aCByZWNvcmRzIGluIHRoZSBmb3JtIG9mIGFycmF5cyBiYXNlZCBvbiBpbmRleCBwb3NpdGlvbjsgb3JkZXIgbWF0dGVycy5cbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXV0byBkaXNjb3ZlcmVkIGluIHRoZSBmaXJzdCByZWNvcmQgd2hlbiB0aGUgdXNlciB3cml0ZSBvYmplY3RzLCBjYW4gcmVmZXIgdG8gbmVzdGVkIHByb3BlcnRpZXMgb2YgdGhlIGlucHV0IEpTT04sIHNlZSB0aGUgYGhlYWRlcmAgb3B0aW9uIG9uIGhvdyB0byBwcmludCBjb2x1bW5zIG5hbWVzIG9uIHRoZSBmaXJzdCBsaW5lLlxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLmZvcm1hdD10cnVlXSAtIElmIHNldCB0byBmYWxzZSB3cml0ZXIgd2lsbCBub3QgZm9ybWF0IGNlbGxzIHdpdGggbnVtYmVyLCBkYXRlLCBib29sZWFuIGFuZCB0ZXh0LlxuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnMuc3R5bGVEZWZzXSAtIElmIHNldCB5b3UgY2FuIG92ZXJ3cml0ZSBkZWZhdWx0IHN0YW5kYXJkIHR5cGUgc3R5bGVzIGJ5IG90aGVyIHN0YW5kYXJkIG9uZXMgb3IgZXZlbiBkZWZpbmUgY3VzdG9tIGBmb3JtYXRDb2RlYC5cbiAgICogQHBhcmFtIHtCb29sZWFufSBbb3B0aW9ucy5pbW1lZGlhdGVJbml0aWFsaXphdGlvbj1mYWxzZV0gLSBJZiBzZXQgdG8gdHJ1ZSB3cml0ZXIgd2lsbCBpbml0aWFsaXplIGFyY2hpdmUgYW5kIHN0YXJ0IGNvbXByZXNzaW5nIHhsc3ggY29tbW9uIHN0dWZmIGltbWVkaWF0ZWx5LCBhZGRpbmcgc3Vic2VxdWVudGx5IGEgbGl0dGxlIG1lbW9yeSBhbmQgcHJvY2Vzc29yIGZvb3RwcmludC4gSWYgbm90LCBpbml0aWFsaXphdGlvbiB3aWxsIGJlIGRlbGF5ZWQgdG8gdGhlIGZpcnN0IGRhdGEgcHJvY2Vzc2luZy5cbiAgICovXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnMpIHtcbiAgICBzdXBlcih7IG9iamVjdE1vZGU6IHRydWUgfSk7XG5cbiAgICB0aGlzLnBpcGVsaW5lSW5pdGlhbGl6ZWQgPSBmYWxzZTtcbiAgICB0aGlzLmluaXRpYWxpemVkID0gZmFsc2U7XG4gICAgdGhpcy5hcnJheU1vZGUgPSBudWxsO1xuXG4gICAgdGhpcy5vcHRpb25zID0gZGVmYXVsdHNEZWVwKHt9LCBvcHRpb25zLCB7IGhlYWRlcjogZmFsc2UsIGZvcm1hdDogdHJ1ZSwgaW1tZWRpYXRlSW5pdGlhbGl6YXRpb246IGZhbHNlIH0pO1xuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5pbW1lZGlhdGVJbml0aWFsaXphdGlvbikgdGhpcy5faW5pdGlhbGl6ZVBpcGVsaW5lKCk7XG4gIH1cblxuICBfdHJhbnNmb3JtKGNodW5rLCBlbmNvZGluZywgY2FsbGJhY2spIHtcbiAgICBpZiAoIXRoaXMuaW5pdGlhbGl6ZWQpIHRoaXMuX2luaXRpYWxpemUoY2h1bmspO1xuXG4gICAgdGhpcy50b1hsc3hSb3cud3JpdGUodGhpcy5ub3JtYWxpemUoY2h1bmspLCBlbmNvZGluZywgY2FsbGJhY2spO1xuICB9XG5cbiAgX2luaXRpYWxpemUoY2h1bmspIHtcbiAgICB0aGlzLl9pbml0aWFsaXplUGlwZWxpbmUoKTtcbiAgICB0aGlzLl9pbml0aWFsaXplSGVhZGVyKGNodW5rKTtcblxuICAgIGlmIChjaHVuaykge1xuICAgICAgdGhpcy5hcnJheU1vZGUgPSBBcnJheS5pc0FycmF5KGNodW5rKTtcbiAgICAgIHRoaXMubm9ybWFsaXplID0gY2h1bmsgPT4gdGhpcy5jb2x1bW5zLm1hcChrZXkgPT4gY2h1bmtba2V5XSk7XG4gICAgfVxuXG4gICAgdGhpcy5pbml0aWFsaXplZCA9IHRydWU7XG4gIH1cblxuICAvKipcbiAgICogSW5pdGlhbGl6ZSBwaXBlbGluZSB3aXRoIHhsc3ggYXJjaGl2ZSBjb21tb24gZmlsZXNcbiAgICovXG4gIF9pbml0aWFsaXplUGlwZWxpbmUoKSB7XG4gICAgaWYgKHRoaXMucGlwZWxpbmVJbml0aWFsaXplZCkgcmV0dXJuO1xuXG4gICAgdGhpcy56aXAgPSBBcmNoaXZlcignemlwJywgeyBmb3JjZVVUQzogdHJ1ZSB9KTtcbiAgICB0aGlzLnppcC5jYXRjaEVhcmx5RXhpdEF0dGFjaGVkID0gdHJ1ZTtcblxuICAgIC8vIENvbW1vbiB4bHN4IGFyY2hpdmUgZmlsZXMgKG5vdCBlZGl0YWJsZSlcbiAgICB0aGlzLnppcC5hcHBlbmQodGVtcGxhdGVzLkNvbnRlbnRUeXBlcywgeyBuYW1lOiAnW0NvbnRlbnRfVHlwZXNdLnhtbCcgfSk7XG4gICAgdGhpcy56aXAuYXBwZW5kKHRlbXBsYXRlcy5SZWxzLCB7IG5hbWU6ICdfcmVscy8ucmVscycgfSk7XG4gICAgdGhpcy56aXAuYXBwZW5kKHRlbXBsYXRlcy5Xb3JrYm9vaywgeyBuYW1lOiAneGwvd29ya2Jvb2sueG1sJyB9KTtcbiAgICB0aGlzLnppcC5hcHBlbmQodGVtcGxhdGVzLldvcmtib29rUmVscywgeyBuYW1lOiAneGwvX3JlbHMvd29ya2Jvb2sueG1sLnJlbHMnIH0pO1xuXG4gICAgLy8gU3R5bGUgeGxzeCBkZWZpbml0aW9ucyAob25lIHRpbWUgZ2VuZXJhdGlvbilcbiAgICBjb25zdCBzdHlsZXMgPSBuZXcgdGVtcGxhdGVzLlN0eWxlcyh0aGlzLm9wdGlvbnMuc3R5bGVEZWZzKTtcbiAgICB0aGlzLnppcC5hcHBlbmQoc3R5bGVzLnJlbmRlcigpLCB7IG5hbWU6ICd4bC9zdHlsZXMueG1sJyB9KTtcblxuICAgIHRoaXMuemlwXG4gICAgICAub24oJ2RhdGEnLCBkYXRhID0+IHRoaXMucHVzaChkYXRhKSlcbiAgICAgIC5vbignd2FybmluZycsIGVyciA9PiB0aGlzLmVtaXQoJ3dhcm5pbmcnLCBlcnIpKVxuICAgICAgLm9uKCdlcnJvcicsIGVyciA9PiB0aGlzLmVtaXQoJ2Vycm9yJywgZXJyKSk7XG5cbiAgICB0aGlzLnRvWGxzeFJvdyA9IG5ldyBYTFNYUm93VHJhbnNmb3JtKHsgZm9ybWF0OiB0aGlzLm9wdGlvbnMuZm9ybWF0LCBzdHlsZXMgfSk7XG4gICAgdGhpcy5zaGVldFN0cmVhbSA9IG5ldyBQYXNzVGhyb3VnaCgpO1xuICAgIHRoaXMuc2hlZXRTdHJlYW0ud3JpdGUodGVtcGxhdGVzLlNoZWV0SGVhZGVyKTtcbiAgICB0aGlzLnRvWGxzeFJvdy5waXBlKHRoaXMuc2hlZXRTdHJlYW0sIHsgZW5kOiBmYWxzZSB9KTtcbiAgICB0aGlzLnppcC5hcHBlbmQodGhpcy5zaGVldFN0cmVhbSwge1xuICAgICAgbmFtZTogJ3hsL3dvcmtzaGVldHMvc2hlZXQxLnhtbCdcbiAgICB9KTtcblxuICAgIHRoaXMucGlwZWxpbmVJbml0aWFsaXplZCA9IHRydWU7XG4gIH1cblxuICBfaW5pdGlhbGl6ZUhlYWRlcihjaHVuayA9IFtdKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY2h1bmspKSB7XG4gICAgICB0aGlzLmNvbHVtbnMgPSAodGhpcy5vcHRpb25zLmNvbHVtbnMgPyB0aGlzLm9wdGlvbnMuY29sdW1ucyA6IGNodW5rKS5tYXAoKHZhbHVlLCBpbmRleCkgPT4gaW5kZXgpO1xuXG4gICAgICBpZiAoQXJyYXkuaXNBcnJheSh0aGlzLm9wdGlvbnMuY29sdW1ucykpIHtcbiAgICAgICAgdGhpcy5oZWFkZXIgPSBbLi4udGhpcy5vcHRpb25zLmNvbHVtbnNdO1xuICAgICAgfSBlbHNlIGlmIChpc09iamVjdCh0aGlzLm9wdGlvbnMuY29sdW1ucykpIHtcbiAgICAgICAgdGhpcy5oZWFkZXIgPSBbLi4uT2JqZWN0LnZhbHVlcyh0aGlzLm9wdGlvbnMuY29sdW1ucyldO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoQXJyYXkuaXNBcnJheSh0aGlzLm9wdGlvbnMuY29sdW1ucykpIHtcbiAgICAgICAgdGhpcy5oZWFkZXIgPSBbLi4udGhpcy5vcHRpb25zLmNvbHVtbnNdO1xuICAgICAgICB0aGlzLmNvbHVtbnMgPSBbLi4udGhpcy5vcHRpb25zLmNvbHVtbnNdO1xuICAgICAgfSBlbHNlIGlmIChpc09iamVjdCh0aGlzLm9wdGlvbnMuY29sdW1ucykpIHtcbiAgICAgICAgdGhpcy5oZWFkZXIgPSBbLi4uT2JqZWN0LnZhbHVlcyh0aGlzLm9wdGlvbnMuY29sdW1ucyldO1xuICAgICAgICB0aGlzLmNvbHVtbnMgPSBbLi4uT2JqZWN0LmtleXModGhpcy5vcHRpb25zLmNvbHVtbnMpXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIEluaXQgaGVhZGVyIGFuZCBjb2x1bW5zIGZyb20gY2h1bmtcbiAgICAgICAgdGhpcy5oZWFkZXIgPSBbLi4uT2JqZWN0LmtleXMoY2h1bmspXTtcbiAgICAgICAgdGhpcy5jb2x1bW5zID0gWy4uLk9iamVjdC5rZXlzKGNodW5rKV07XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5oZWFkZXIgJiYgdGhpcy5oZWFkZXIpIHtcbiAgICAgIHRoaXMudG9YbHN4Um93LndyaXRlKHRoaXMuaGVhZGVyKTtcbiAgICB9XG4gIH1cblxuICBfZmluYWwoY2FsbGJhY2spIHtcbiAgICBpZiAoIXRoaXMuaW5pdGlhbGl6ZWQpIHRoaXMuX2luaXRpYWxpemUoKTtcbiAgICB0aGlzLnRvWGxzeFJvdy5lbmQoKTtcbiAgICB0aGlzLnRvWGxzeFJvdy5vbignZW5kJywgKCkgPT5cbiAgICAgIHRoaXMuX2ZpbmFsaXplKCkudGhlbigoKSA9PiB7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICB9KVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogRmluYWxpemUgdGhlIHppcCBhcmNoaXZlXG4gICAqL1xuICBfZmluYWxpemUoKSB7XG4gICAgdGhpcy5zaGVldFN0cmVhbS5lbmQodGVtcGxhdGVzLlNoZWV0Rm9vdGVyKTtcbiAgICByZXR1cm4gdGhpcy56aXAuZmluYWxpemUoKTtcbiAgfVxufVxuIl19