@jsreport/exceljs
Version:
Excel Workbook Manager - Read and Write xlsx and csv Files.
1,552 lines (1,508 loc) • 2.01 MB
JavaScript
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.ExcelJS = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
(function (Buffer){(function (){
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.CsvFormatterStream = void 0;
const stream_1 = require("stream");
const formatter_1 = require("./formatter");
class CsvFormatterStream extends stream_1.Transform {
constructor(formatterOptions) {
super({
writableObjectMode: formatterOptions.objectMode
});
this.hasWrittenBOM = false;
this.formatterOptions = formatterOptions;
this.rowFormatter = new formatter_1.RowFormatter(formatterOptions);
// if writeBOM is false then set to true
// if writeBOM is true then set to false by default so it is written out
this.hasWrittenBOM = !formatterOptions.writeBOM;
}
transform(transformFunction) {
this.rowFormatter.rowTransform = transformFunction;
return this;
}
_transform(row, encoding, cb) {
let cbCalled = false;
try {
if (!this.hasWrittenBOM) {
this.push(this.formatterOptions.BOM);
this.hasWrittenBOM = true;
}
this.rowFormatter.format(row, (err, rows) => {
if (err) {
cbCalled = true;
return cb(err);
}
if (rows) {
rows.forEach(r => {
this.push(Buffer.from(r, 'utf8'));
});
}
cbCalled = true;
return cb();
});
} catch (e) {
if (cbCalled) {
throw e;
}
cb(e);
}
}
_flush(cb) {
this.rowFormatter.finish((err, rows) => {
if (err) {
return cb(err);
}
if (rows) {
rows.forEach(r => {
this.push(Buffer.from(r, 'utf8'));
});
}
return cb();
});
}
}
exports.CsvFormatterStream = CsvFormatterStream;
}).call(this)}).call(this,require("buffer").Buffer)
},{"./formatter":5,"buffer":85,"stream":237}],2:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.FormatterOptions = void 0;
class FormatterOptions {
constructor() {
let opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var _a;
this.objectMode = true;
this.delimiter = ',';
this.rowDelimiter = '\n';
this.quote = '"';
this.escape = this.quote;
this.quoteColumns = false;
this.quoteHeaders = this.quoteColumns;
this.headers = null;
this.includeEndRowDelimiter = false;
this.writeBOM = false;
this.BOM = '\ufeff';
this.alwaysWriteHeaders = false;
Object.assign(this, opts || {});
if (typeof (opts === null || opts === void 0 ? void 0 : opts.quoteHeaders) === 'undefined') {
this.quoteHeaders = this.quoteColumns;
}
if ((opts === null || opts === void 0 ? void 0 : opts.quote) === true) {
this.quote = '"';
} else if ((opts === null || opts === void 0 ? void 0 : opts.quote) === false) {
this.quote = '';
}
if (typeof (opts === null || opts === void 0 ? void 0 : opts.escape) !== 'string') {
this.escape = this.quote;
}
this.shouldWriteHeaders = !!this.headers && ((_a = opts.writeHeaders) !== null && _a !== void 0 ? _a : true);
this.headers = Array.isArray(this.headers) ? this.headers : null;
this.escapedQuote = "".concat(this.escape).concat(this.quote);
}
}
exports.FormatterOptions = FormatterOptions;
},{}],3:[function(require,module,exports){
"use strict";
var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
return mod && mod.__esModule ? mod : {
"default": mod
};
};
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.FieldFormatter = void 0;
const lodash_isboolean_1 = __importDefault(require("lodash.isboolean"));
const lodash_isnil_1 = __importDefault(require("lodash.isnil"));
const lodash_escaperegexp_1 = __importDefault(require("lodash.escaperegexp"));
class FieldFormatter {
constructor(formatterOptions) {
this._headers = null;
this.formatterOptions = formatterOptions;
if (formatterOptions.headers !== null) {
this.headers = formatterOptions.headers;
}
this.REPLACE_REGEXP = new RegExp(formatterOptions.quote, 'g');
const escapePattern = "[".concat(formatterOptions.delimiter).concat(lodash_escaperegexp_1.default(formatterOptions.rowDelimiter), "|\r|\n]");
this.ESCAPE_REGEXP = new RegExp(escapePattern);
}
set headers(headers) {
this._headers = headers;
}
shouldQuote(fieldIndex, isHeader) {
const quoteConfig = isHeader ? this.formatterOptions.quoteHeaders : this.formatterOptions.quoteColumns;
if (lodash_isboolean_1.default(quoteConfig)) {
return quoteConfig;
}
if (Array.isArray(quoteConfig)) {
return quoteConfig[fieldIndex];
}
if (this._headers !== null) {
return quoteConfig[this._headers[fieldIndex]];
}
return false;
}
format(field, fieldIndex, isHeader) {
const preparedField = "".concat(lodash_isnil_1.default(field) ? '' : field).replace(/\0/g, '');
const {
formatterOptions
} = this;
if (formatterOptions.quote !== '') {
const shouldEscape = preparedField.indexOf(formatterOptions.quote) !== -1;
if (shouldEscape) {
return this.quoteField(preparedField.replace(this.REPLACE_REGEXP, formatterOptions.escapedQuote));
}
}
const hasEscapeCharacters = preparedField.search(this.ESCAPE_REGEXP) !== -1;
if (hasEscapeCharacters || this.shouldQuote(fieldIndex, isHeader)) {
return this.quoteField(preparedField);
}
return preparedField;
}
quoteField(field) {
const {
quote
} = this.formatterOptions;
return "".concat(quote).concat(field).concat(quote);
}
}
exports.FieldFormatter = FieldFormatter;
},{"lodash.escaperegexp":144,"lodash.isboolean":146,"lodash.isnil":149}],4:[function(require,module,exports){
"use strict";
var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
return mod && mod.__esModule ? mod : {
"default": mod
};
};
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.RowFormatter = void 0;
const lodash_isfunction_1 = __importDefault(require("lodash.isfunction"));
const lodash_isequal_1 = __importDefault(require("lodash.isequal"));
const FieldFormatter_1 = require("./FieldFormatter");
const types_1 = require("../types");
class RowFormatter {
constructor(formatterOptions) {
this.rowCount = 0;
this.formatterOptions = formatterOptions;
this.fieldFormatter = new FieldFormatter_1.FieldFormatter(formatterOptions);
this.headers = formatterOptions.headers;
this.shouldWriteHeaders = formatterOptions.shouldWriteHeaders;
this.hasWrittenHeaders = false;
if (this.headers !== null) {
this.fieldFormatter.headers = this.headers;
}
if (formatterOptions.transform) {
this.rowTransform = formatterOptions.transform;
}
}
static isRowHashArray(row) {
if (Array.isArray(row)) {
return Array.isArray(row[0]) && row[0].length === 2;
}
return false;
}
static isRowArray(row) {
return Array.isArray(row) && !this.isRowHashArray(row);
}
// get headers from a row item
static gatherHeaders(row) {
if (RowFormatter.isRowHashArray(row)) {
// lets assume a multi-dimesional array with item 0 being the header
return row.map(it => it[0]);
}
if (Array.isArray(row)) {
return row;
}
return Object.keys(row);
}
// eslint-disable-next-line @typescript-eslint/no-shadow
static createTransform(transformFunction) {
if (types_1.isSyncTransform(transformFunction)) {
return (row, cb) => {
let transformedRow = null;
try {
transformedRow = transformFunction(row);
} catch (e) {
return cb(e);
}
return cb(null, transformedRow);
};
}
return (row, cb) => {
transformFunction(row, cb);
};
}
set rowTransform(transformFunction) {
if (!lodash_isfunction_1.default(transformFunction)) {
throw new TypeError('The transform should be a function');
}
this._rowTransform = RowFormatter.createTransform(transformFunction);
}
format(row, cb) {
this.callTransformer(row, (err, transformedRow) => {
if (err) {
return cb(err);
}
if (!row) {
return cb(null);
}
const rows = [];
if (transformedRow) {
const {
shouldFormatColumns,
headers
} = this.checkHeaders(transformedRow);
if (this.shouldWriteHeaders && headers && !this.hasWrittenHeaders) {
rows.push(this.formatColumns(headers, true));
this.hasWrittenHeaders = true;
}
if (shouldFormatColumns) {
const columns = this.gatherColumns(transformedRow);
rows.push(this.formatColumns(columns, false));
}
}
return cb(null, rows);
});
}
finish(cb) {
const rows = [];
// check if we should write headers and we didnt get any rows
if (this.formatterOptions.alwaysWriteHeaders && this.rowCount === 0) {
if (!this.headers) {
return cb(new Error('`alwaysWriteHeaders` option is set to true but `headers` option not provided.'));
}
rows.push(this.formatColumns(this.headers, true));
}
if (this.formatterOptions.includeEndRowDelimiter) {
rows.push(this.formatterOptions.rowDelimiter);
}
return cb(null, rows);
}
// check if we need to write header return true if we should also write a row
// could be false if headers is true and the header row(first item) is passed in
checkHeaders(row) {
if (this.headers) {
// either the headers were provided by the user or we have already gathered them.
return {
shouldFormatColumns: true,
headers: this.headers
};
}
const headers = RowFormatter.gatherHeaders(row);
this.headers = headers;
this.fieldFormatter.headers = headers;
if (!this.shouldWriteHeaders) {
// if we are not supposed to write the headers then
// always format the columns
return {
shouldFormatColumns: true,
headers: null
};
}
// if the row is equal to headers dont format
return {
shouldFormatColumns: !lodash_isequal_1.default(headers, row),
headers
};
}
// todo change this method to unknown[]
gatherColumns(row) {
if (this.headers === null) {
throw new Error('Headers is currently null');
}
if (!Array.isArray(row)) {
return this.headers.map(header => row[header]);
}
if (RowFormatter.isRowHashArray(row)) {
return this.headers.map((header, i) => {
const col = row[i];
if (col) {
return col[1];
}
return '';
});
}
// if its a one dimensional array and headers were not provided
// then just return the row
if (RowFormatter.isRowArray(row) && !this.shouldWriteHeaders) {
return row;
}
return this.headers.map((header, i) => row[i]);
}
callTransformer(row, cb) {
if (!this._rowTransform) {
return cb(null, row);
}
return this._rowTransform(row, cb);
}
formatColumns(columns, isHeadersRow) {
const formattedCols = columns.map((field, i) => this.fieldFormatter.format(field, i, isHeadersRow)).join(this.formatterOptions.delimiter);
const {
rowCount
} = this;
this.rowCount += 1;
if (rowCount) {
return [this.formatterOptions.rowDelimiter, formattedCols].join('');
}
return formattedCols;
}
}
exports.RowFormatter = RowFormatter;
},{"../types":7,"./FieldFormatter":3,"lodash.isequal":147,"lodash.isfunction":148}],5:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.FieldFormatter = exports.RowFormatter = void 0;
var RowFormatter_1 = require("./RowFormatter");
Object.defineProperty(exports, "RowFormatter", {
enumerable: true,
get: function () {
return RowFormatter_1.RowFormatter;
}
});
var FieldFormatter_1 = require("./FieldFormatter");
Object.defineProperty(exports, "FieldFormatter", {
enumerable: true,
get: function () {
return FieldFormatter_1.FieldFormatter;
}
});
},{"./FieldFormatter":3,"./RowFormatter":4}],6:[function(require,module,exports){
(function (Buffer){(function (){
"use strict";
var __createBinding = void 0 && (void 0).__createBinding || (Object.create ? function (o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, {
enumerable: true,
get: function () {
return m[k];
}
});
} : function (o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
});
var __setModuleDefault = void 0 && (void 0).__setModuleDefault || (Object.create ? function (o, v) {
Object.defineProperty(o, "default", {
enumerable: true,
value: v
});
} : function (o, v) {
o["default"] = v;
});
var __importStar = void 0 && (void 0).__importStar || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __exportStar = void 0 && (void 0).__exportStar || function (m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.writeToPath = exports.writeToString = exports.writeToBuffer = exports.writeToStream = exports.write = exports.format = exports.FormatterOptions = exports.CsvFormatterStream = void 0;
const util_1 = require("util");
const stream_1 = require("stream");
const fs = __importStar(require("fs"));
const FormatterOptions_1 = require("./FormatterOptions");
const CsvFormatterStream_1 = require("./CsvFormatterStream");
__exportStar(require("./types"), exports);
var CsvFormatterStream_2 = require("./CsvFormatterStream");
Object.defineProperty(exports, "CsvFormatterStream", {
enumerable: true,
get: function () {
return CsvFormatterStream_2.CsvFormatterStream;
}
});
var FormatterOptions_2 = require("./FormatterOptions");
Object.defineProperty(exports, "FormatterOptions", {
enumerable: true,
get: function () {
return FormatterOptions_2.FormatterOptions;
}
});
exports.format = options => new CsvFormatterStream_1.CsvFormatterStream(new FormatterOptions_1.FormatterOptions(options));
exports.write = (rows, options) => {
const csvStream = exports.format(options);
const promiseWrite = util_1.promisify((row, cb) => {
csvStream.write(row, undefined, cb);
});
rows.reduce((prev, row) => prev.then(() => promiseWrite(row)), Promise.resolve()).then(() => csvStream.end()).catch(err => {
csvStream.emit('error', err);
});
return csvStream;
};
exports.writeToStream = (ws, rows, options) => exports.write(rows, options).pipe(ws);
exports.writeToBuffer = function (rows) {
let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
const buffers = [];
const ws = new stream_1.Writable({
write(data, enc, writeCb) {
buffers.push(data);
writeCb();
}
});
return new Promise((res, rej) => {
ws.on('error', rej).on('finish', () => res(Buffer.concat(buffers)));
exports.write(rows, opts).pipe(ws);
});
};
exports.writeToString = (rows, options) => exports.writeToBuffer(rows, options).then(buffer => buffer.toString());
exports.writeToPath = (path, rows, options) => {
const stream = fs.createWriteStream(path, {
encoding: 'utf8'
});
return exports.write(rows, options).pipe(stream);
};
}).call(this)}).call(this,require("buffer").Buffer)
},{"./CsvFormatterStream":1,"./FormatterOptions":2,"./types":7,"buffer":85,"fs":84,"stream":237,"util":242}],7:[function(require,module,exports){
"use strict";
/* eslint-disable @typescript-eslint/no-explicit-any */
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.isSyncTransform = void 0;
exports.isSyncTransform = transform => transform.length === 1;
},{}],8:[function(require,module,exports){
(function (setImmediate){(function (){
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.CsvParserStream = void 0;
const string_decoder_1 = require("string_decoder");
const stream_1 = require("stream");
const transforms_1 = require("./transforms");
const parser_1 = require("./parser");
class CsvParserStream extends stream_1.Transform {
constructor(parserOptions) {
super({
objectMode: parserOptions.objectMode
});
this.lines = '';
this.rowCount = 0;
this.parsedRowCount = 0;
this.parsedLineCount = 0;
this.endEmitted = false;
this.headersEmitted = false;
this.parserOptions = parserOptions;
this.parser = new parser_1.Parser(parserOptions);
this.headerTransformer = new transforms_1.HeaderTransformer(parserOptions);
this.decoder = new string_decoder_1.StringDecoder(parserOptions.encoding);
this.rowTransformerValidator = new transforms_1.RowTransformerValidator();
}
get hasHitRowLimit() {
return this.parserOptions.limitRows && this.rowCount >= this.parserOptions.maxRows;
}
get shouldEmitRows() {
return this.parsedRowCount > this.parserOptions.skipRows;
}
get shouldSkipLine() {
return this.parsedLineCount <= this.parserOptions.skipLines;
}
transform(transformFunction) {
this.rowTransformerValidator.rowTransform = transformFunction;
return this;
}
validate(validateFunction) {
this.rowTransformerValidator.rowValidator = validateFunction;
return this;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
emit(event) {
if (event === 'end') {
if (!this.endEmitted) {
this.endEmitted = true;
super.emit('end', this.rowCount);
}
return false;
}
for (var _len = arguments.length, rest = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
rest[_key - 1] = arguments[_key];
}
return super.emit(event, ...rest);
}
_transform(data, encoding, done) {
// if we have hit our maxRows parsing limit then skip parsing
if (this.hasHitRowLimit) {
return done();
}
const wrappedCallback = CsvParserStream.wrapDoneCallback(done);
try {
const {
lines
} = this;
const newLine = lines + this.decoder.write(data);
const rows = this.parse(newLine, true);
return this.processRows(rows, wrappedCallback);
} catch (e) {
return wrappedCallback(e);
}
}
_flush(done) {
const wrappedCallback = CsvParserStream.wrapDoneCallback(done);
// if we have hit our maxRows parsing limit then skip parsing
if (this.hasHitRowLimit) {
return wrappedCallback();
}
try {
const newLine = this.lines + this.decoder.end();
const rows = this.parse(newLine, false);
return this.processRows(rows, wrappedCallback);
} catch (e) {
return wrappedCallback(e);
}
}
parse(data, hasMoreData) {
if (!data) {
return [];
}
const {
line,
rows
} = this.parser.parse(data, hasMoreData);
this.lines = line;
return rows;
}
processRows(rows, cb) {
const rowsLength = rows.length;
const iterate = i => {
const callNext = err => {
if (err) {
return cb(err);
}
if (i % 100 === 0) {
// incase the transform are sync insert a next tick to prevent stack overflow
setImmediate(() => iterate(i + 1));
return undefined;
}
return iterate(i + 1);
};
this.checkAndEmitHeaders();
// if we have emitted all rows or we have hit the maxRows limit option
// then end
if (i >= rowsLength || this.hasHitRowLimit) {
return cb();
}
this.parsedLineCount += 1;
if (this.shouldSkipLine) {
return callNext();
}
const row = rows[i];
this.rowCount += 1;
this.parsedRowCount += 1;
const nextRowCount = this.rowCount;
return this.transformRow(row, (err, transformResult) => {
if (err) {
this.rowCount -= 1;
return callNext(err);
}
if (!transformResult) {
return callNext(new Error('expected transform result'));
}
if (!transformResult.isValid) {
this.emit('data-invalid', transformResult.row, nextRowCount, transformResult.reason);
} else if (transformResult.row) {
return this.pushRow(transformResult.row, callNext);
}
return callNext();
});
};
iterate(0);
}
transformRow(parsedRow, cb) {
try {
this.headerTransformer.transform(parsedRow, (err, withHeaders) => {
if (err) {
return cb(err);
}
if (!withHeaders) {
return cb(new Error('Expected result from header transform'));
}
if (!withHeaders.isValid) {
if (this.shouldEmitRows) {
return cb(null, {
isValid: false,
row: parsedRow
});
}
// skipped because of skipRows option remove from total row count
return this.skipRow(cb);
}
if (withHeaders.row) {
if (this.shouldEmitRows) {
return this.rowTransformerValidator.transformAndValidate(withHeaders.row, cb);
}
// skipped because of skipRows option remove from total row count
return this.skipRow(cb);
}
// this is a header row dont include in the rowCount or parsedRowCount
this.rowCount -= 1;
this.parsedRowCount -= 1;
return cb(null, {
row: null,
isValid: true
});
});
} catch (e) {
cb(e);
}
}
checkAndEmitHeaders() {
if (!this.headersEmitted && this.headerTransformer.headers) {
this.headersEmitted = true;
this.emit('headers', this.headerTransformer.headers);
}
}
skipRow(cb) {
// skipped because of skipRows option remove from total row count
this.rowCount -= 1;
return cb(null, {
row: null,
isValid: true
});
}
pushRow(row, cb) {
try {
if (!this.parserOptions.objectMode) {
this.push(JSON.stringify(row));
} else {
this.push(row);
}
cb();
} catch (e) {
cb(e);
}
}
static wrapDoneCallback(done) {
let errorCalled = false;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return function (err) {
if (err) {
if (errorCalled) {
throw err;
}
errorCalled = true;
done(err);
return;
}
for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
args[_key2 - 1] = arguments[_key2];
}
done(...args);
};
}
}
exports.CsvParserStream = CsvParserStream;
}).call(this)}).call(this,require("timers").setImmediate)
},{"./parser":20,"./transforms":23,"stream":237,"string_decoder":87,"timers":238}],9:[function(require,module,exports){
"use strict";
var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
return mod && mod.__esModule ? mod : {
"default": mod
};
};
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ParserOptions = void 0;
const lodash_escaperegexp_1 = __importDefault(require("lodash.escaperegexp"));
const lodash_isnil_1 = __importDefault(require("lodash.isnil"));
class ParserOptions {
constructor(opts) {
var _a;
this.objectMode = true;
this.delimiter = ',';
this.ignoreEmpty = false;
this.quote = '"';
this.escape = null;
this.escapeChar = this.quote;
this.comment = null;
this.supportsComments = false;
this.ltrim = false;
this.rtrim = false;
this.trim = false;
this.headers = null;
this.renameHeaders = false;
this.strictColumnHandling = false;
this.discardUnmappedColumns = false;
this.carriageReturn = '\r';
this.encoding = 'utf8';
this.limitRows = false;
this.maxRows = 0;
this.skipLines = 0;
this.skipRows = 0;
Object.assign(this, opts || {});
if (this.delimiter.length > 1) {
throw new Error('delimiter option must be one character long');
}
this.escapedDelimiter = lodash_escaperegexp_1.default(this.delimiter);
this.escapeChar = (_a = this.escape) !== null && _a !== void 0 ? _a : this.quote;
this.supportsComments = !lodash_isnil_1.default(this.comment);
this.NEXT_TOKEN_REGEXP = new RegExp("([^\\s]|\\r\\n|\\n|\\r|".concat(this.escapedDelimiter, ")"));
if (this.maxRows > 0) {
this.limitRows = true;
}
}
}
exports.ParserOptions = ParserOptions;
},{"lodash.escaperegexp":144,"lodash.isnil":149}],10:[function(require,module,exports){
"use strict";
var __createBinding = void 0 && (void 0).__createBinding || (Object.create ? function (o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, {
enumerable: true,
get: function () {
return m[k];
}
});
} : function (o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
});
var __setModuleDefault = void 0 && (void 0).__setModuleDefault || (Object.create ? function (o, v) {
Object.defineProperty(o, "default", {
enumerable: true,
value: v
});
} : function (o, v) {
o["default"] = v;
});
var __importStar = void 0 && (void 0).__importStar || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __exportStar = void 0 && (void 0).__exportStar || function (m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.parseString = exports.parseFile = exports.parseStream = exports.parse = exports.ParserOptions = exports.CsvParserStream = void 0;
const fs = __importStar(require("fs"));
const stream_1 = require("stream");
const ParserOptions_1 = require("./ParserOptions");
const CsvParserStream_1 = require("./CsvParserStream");
__exportStar(require("./types"), exports);
var CsvParserStream_2 = require("./CsvParserStream");
Object.defineProperty(exports, "CsvParserStream", {
enumerable: true,
get: function () {
return CsvParserStream_2.CsvParserStream;
}
});
var ParserOptions_2 = require("./ParserOptions");
Object.defineProperty(exports, "ParserOptions", {
enumerable: true,
get: function () {
return ParserOptions_2.ParserOptions;
}
});
exports.parse = args => new CsvParserStream_1.CsvParserStream(new ParserOptions_1.ParserOptions(args));
exports.parseStream = (stream, options) => stream.pipe(new CsvParserStream_1.CsvParserStream(new ParserOptions_1.ParserOptions(options)));
exports.parseFile = function (location) {
let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
return fs.createReadStream(location).pipe(new CsvParserStream_1.CsvParserStream(new ParserOptions_1.ParserOptions(options)));
};
exports.parseString = (string, options) => {
const rs = new stream_1.Readable();
rs.push(string);
rs.push(null);
return rs.pipe(new CsvParserStream_1.CsvParserStream(new ParserOptions_1.ParserOptions(options)));
};
},{"./CsvParserStream":8,"./ParserOptions":9,"./types":24,"fs":84,"stream":237}],11:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Parser = void 0;
const Scanner_1 = require("./Scanner");
const RowParser_1 = require("./RowParser");
const Token_1 = require("./Token");
class Parser {
constructor(parserOptions) {
this.parserOptions = parserOptions;
this.rowParser = new RowParser_1.RowParser(this.parserOptions);
}
static removeBOM(line) {
// Catches EFBBBF (UTF-8 BOM) because the buffer-to-string
// conversion translates it to FEFF (UTF-16 BOM)
if (line && line.charCodeAt(0) === 0xfeff) {
return line.slice(1);
}
return line;
}
parse(line, hasMoreData) {
const scanner = new Scanner_1.Scanner({
line: Parser.removeBOM(line),
parserOptions: this.parserOptions,
hasMoreData
});
if (this.parserOptions.supportsComments) {
return this.parseWithComments(scanner);
}
return this.parseWithoutComments(scanner);
}
parseWithoutComments(scanner) {
const rows = [];
let shouldContinue = true;
while (shouldContinue) {
shouldContinue = this.parseRow(scanner, rows);
}
return {
line: scanner.line,
rows
};
}
parseWithComments(scanner) {
const {
parserOptions
} = this;
const rows = [];
for (let nextToken = scanner.nextCharacterToken; nextToken !== null; nextToken = scanner.nextCharacterToken) {
if (Token_1.Token.isTokenComment(nextToken, parserOptions)) {
const cursor = scanner.advancePastLine();
if (cursor === null) {
return {
line: scanner.lineFromCursor,
rows
};
}
if (!scanner.hasMoreCharacters) {
return {
line: scanner.lineFromCursor,
rows
};
}
scanner.truncateToCursor();
} else if (!this.parseRow(scanner, rows)) {
break;
}
}
return {
line: scanner.line,
rows
};
}
parseRow(scanner, rows) {
const nextToken = scanner.nextNonSpaceToken;
if (!nextToken) {
return false;
}
const row = this.rowParser.parse(scanner);
if (row === null) {
return false;
}
if (this.parserOptions.ignoreEmpty && RowParser_1.RowParser.isEmptyRow(row)) {
return true;
}
rows.push(row);
return true;
}
}
exports.Parser = Parser;
},{"./RowParser":12,"./Scanner":13,"./Token":14}],12:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.RowParser = void 0;
const column_1 = require("./column");
const Token_1 = require("./Token");
const EMPTY_STRING = '';
class RowParser {
constructor(parserOptions) {
this.parserOptions = parserOptions;
this.columnParser = new column_1.ColumnParser(parserOptions);
}
static isEmptyRow(row) {
return row.join(EMPTY_STRING).replace(/\s+/g, EMPTY_STRING) === EMPTY_STRING;
}
parse(scanner) {
const {
parserOptions
} = this;
const {
hasMoreData
} = scanner;
const currentScanner = scanner;
const columns = [];
let currentToken = this.getStartToken(currentScanner, columns);
while (currentToken) {
if (Token_1.Token.isTokenRowDelimiter(currentToken)) {
currentScanner.advancePastToken(currentToken);
// if ends with CR and there is more data, keep unparsed due to possible
// coming LF in CRLF
if (!currentScanner.hasMoreCharacters && Token_1.Token.isTokenCarriageReturn(currentToken, parserOptions) && hasMoreData) {
return null;
}
currentScanner.truncateToCursor();
return columns;
}
if (!this.shouldSkipColumnParse(currentScanner, currentToken, columns)) {
const item = this.columnParser.parse(currentScanner);
if (item === null) {
return null;
}
columns.push(item);
}
currentToken = currentScanner.nextNonSpaceToken;
}
if (!hasMoreData) {
currentScanner.truncateToCursor();
return columns;
}
return null;
}
getStartToken(scanner, columns) {
const currentToken = scanner.nextNonSpaceToken;
if (currentToken !== null && Token_1.Token.isTokenDelimiter(currentToken, this.parserOptions)) {
columns.push('');
return scanner.nextNonSpaceToken;
}
return currentToken;
}
shouldSkipColumnParse(scanner, currentToken, columns) {
const {
parserOptions
} = this;
if (Token_1.Token.isTokenDelimiter(currentToken, parserOptions)) {
scanner.advancePastToken(currentToken);
// if the delimiter is at the end of a line
const nextToken = scanner.nextCharacterToken;
if (!scanner.hasMoreCharacters || nextToken !== null && Token_1.Token.isTokenRowDelimiter(nextToken)) {
columns.push('');
return true;
}
if (nextToken !== null && Token_1.Token.isTokenDelimiter(nextToken, parserOptions)) {
columns.push('');
return true;
}
}
return false;
}
}
exports.RowParser = RowParser;
},{"./Token":14,"./column":19}],13:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Scanner = void 0;
const Token_1 = require("./Token");
const ROW_DELIMITER = /((?:\r\n)|\n|\r)/;
class Scanner {
constructor(args) {
this.cursor = 0;
this.line = args.line;
this.lineLength = this.line.length;
this.parserOptions = args.parserOptions;
this.hasMoreData = args.hasMoreData;
this.cursor = args.cursor || 0;
}
get hasMoreCharacters() {
return this.lineLength > this.cursor;
}
get nextNonSpaceToken() {
const {
lineFromCursor
} = this;
const regex = this.parserOptions.NEXT_TOKEN_REGEXP;
if (lineFromCursor.search(regex) === -1) {
return null;
}
const match = regex.exec(lineFromCursor);
if (match == null) {
return null;
}
const token = match[1];
const startCursor = this.cursor + (match.index || 0);
return new Token_1.Token({
token,
startCursor,
endCursor: startCursor + token.length - 1
});
}
get nextCharacterToken() {
const {
cursor,
lineLength
} = this;
if (lineLength <= cursor) {
return null;
}
return new Token_1.Token({
token: this.line[cursor],
startCursor: cursor,
endCursor: cursor
});
}
get lineFromCursor() {
return this.line.substr(this.cursor);
}
advancePastLine() {
const match = ROW_DELIMITER.exec(this.lineFromCursor);
if (!match) {
if (this.hasMoreData) {
return null;
}
this.cursor = this.lineLength;
return this;
}
this.cursor += (match.index || 0) + match[0].length;
return this;
}
advanceTo(cursor) {
this.cursor = cursor;
return this;
}
advanceToToken(token) {
this.cursor = token.startCursor;
return this;
}
advancePastToken(token) {
this.cursor = token.endCursor + 1;
return this;
}
truncateToCursor() {
this.line = this.lineFromCursor;
this.lineLength = this.line.length;
this.cursor = 0;
return this;
}
}
exports.Scanner = Scanner;
},{"./Token":14}],14:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Token = void 0;
class Token {
constructor(tokenArgs) {
this.token = tokenArgs.token;
this.startCursor = tokenArgs.startCursor;
this.endCursor = tokenArgs.endCursor;
}
static isTokenRowDelimiter(token) {
const content = token.token;
return content === '\r' || content === '\n' || content === '\r\n';
}
static isTokenCarriageReturn(token, parserOptions) {
return token.token === parserOptions.carriageReturn;
}
static isTokenComment(token, parserOptions) {
return parserOptions.supportsComments && !!token && token.token === parserOptions.comment;
}
static isTokenEscapeCharacter(token, parserOptions) {
return token.token === parserOptions.escapeChar;
}
static isTokenQuote(token, parserOptions) {
return token.token === parserOptions.quote;
}
static isTokenDelimiter(token, parserOptions) {
return token.token === parserOptions.delimiter;
}
}
exports.Token = Token;
},{}],15:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ColumnFormatter = void 0;
class ColumnFormatter {
constructor(parserOptions) {
if (parserOptions.trim) {
this.format = col => col.trim();
} else if (parserOptions.ltrim) {
this.format = col => col.trimLeft();
} else if (parserOptions.rtrim) {
this.format = col => col.trimRight();
} else {
this.format = col => col;
}
}
}
exports.ColumnFormatter = ColumnFormatter;
},{}],16:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ColumnParser = void 0;
const NonQuotedColumnParser_1 = require("./NonQuotedColumnParser");
const QuotedColumnParser_1 = require("./QuotedColumnParser");
const Token_1 = require("../Token");
class ColumnParser {
constructor(parserOptions) {
this.parserOptions = parserOptions;
this.quotedColumnParser = new QuotedColumnParser_1.QuotedColumnParser(parserOptions);
this.nonQuotedColumnParser = new NonQuotedColumnParser_1.NonQuotedColumnParser(parserOptions);
}
parse(scanner) {
const {
nextNonSpaceToken
} = scanner;
if (nextNonSpaceToken !== null && Token_1.Token.isTokenQuote(nextNonSpaceToken, this.parserOptions)) {
scanner.advanceToToken(nextNonSpaceToken);
return this.quotedColumnParser.parse(scanner);
}
return this.nonQuotedColumnParser.parse(scanner);
}
}
exports.ColumnParser = ColumnParser;
},{"../Token":14,"./NonQuotedColumnParser":17,"./QuotedColumnParser":18}],17:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.NonQuotedColumnParser = void 0;
const ColumnFormatter_1 = require("./ColumnFormatter");
const Token_1 = require("../Token");
class NonQuotedColumnParser {
constructor(parserOptions) {
this.parserOptions = parserOptions;
this.columnFormatter = new ColumnFormatter_1.ColumnFormatter(parserOptions);
}
parse(scanner) {
if (!scanner.hasMoreCharacters) {
return null;
}
const {
parserOptions
} = this;
const characters = [];
let nextToken = scanner.nextCharacterToken;
for (; nextToken; nextToken = scanner.nextCharacterToken) {
if (Token_1.Token.isTokenDelimiter(nextToken, parserOptions) || Token_1.Token.isTokenRowDelimiter(nextToken)) {
break;
}
characters.push(nextToken.token);
scanner.advancePastToken(nextToken);
}
return this.columnFormatter.format(characters.join(''));
}
}
exports.NonQuotedColumnParser = NonQuotedColumnParser;
},{"../Token":14,"./ColumnFormatter":15}],18:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.QuotedColumnParser = void 0;
const ColumnFormatter_1 = require("./ColumnFormatter");
const Token_1 = require("../Token");
class QuotedColumnParser {
constructor(parserOptions) {
this.parserOptions = parserOptions;
this.columnFormatter = new ColumnFormatter_1.ColumnFormatter(parserOptions);
}
parse(scanner) {
if (!scanner.hasMoreCharacters) {
return null;
}
const originalCursor = scanner.cursor;
const {
foundClosingQuote,
col
} = this.gatherDataBetweenQuotes(scanner);
if (!foundClosingQuote) {
// reset the cursor to the original
scanner.advanceTo(originalCursor);
// if we didnt find a closing quote but we potentially have more data then skip the parsing
// and return the original scanner.
if (!scanner.hasMoreData) {
throw new Error("Parse Error: missing closing: '".concat(this.parserOptions.quote || '', "' in line: at '").concat(scanner.lineFromCursor.replace(/[\r\n]/g, "\\n'"), "'"));
}
return null;
}
this.checkForMalformedColumn(scanner);
return col;
}
gatherDataBetweenQuotes(scanner) {
const {
parserOptions
} = this;
let foundStartingQuote = false;
let foundClosingQuote = false;
const characters = [];
let nextToken = scanner.nextCharacterToken;
for (; !foundClosingQuote && nextToken !== null; nextToken = scanner.nextCharacterToken) {
const isQuote = Token_1.Token.isTokenQuote(nextToken, parserOptions);
// ignore first quote
if (!foundStartingQuote && isQuote) {
foundStartingQuote = true;
} else if (foundStartingQuote) {
if (Token_1.Token.isTokenEscapeCharacter(nextToken, parserOptions)) {
// advance past the escape character so we can get the next one in line
scanner.advancePastToken(nextToken);
const tokenFollowingEscape = scanner.nextCharacterToken;
// if the character following the escape is a quote character then just add
// the quote and advance to that character
if (tokenFollowingEscape !== null && (Token_1.Token.isTokenQuote(tokenFollowingEscape, parserOptions) || Token_1.Token.isTokenEscapeCharacter(tokenFollowingEscape, parserOptions))) {
characters.push(tokenFollowingEscape.token);
nextToken = tokenFollowingEscape;
} else if (isQuote) {
// if the escape is also a quote then we found our closing quote and finish early
foundClosingQuote = true;
} else {
// other wise add the escape token to the characters since it wast escaping anything
characters.push(nextToken.token);
}
} else if (isQuote) {
// we found our closing quote!
foundClosingQuote = true;
} else {
// add the token to the characters
characters.push(nextToken.token);
}
}
scanner.advancePastToken(nextToken);
}
return {
col: this.columnFormatter.format(characters.join('')),
foundClosingQuote
};
}
checkForMalformedColumn(scanner) {
const {
parserOptions
} = this;
const {
nextNonSpaceToken
} = scanner;
if (nextNonSpaceToken) {
const isNextTokenADelimiter = Token_1.Token.isTokenDelimiter(nextNonSpaceToken, parserOptions);
const isNextTokenARowDelimiter = Token_1.Token.isTokenRowDelimiter(nextNonSpaceToken);
if (!(isNextTokenADelimiter || isNextTokenARowDelimiter)) {
// if the final quote was NOT followed by a column (,) or row(\n) delimiter then its a bad column
// tldr: only part of the column was quoted
const linePreview = scanner.lineFromCursor.substr(0, 10).replace(/[\r\n]/g, "\\n'");
throw new Error("Parse Error: expected: '".concat(parserOptions.escapedDelimiter, "' OR new line got: '").concat(nextNonSpaceToken.token, "'. at '").concat(linePreview));
}
scanner.advanceToToken(nextNonSpaceToken);
} else if (!scanner.hasMoreData) {
scanner.advancePastLine();
}
}
}
exports.QuotedColumnParser = QuotedColumnParser;
},{"../Token":14,"./ColumnFormatter":15}],19:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ColumnFormatter = exports.QuotedColumnParser = exports.NonQuotedColumnParser = exports.ColumnParser = void 0;
var ColumnParser_1 = require("./ColumnParser");
Object.defineProperty(exports, "ColumnParser", {
enumerable: true,
get: function () {
return ColumnParser_1.ColumnParser;
}
});
var NonQuotedColumnParser_1 = require("./NonQuotedColumnParser");
Object.defineProperty(exports, "NonQuotedColumnParser", {
enumerable: true,
get: function () {
return NonQuotedColumnParser_1.NonQuotedColumnParser;
}
});
var QuotedColumnParser_1 = require("./QuotedColumnParser");
Object.defineProperty(exports, "QuotedColumnParser", {
enumerable: true,
get: function () {
return QuotedColumnParser_1.QuotedColumnParser;
}
});
var ColumnFormatter_1 = require("./ColumnFormatter");
Object.defineProperty(exports, "ColumnFormatter", {
enumerable: true,
get: function () {
return ColumnFormatter_1.ColumnFormatter;
}
});
},{"./ColumnFormatter":15,"./ColumnParser":16,"./NonQuotedColumnParser":17,"./QuotedColumnParser":18}],20:[function(require,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.QuotedColumnParser = exports.NonQuotedColumnParser = exports.ColumnParser = exports.Token = exports.Scanner = exports.RowParser = exports.Parser = void 0;
var Parser_1 = require("./Parser");
Object.defineProperty(exports, "Parser", {
enumerable: true,
get: function () {
return Parser_1.Parser;
}
});
var RowParser_1 = require("./RowParser");
Object.defineProperty(exports, "RowParser", {
enumerable: true,
get: function () {
return RowParser_1.RowParser;
}
});
var Scanner_1 = require("./Scanner");
Object.defineProperty(exports, "Scanner", {
enumerable: true,
get: function () {
return Scanner_1.Scanner;
}
});
var Token_1 = require("./Token");
Object.defineProperty(exports, "Token", {
enumerable: true,
get: function () {
return Token_1.Token;
}
});
var column_1 = require("./column");
Object.defineProperty(exports, "ColumnParser", {
enumerable: true,
get: function () {
return column_1.ColumnParser;
}
});
Object.defineProperty(exports, "NonQuotedColumnParser", {
enumerable: true,
get: function () {
return column_1.NonQuotedColumnParser;
}
});
Object.defineProperty(exports, "QuotedColumnParser", {
enumerable: true,
get: function () {
return column_1.QuotedColumnParser;
}
});
},{"./Parser":11,"./RowParser":12,"./Scanner":13,"./Token":14,"./column":19}],21:[function(require,module,exports){
"use strict";
var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
return mod && mod.__esModule ? mod : {
"default": mod
};
};
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.HeaderTransformer = void 0;
const lodash_isundefined_1 = __importDefault(require("lodash.isundefined"));
const lodash_isfunction_1 = __importDefault(require("lodash.isfunction"));
const lodash_uniq_1 = __importDefault(require("lodash.uniq"));
const lodash_groupby_1 = __importDefault(require("lodash.groupby"));
class HeaderTransformer {
constructor(parserOptions) {
this.headers = null;
this.receivedHeaders = false;
this.shouldUseFirstRow = false;
this.processedFirstRow = false;
this.headersLength = 0;
this.parserOptions = parserOptions;
if (parserOptions.headers === true) {
this.shouldUseFirstRow = true;
} else if (Array.isArray(parserOptions.headers)) {
this.setHeaders(parserOptions.headers);
} else if (lodash_isfunction_1.default(parserOptions.headers)) {
this.headersTransform = parserOptions.headers;
}
}
transform(row, cb) {
if (!this.shouldMapRow(row)) {
return cb(null, {
row: null,
isValid: true
});
}
return cb(null, this.processRow(row));
}
shouldMapRow(row) {
const {
parserOptions
} = this;
if (!this.headersTransform && parserOptions.renameHeaders && !this.processedFirstRow) {
if (!this.receivedHeaders) {
throw new Error('Error renaming headers: new headers must be provided in an array');
}
this.processedFirstRow = true;
return false;
}
if (!this.receivedHeaders && Array.isArray(row)) {
if (this.headersTransform) {
this.setHeaders(this.headersTransform(row));
} else if (this.shouldUseFirstRow) {
this.setHeaders(row);
} else {
// dont do anything with the headers if we didnt receive a transform or shouldnt use the first row.
return true;
}
return false;
}
return true;
}
processRow(row) {
if (!this.headers) {
return {
row: row,
isValid: true
};
}
const {
parserOptions
} = this;
if (!parserOptions.discardUnmappedColumns && row.length > this.headersLength) {
if (!parserOptions.strictColumnHandling) {
throw new Error("Unexpected Error: column header mismatch expected: ".concat(this.headersLength, " columns got: ").concat(row.length));
}
return {
row: row,
isValid: false,
reason: "Column header mismatch expected: ".concat(this.headersLength, " columns got: ").concat(row.length)
};
}
if (parserOptions.strictColumnHandling && row.length < this.headersLength) {
return {
row: row,
isValid: false,
reason: "Column header mismatch expected: ".concat(this.headersLength, " columns got: ").concat(row.length)
};
}
return {
row: this.mapHeaders(row),
isValid: true
};
}
mapHeaders(row) {
const rowMap = {};
const {
headers,
headersLength
} = this;
for (let i = 0; i < headersLength; i += 1) {
const header = headers[i];
if (!lodash_isundefined_1.default(header)) {
const val = row[i];
// eslint-disable-next-line no-param-reassign
if (lodash_isundefined_1.default(val)) {
rowMap[header] = '';
} else {
rowMap[header] = val;
}
}
}
return rowMap;
}
setHe