Socket
Socket
Sign inDemoInstall

csv-parse

Package Overview
Dependencies
Maintainers
1
Versions
141
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

csv-parse - npm Package Compare versions

Comparing version 3.2.0 to 4.0.0

lib/es5/ResizeableBuffer.js

38

CHANGELOG.md
# Changelog
## Version 4.0.0
This is a complete rewrite based with a Buffer implementation. There are no major breaking changes but it introduces multiple minor breaking changes:
* option `rowDelimiter` is now `record_delimiter`
* option `max_limit_on_data_read` is now `max_record_size`
* drop the record event
* normalise error message as `{error type}: {error description}`
* state values are now isolated into the `info` object
* `count` is now `info.records`
* `lines` is now `info.lines`
* `empty_line_count` is now `info.empty_lines`
* `skipped_line_count` is now `info.invalid_field_length`
* `context.count` is cast function is now `context.records`
* drop support for deprecated options `auto_parse` and `auto_parse_date`
* drop emission of the `record` event
* in `raw` option, the `row` property is renamed `record`
* default value of `max_record_size` is now `0` (unlimited)
* remove the `record` event, use the `readable` event and `this.read()` instead
New features:
* new options `info`, `from_line` and `to_line`
* trim: respect `ltrim` and `rtrim` when defined
* delimiter: may be a Buffer
* delimiter: handle multiple bytes/characters
* callback: export info object as third argument
* cast: catch error in user functions
* ts: mark info as readonly with required properties
* comment_lines: count the number of commented lines with no records
* callback: pass undefined instead of null
API management
* Multiple tests have been rewritten with easier data sample
* Source code is now written in ES6 instead of CoffeeScript
* package: switch to MIT license
## Version 3.2.0

@@ -5,0 +43,0 @@

1405

lib/es5/index.js

@@ -21,821 +21,978 @@ "use strict";

// Generated by CoffeeScript 2.3.2
// # CSV Parser
// This module provides a CSV parser tested and used against large datasets. Over the year, it has been enhance and is now full of useful options.
// Please look at the [project website](https://csv.js.org/parse/) for additional information.
var Parser, StringDecoder, default_options, isObjLiteral, stream, util;
stream = require('stream');
util = require('util');
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var _require = require('string_decoder');
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
StringDecoder = _require.StringDecoder;
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
// ## Usage
// Callback approach, for ease of use:
// `parse(data, [options], callback)`
// [Node.js Stream API](http://nodejs.org/api/stream.html), for maximum of power:
// `parse([options], [callback])`
module.exports = function () {
var callback, called, chunks, data, err, options, parser;
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
if (arguments.length === 3) {
data = arguments[0];
options = arguments[1];
callback = arguments[2];
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
if (typeof callback !== 'function') {
throw Error("Invalid callback argument: ".concat(JSON.stringify(callback)));
}
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
if (!(typeof data === 'string' || Buffer.isBuffer(arguments[0]))) {
return callback(Error("Invalid data argument: ".concat(JSON.stringify(data))));
}
} else if (arguments.length === 2) {
// 1st arg is data:string or options:object
if (typeof arguments[0] === 'string' || Buffer.isBuffer(arguments[0])) {
data = arguments[0];
} else if (isObjLiteral(arguments[0])) {
options = arguments[0];
} else {
err = "Invalid first argument: ".concat(JSON.stringify(arguments[0]));
} // 2nd arg is options:object or callback:function
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
if (typeof arguments[1] === 'function') {
callback = arguments[1];
} else if (isObjLiteral(arguments[1])) {
if (options) {
err = 'Invalid arguments: got options twice as first and second arguments';
} else {
options = arguments[1];
}
} else {
err = "Invalid first argument: ".concat(JSON.stringify(arguments[1]));
}
var _require = require('stream'),
Transform = _require.Transform;
if (err) {
if (!callback) {
throw Error(err);
} else {
return callback(Error(err));
}
}
} else if (arguments.length === 1) {
if (typeof arguments[0] === 'function') {
callback = arguments[0];
} else {
options = arguments[0];
}
}
var ResizeableBuffer = require('./ResizeableBuffer');
if (options == null) {
options = {};
}
parser = new Parser(options);
if (data != null) {
process.nextTick(function () {
parser.write(data);
return parser.end();
});
}
if (callback) {
called = false;
chunks = options.objname ? {} : [];
parser.on('readable', function () {
var chunk, results;
results = [];
while (chunk = parser.read()) {
if (options.objname) {
results.push(chunks[chunk[0]] = chunk[1]);
} else {
results.push(chunks.push(chunk));
}
}
return results;
});
parser.on('error', function (err) {
called = true;
return callback(err);
});
parser.on('end', function () {
if (!called) {
return callback(null, chunks);
}
});
}
return parser;
}; // ## `Parser([options])`
// Options are documented [here](http://csv.js.org/parse/options/).
default_options = {
rowDelimiter: null,
delimiter: ',',
quote: '"',
escape: '"',
var default_options = {
// cast: false,
// cast_date: false,
columns: null,
comment: '',
objname: false,
trim: false,
ltrim: false,
rtrim: false,
cast: false,
cast_date: false,
delimiter: Buffer.from(','),
escape: Buffer.from('"'),
from: 1,
from_line: 1,
objname: undefined,
// ltrim: false,
// quote: Buffer.from('"'),
// TODO create a max_comment_size
max_record_size: 0,
relax: false,
relax_column_count: false,
// rtrim: false,
skip_empty_lines: false,
max_limit_on_data_read: 128000,
skip_lines_with_empty_values: false,
skip_lines_with_error: false
skip_lines_with_error: false,
to_line: -1,
to: -1,
trim: false
};
var cr = 13;
var nl = 10;
var space = 32;
Parser = function Parser() {
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var k, options, v;
opts.objectMode = true;
stream.Transform.call(this, opts);
options = {}; // Clone options
var Parser =
/*#__PURE__*/
function (_Transform) {
_inherits(Parser, _Transform);
for (k in opts) {
v = opts[k];
options[k] = v;
} // Default values
function Parser() {
var _this;
var opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
for (k in default_options) {
v = default_options[k];
_classCallCheck(this, Parser);
if (options[k] === void 0) {
options[k] = default_options[k];
var options = {};
for (var i in opts) {
options[i] = opts[i];
}
}
this.options = options;
options.readableObjectMode = true;
_this = _possibleConstructorReturn(this, _getPrototypeOf(Parser).call(this, options)); // Import default options
if (typeof options.rowDelimiter === 'string') {
options.rowDelimiter = [options.rowDelimiter];
}
for (var k in default_options) {
if (options[k] === undefined) {
options[k] = default_options[k];
}
} // Normalize option `cast`
if (options.quote !== void 0 && !options.quote) {
options.quote = '';
}
if (options.auto_parse != null) {
options.cast = options.auto_parse;
}
var fnCastField = null;
if (options.auto_parse_date != null) {
options.cast_date = options.auto_parse_date;
}
if (options.cast === undefined || options.cast === null || options.cast === false || options.cast === '') {
options.cast = undefined;
} else if (typeof options.cast === 'function') {
fnCastField = options.cast;
options.cast = true;
} else if (options.cast !== true) {
throw new Error('Invalid Option: cast must be true or a function');
} // Normize option `cast_date`
if (options.cast_date === true) {
options.cast_date = function (value) {
var m;
m = Date.parse(value);
if (!isNaN(m)) {
value = new Date(m);
if (options.cast_date === undefined || options.cast_date === null || options.cast_date === false || options.cast_date === '') {
options.cast_date = false;
} else if (options.cast_date === true) {
options.cast_date = function (value) {
var date = Date.parse(value);
return !isNaN(date) ? new Date(date) : value;
};
} else if (typeof options.cast_date !== 'function') {
throw new Error('Invalid Option: cast_date must be true or a function');
} // Normalize option `comment`
if (options.comment === undefined || options.comment === null || options.comment === false || options.comment === '') {
options.comment = null;
} else {
if (typeof options.comment === 'string') {
options.comment = Buffer.from(options.comment);
}
return value;
};
} // Counters
// lines = count + skipped_line_count + empty_line_count
if (!Buffer.isBuffer(options.comment)) {
throw new Error("Invalid Option: comment must be a buffer or a string, got ".concat(JSON.stringify(options.comment)));
}
} // Normalize option `delimiter`
this.lines = 0; // Number of lines encountered in the source dataset
if (typeof options.delimiter === 'string') {
options.delimiter = Buffer.from(options.delimiter);
} // Normalize option `columns`
this.count = 0; // Number of records being processed
this.skipped_line_count = 0; // Number of records skipped due to errors
var fnFirstLineToHeaders = null;
this.empty_line_count = 0; // Number of empty lines
// Constants
if (options.columns === true) {
fnFirstLineToHeaders = firstLineToHeadersDefault;
} else if (typeof options.columns === 'function') {
fnFirstLineToHeaders = options.columns;
options.columns = true;
} else if (Array.isArray(options.columns)) {
normalizeColumnsArray(options.columns);
} else if (options.columns === undefined || options.columns === null || options.columns === false) {
options.columns = false;
} else {
throw new Error("Invalid Option columns: expect an object or true, got ".concat(JSON.stringify(options.columns)));
} // Normalize option `escape`
this.is_int = /^(\-|\+)?([1-9]+[0-9]*)$/; // @is_float = /^(\-|\+)?([0-9]+(\.[0-9]+)([eE][0-9]+)?|Infinity)$/
// @is_float = /^(\-|\+)?((([0-9])|([1-9]+[0-9]*))(\.[0-9]+)([eE][0-9]+)?|Infinity)$/
this.is_float = function (value) {
return value - parseFloat(value) + 1 >= 0; // Borrowed from jquery
}; // Internal private state
if (typeof options.escape === 'string') {
options.escape = Buffer.from(options.escape);
}
if (!Buffer.isBuffer(options.escape)) {
throw new Error("Invalid Option: escape must be a buffer or a string, got ".concat(JSON.stringify(options.escape)));
} else if (options.escape.length !== 1) {
throw new Error("Invalid Option Length: escape must be one character, got ".concat(options.escape.length));
} else {
options.escape = options.escape[0];
} // Normalize option `info`
this._ = {
decoder: new StringDecoder(),
quoting: false,
commenting: false,
field: null,
nextChar: null,
closingQuote: 0,
line: [],
chunks: [],
rawBuf: '',
buf: '',
rowDelimiterMaxLength: this.options.rowDelimiter ? Math.max.apply(Math, _toConsumableArray(this.options.rowDelimiter.map(function (v) {
return v.length;
}))) : void 0,
quotedRowDelimiterMaxLength: this.options.rowDelimiter ? options.quote.length + Math.max.apply(Math, _toConsumableArray(this.options.rowDelimiter.map(function (v) {
return v.length;
}))) : void 0,
lineHasError: false,
isEnded: false
};
return this;
}; // ## Internal API
// The Parser implement a [`stream.Transform` class](https://nodejs.org/api/stream.html#stream_class_stream_transform).
// ### Events
// The library extends Node [EventEmitter][event] class and emit all the events of the Writable and Readable [Stream API](http://nodejs.org/api/stream.html).
if (options.info === undefined || options.info === null || options.info === false) {
options.info = false;
} else if (options.info !== true) {
throw new Error("Invalid Option: info must be true, got ".concat(JSON.stringify(options.info)));
} // Normalize option `quote`
util.inherits(Parser, stream.Transform); // For extra flexibility, you can get access to the original Parser class: `require('csv-parse').Parser`.
module.exports.Parser = Parser; // ### `_transform(chunk, encoding, callback)`
// * `chunk` Buffer | String
// The chunk to be transformed. Will always be a buffer unless the decodeStrings option was set to false.
// * `encoding` String
// If the chunk is a string, then this is the encoding type. (Ignore if decodeStrings chunk is a buffer.)
// * `callback` Function
// Call this function (optionally with an error argument) when you are done processing the supplied chunk.
// Implementation of the [`stream.Transform` API](https://nodejs.org/api/stream.html#stream_class_stream_transform)
if (options.quote === null || options.quote === false || options.quote === '') {
options.quote = null;
} else {
if (options.quote === undefined || options.quote === true) {
options.quote = Buffer.from('"');
} else if (typeof options.quote === 'string') {
options.quote = Buffer.from(options.quote);
}
Parser.prototype._transform = function (chunk, encoding, callback) {
var _this = this;
if (!Buffer.isBuffer(options.quote)) {
throw new Error("Invalid Option: quote must be a buffer or a string, got ".concat(JSON.stringify(options.quote)));
} else if (options.quote.length !== 1) {
throw new Error("Invalid Option Length: quote must be one character, got ".concat(options.quote.length));
} else {
options.quote = options.quote[0];
}
} // Normalize options `raw`
return setImmediate(function () {
var err;
if (chunk instanceof Buffer) {
chunk = _this._.decoder.write(chunk);
}
if (options.raw === undefined || options.raw === null || options.raw === false) {
options.raw = false;
} else if (options.raw !== true) {
throw new Error("Invalid Option: raw must be true, got ".concat(JSON.stringify(options.raw)));
} // Normalize option `record_delimiter`
err = _this.__write(chunk, false);
if (err) {
return _this.emit('error', err);
if (!options.record_delimiter) {
options.record_delimiter = [];
} else if (!Array.isArray(options.record_delimiter)) {
options.record_delimiter = [options.record_delimiter];
}
return callback();
});
};
options.record_delimiter = options.record_delimiter.map(function (rd) {
if (typeof rd === 'string') {
rd = Buffer.from(rd);
}
Parser.prototype._flush = function (callback) {
return callback(this.__flush());
};
return rd;
}); // Normalize options `trim`, `ltrim` and `rtrim`
Parser.prototype.__flush = function () {
var err;
err = this.__write(this._.decoder.end(), true);
if (options.trim === true && options.ltrim !== false) {
options.ltrim = true;
} else if (options.ltrim !== true) {
options.ltrim = false;
}
if (err) {
return err;
}
if (options.trim === true && options.rtrim !== false) {
options.rtrim = true;
} else if (options.rtrim !== true) {
options.rtrim = false;
}
if (this._.quoting) {
err = this.error("Quoted field not terminated at line ".concat(this.lines + 1));
return err;
_this.info = {
comment_lines: 0,
empty_lines: 0,
invalid_field_length: 0,
lines: 1,
records: 0
};
_this.options = options;
_this.state = {
castField: fnCastField,
commenting: false,
enabled: options.from_line === 1,
escaping: false,
escapeIsQuote: options.escape === options.quote,
expectedRecordLength: options.columns === null ? 0 : options.columns.length,
field: new ResizeableBuffer(20),
firstLineToHeaders: fnFirstLineToHeaders,
info: Object.assign({}, _this.info),
previousBuf: undefined,
quoting: false,
stop: false,
rawBuffer: new ResizeableBuffer(100),
record: [],
recordHasError: false,
record_length: 0,
recordDelimiterMaxLength: options.record_delimiter.length === 0 ? 2 : Math.max.apply(Math, _toConsumableArray(options.record_delimiter.map(function (v) {
return v.length;
}))),
trimChars: [Buffer.from(' ')[0], Buffer.from('\t')[0]],
wasQuoting: false,
wasRowDelimiter: false
};
return _this;
}
if (this._.line.length > 0) {
return this.__push(this._.line);
}
};
_createClass(Parser, [{
key: "_transform",
value: function _transform(buf, encoding, callback) {
if (this.state.stop === true) {
return;
}
Parser.prototype.__push = function (line) {
var call_column_udf, columnName, columns, err, field, i, j, len, lineAsColumns, record;
var err = this.__parse(buf, false);
if (this._.isEnded) {
return;
}
if (err !== undefined) {
this.state.stop = true;
}
if (this.options.skip_lines_with_empty_values && line.join('').trim() === '') {
return;
}
callback(err);
}
}, {
key: "_flush",
value: function _flush(callback) {
if (this.state.stop === true) {
return;
}
record = null;
var err = this.__parse(undefined, true);
if (this.options.columns === true) {
this.options.columns = line;
return;
} else if (typeof this.options.columns === 'function') {
call_column_udf = function call_column_udf(fn, line) {
var columns, err;
callback(err);
}
}, {
key: "__parse",
value: function __parse(nextBuf, end) {
var _this$options = this.options,
comment = _this$options.comment,
escape = _this$options.escape,
from = _this$options.from,
from_line = _this$options.from_line,
info = _this$options.info,
ltrim = _this$options.ltrim,
max_record_size = _this$options.max_record_size,
quote = _this$options.quote,
raw = _this$options.raw,
relax = _this$options.relax,
rtrim = _this$options.rtrim,
skip_empty_lines = _this$options.skip_empty_lines,
to = _this$options.to,
to_line = _this$options.to_line;
var record_delimiter = this.options.record_delimiter;
var _this$state = this.state,
previousBuf = _this$state.previousBuf,
rawBuffer = _this$state.rawBuffer,
escapeIsQuote = _this$state.escapeIsQuote,
trimChars = _this$state.trimChars;
var buf;
try {
columns = fn.call(null, line);
return [null, columns];
} catch (error) {
err = error;
return [err];
if (previousBuf === undefined && nextBuf !== undefined) {
buf = nextBuf;
} else if (previousBuf !== undefined && nextBuf === undefined) {
buf = previousBuf;
} else {
buf = Buffer.concat([previousBuf, nextBuf]);
}
};
var _call_column_udf = call_column_udf(this.options.columns, line);
var bufLen = buf.length;
var pos; // let escaping = this.
var _call_column_udf2 = _slicedToArray(_call_column_udf, 2);
for (pos = 0; pos < bufLen; pos++) {
// Ensure we get enough space to look ahead
// There should be a way to move this out of the loop
if (this.__needMoreData(pos, bufLen, end)) {
break;
}
err = _call_column_udf2[0];
columns = _call_column_udf2[1];
if (this.state.wasRowDelimiter === true) {
this.info.lines++;
if (err) {
return err;
}
if (info === true && this.state.record.length === 0 && this.state.field.length === 0 && this.state.wasQuoting === false) {
this.state.info = Object.assign({}, this.info);
}
this.options.columns = columns;
return;
}
this.state.wasRowDelimiter = false;
}
if (!this._.line_length && line.length > 0) {
this._.line_length = this.options.columns ? this.options.columns.length : line.length;
} // Dont check column count on empty lines
if (to_line !== -1 && this.info.lines > to_line) {
this.state.stop = true;
this.push(null);
return;
} // Auto discovery of record_delimiter, unix, mac and windows supported
if (line.length === 1 && line[0] === '') {
this.empty_line_count++;
} else if (line.length !== this._.line_length) {
// Dont check column count with relax_column_count
if (this.options.relax_column_count) {
this.count++;
this.skipped_line_count++;
} else if (this.options.columns != null) {
// Suggest: Inconsistent header and column numbers: header is 1 and number of columns is 1 on line 1
err = this.error("Number of columns on line ".concat(this.lines, " does not match header"));
return err;
} else {
err = this.error("Number of columns is inconsistent on line ".concat(this.lines));
return err;
}
} else {
this.count++;
}
if (this.state.quoting === false && record_delimiter.length === 0) {
var recordDelimiterCount = this.__autoDiscoverRowDelimiter(buf, pos);
if (this.options.columns != null) {
lineAsColumns = {};
if (recordDelimiterCount) {
record_delimiter = this.options.record_delimiter;
}
}
for (i = j = 0, len = line.length; j < len; i = ++j) {
field = line[i];
columnName = this.options.columns[i];
var chr = buf[pos];
if (columnName === void 0 || columnName === null || columnName === false) {
continue;
}
if (raw === true) {
rawBuffer.append(chr);
}
if (typeof columnName !== 'string') {
throw Error("Invalid column name ".concat(JSON.stringify(columnName)));
}
if ((chr === cr || chr === nl) && this.state.wasRowDelimiter === false) {
this.state.wasRowDelimiter = true;
} // Previous char was a valid escape char
// treat the current char as a regular char
lineAsColumns[columnName] = field;
}
if (this.options.objname) {
record = [lineAsColumns[this.options.objname], lineAsColumns];
} else {
record = lineAsColumns;
}
} else {
record = line;
}
if (this.state.escaping === true) {
this.state.escaping = false;
} else {
// Escape is only active inside quoted fields
if (this.state.quoting === true && chr === escape && pos + 1 < bufLen) {
// We are quoting, the char is an escape chr and there is a chr to escape
if (escapeIsQuote) {
if (buf[pos + 1] === quote) {
this.state.escaping = true;
continue;
}
} else {
this.state.escaping = true;
continue;
}
} // Not currently escaping and chr is a quote
// TODO: need to compare bytes instead of single char
if (this.count < this.options.from) {
return;
}
if (this.options.raw) {
this.push({
raw: this._.rawBuf,
row: record
});
this._.rawBuf = '';
} else {
this.push(record);
}
if (this.state.commenting === false && chr === quote) {
if (this.state.quoting === true) {
var nextChr = buf[pos + 1];
if (this.listenerCount('record')) {
this.emit('record', record);
} // When to is reached set ignore any future calls
var isNextChrTrimable = rtrim && this.__isCharTrimable(nextChr); // const isNextChrComment = nextChr === comment
if (this.count >= this.options.to) {
this._.isEnded = true;
return this.push(null);
}
var isNextChrComment = comment !== null && this.__compareBytes(comment, buf, pos + 1, nextChr);
return null;
};
var isNextChrDelimiter = this.__isDelimiter(nextChr, buf, pos + 1);
Parser.prototype.__write = function (chars, end) {
var _this2 = this;
var isNextChrRowDelimiter = record_delimiter.length === 0 ? this.__autoDiscoverRowDelimiter(buf, pos + 1) : this.__isRecordDelimiter(nextChr, buf, pos + 1); // Escape a quote
// Treat next char as a regular character
// TODO: need to compare bytes instead of single char
var areNextCharsDelimiter, areNextCharsRowDelimiters, cast, char, err, escapeIsQuote, i, isDelimiter, isEscape, isNextCharAComment, isNextCharTrimable, isQuote, isRowDelimiter, isRowDelimiterLength, is_float, is_int, l, ltrim, nextCharPos, numOfCharLeft, ref, ref1, ref2, ref3, ref4, ref5, ref6, remainingBuffer, rowDelimiter, rtrim, wasCommenting;
if (chr === escape && nextChr === quote) {
pos++;
} else if (!nextChr || isNextChrDelimiter || isNextChrRowDelimiter || isNextChrComment || isNextChrTrimable) {
this.state.quoting = false;
this.state.wasQuoting = true;
continue;
} else if (relax === false) {
var err = this.__error("Invalid Closing Quote: got \"".concat(String.fromCharCode(nextChr), "\" at line ").concat(this.info.lines, " instead of delimiter, row delimiter, trimable character (if activated) or comment"));
is_int = function is_int(value) {
if (typeof _this2.is_int === 'function') {
return _this2.is_int(value);
} else {
return _this2.is_int.test(value);
}
};
if (err !== undefined) return err;
} else {
this.state.quoting = false;
this.state.wasQuoting = true; // continue
is_float = function is_float(value) {
if (typeof _this2.is_float === 'function') {
return _this2.is_float(value);
} else {
return _this2.is_float.test(value);
}
};
this.state.field.prepend(quote);
}
} else {
if (this.state.field.length !== 0) {
// In relax mode, treat opening quote preceded by chrs as regular
if (relax === false) {
var _err = this.__error("Invalid opening quote at line ".concat(this.info.lines));
cast = function cast(value) {
var context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
if (_err !== undefined) return _err;
}
} else {
this.state.quoting = true;
continue;
}
}
}
if (!_this2.options.cast) {
return value;
}
if (this.state.quoting === false) {
var recordDelimiterLength = this.__isRecordDelimiter(chr, buf, pos);
if (context.quoting == null) {
context.quoting = !!_this2._.closingQuote;
}
if (recordDelimiterLength !== 0) {
// Do not emit comments which take a full line
var skipCommentLine = this.state.commenting && this.state.wasQuoting === false && this.state.record.length === 0 && this.state.field.length === 0;
if (context.lines == null) {
context.lines = _this2.lines;
}
if (skipCommentLine) {
this.info.comment_lines++; // Skip full comment line
} else {
// Skip if line is empty and skip_empty_lines activated
if (skip_empty_lines === true && this.state.wasQuoting === false && this.state.record.length === 0 && this.state.field.length === 0) {
this.info.empty_lines++;
continue;
} // Activate records emition if above from_line
if (context.count == null) {
context.count = _this2.count;
}
if (context.index == null) {
context.index = _this2._.line.length;
} // context.header ?= if @options.column and @lines is 1 and @count is 0 then true else false
if (this.state.enabled === false && this.info.lines + (this.state.wasRowDelimiter === true ? 1 : 0) >= from_line) {
this.state.enabled = true;
this.__resetField();
if (context.header == null) {
context.header = _this2.options.columns === true;
}
this.__resetRow();
if (context.column == null) {
context.column = Array.isArray(_this2.options.columns) ? _this2.options.columns[context.index] : context.index;
}
continue;
} else {
var errField = this.__onField();
if (typeof _this2.options.cast === 'function') {
return _this2.options.cast(value, context);
}
if (errField !== undefined) return errField;
if (is_int(value)) {
value = parseInt(value);
} else if (is_float(value)) {
value = parseFloat(value);
} else if (_this2.options.cast_date) {
value = _this2.options.cast_date(value, context);
}
var errRecord = this.__onRow();
return value;
};
if (errRecord !== undefined) return errRecord;
}
ltrim = this.options.trim || this.options.ltrim;
rtrim = this.options.trim || this.options.rtrim;
escapeIsQuote = this.options.escape === this.options.quote;
chars = this._.buf + chars;
l = chars.length;
i = 0;
if (to !== -1 && this.info.records >= to) {
this.state.stop = true;
this.push(null);
return;
}
}
if (this.lines === 0 && 0xFEFF === chars.charCodeAt(0)) {
// Strip BOM header
i++;
}
this.state.commenting = false;
pos += recordDelimiterLength - 1;
continue;
}
while (i < l) {
// Ensure we get enough space to look ahead
if (!end) {
numOfCharLeft = l - i;
remainingBuffer = chars.substr(i, numOfCharLeft); // Skip if row delimiter larger than auto discovered values
// Skip if the remaining buffer smaller than comment
// Skip if the remaining buffer smaller than row delimiter
// Skip if the remaining buffer can be row delimiter following the closing quote
// Skip if the remaining buffer can be delimiter
// Skip if the remaining buffer can be escape sequence
if (this.state.commenting) {
continue;
}
if (!this.options.rowDelimiter && i + 3 > l || !this._.commenting && numOfCharLeft < this.options.comment.length || this.options.rowDelimiter && numOfCharLeft < this._.rowDelimiterMaxLength || this._.quoting && this.options.rowDelimiter && numOfCharLeft < this._.quotedRowDelimiterMaxLength || numOfCharLeft <= this.options.delimiter.length && this.options.delimiter.substr(0, numOfCharLeft) === remainingBuffer || numOfCharLeft <= this.options.escape.length && this.options.escape.substr(0, numOfCharLeft) === remainingBuffer) {
break;
}
}
var commentCount = comment === null ? 0 : this.__compareBytes(comment, buf, pos, chr);
char = this._.nextChar ? this._.nextChar : chars.charAt(i);
this._.nextChar = l > i + 1 ? chars.charAt(i + 1) : null;
if (commentCount !== 0) {
this.state.commenting = true;
continue;
}
if (this.options.raw) {
this._.rawBuf += char;
} // Auto discovery of rowDelimiter, unix, mac and windows supported
var delimiterLength = this.__isDelimiter(chr, buf, pos);
if (delimiterLength !== 0) {
var _errField = this.__onField();
if (this.options.rowDelimiter == null) {
nextCharPos = i;
rowDelimiter = null; // First empty line
if (_errField !== undefined) return _errField;
pos += delimiterLength - 1;
continue;
}
}
}
if (!this._.quoting && (char === '\n' || char === '\r')) {
rowDelimiter = char;
nextCharPos += 1;
} else if (this._.quoting && char === this.options.quote && ((ref = this._.nextChar) === '\n' || ref === '\r')) {
rowDelimiter = this._.nextChar;
nextCharPos += 2;
}
if (this.state.commenting === false) {
if (max_record_size !== 0 && this.state.record_length + this.state.field.length > max_record_size) {
var _err2 = this.__error("Max Record Size: record exceed the maximum number of tolerated bytes of ".concat(max_record_size, " on line ").concat(this.info.lines));
if (rowDelimiter) {
if (rowDelimiter === '\r' && chars.charAt(nextCharPos) === '\n') {
rowDelimiter += '\n';
if (_err2 !== undefined) return _err2;
}
}
this.options.rowDelimiter = [rowDelimiter];
this._.rowDelimiterMaxLength = rowDelimiter.length;
var lappend = ltrim === false || this.state.quoting === true || this.state.field.length !== 0 || !this.__isCharTrimable(chr); // rtrim in non quoting is handle in __onField
var rappend = rtrim === false || this.state.wasQuoting === false;
if (lappend === true && rappend === true) {
this.state.field.append(chr);
} else if (rtrim === true && !this.__isCharTrimable(chr)) {
var _err3 = this.__error("Invalid Closing Quote: found non trimable byte after quote at line ".concat(this.info.lines));
if (_err3 !== undefined) return _err3;
}
}
} // Parse that damn char
// Note, shouldn't we have sth like chars.substr(i, @options.escape.length)
if (end === true) {
if (this.state.quoting === true) {
var _err4 = this.__error("Invalid Closing Quote: quote is not closed at line ".concat(this.info.lines));
if (!this._.commenting && char === this.options.escape) {
// Make sure the escape is really here for escaping:
// If escape is same as quote, and escape is first char of a field
// and it's not quoted, then it is a quote
// Next char should be an escape or a quote
isEscape = this._.nextChar === this.options.escape;
isQuote = this._.nextChar === this.options.quote;
if (_err4 !== undefined) return _err4;
} else {
// Skip last line if it has no characters
if (this.state.wasQuoting === true || this.state.record.length !== 0 || this.state.field.length !== 0) {
var _errField2 = this.__onField();
if (!(escapeIsQuote && !this._.field && !this._.quoting) && (isEscape || isQuote)) {
i++;
char = this._.nextChar;
this._.nextChar = chars.charAt(i + 1);
if (_errField2 !== undefined) return _errField2;
if (this._.field == null) {
this._.field = '';
}
var _errRecord = this.__onRow();
this._.field += char; // Since we're skipping the next one, better add it now if in raw mode.
if (this.options.raw) {
this._.rawBuf += char;
if (_errRecord !== undefined) return _errRecord;
} else if (this.state.wasRowDelimiter === true) {
this.info.empty_lines++;
} else if (this.state.commenting === true) {
this.info.comment_lines++;
}
}
} else {
this.state.previousBuf = buf.slice(pos);
}
i++;
continue;
if (this.state.wasRowDelimiter === true) {
this.info.lines++;
this.state.wasRowDelimiter = false;
}
} // Char match quote
}
}, {
key: "__isCharTrimable",
value: function __isCharTrimable(chr) {
return chr === space || chr === cr || chr === nl;
}
}, {
key: "__onRow",
value: function __onRow() {
var _this$options2 = this.options,
columns = _this$options2.columns,
info = _this$options2.info,
from = _this$options2.from,
relax_column_count = _this$options2.relax_column_count,
raw = _this$options2.raw,
skip_lines_with_empty_values = _this$options2.skip_lines_with_empty_values;
var _this$state2 = this.state,
enabled = _this$state2.enabled,
record = _this$state2.record; // Validate column length
if (!this._.commenting && char === this.options.quote) {
if (this._.acceptOnlyEmptyChars && char !== ' ' && char !== '\t') {
return this.error('Only trimable characters are accepted after quotes');
if (columns === true && this.state.firstLineToHeaders) {
return this.__firstLineToColumns(record);
}
if (this._.quoting) {
// Make sure a closing quote is followed by a delimiter
// If we have a next character and
// it isnt a rowDelimiter and
// it isnt an column delimiter and
// it isnt the begining of a comment
// Otherwise, if this is not "relax" mode, throw an error
isNextCharTrimable = rtrim && ((ref1 = this._.nextChar) === ' ' || ref1 === '\t');
areNextCharsRowDelimiters = this.options.rowDelimiter && this.options.rowDelimiter.some(function (rd) {
return chars.substr(i + 1, rd.length) === rd;
});
areNextCharsDelimiter = chars.substr(i + 1, this.options.delimiter.length) === this.options.delimiter;
isNextCharAComment = this._.nextChar === this.options.comment;
var recordLength = record.length;
if (this._.nextChar != null && !isNextCharTrimable && !areNextCharsRowDelimiters && !areNextCharsDelimiter && !isNextCharAComment) {
if (this.options.relax) {
this._.quoting = false;
if (columns === false && this.info.records === 0) {
this.state.expectedRecordLength = recordLength;
} else if (enabled === true) {
if (recordLength !== this.state.expectedRecordLength) {
if (relax_column_count === true) {
this.info.invalid_field_length++;
} else {
if (columns === false) {
var err = this.__error("Invalid Record Length: expect ".concat(this.state.expectedRecordLength, ", got ").concat(recordLength, " on line ").concat(this.info.lines));
if (this._.field) {
this._.field = "".concat(this.options.quote).concat(this._.field);
if (err !== undefined) return err;
} else {
var _err5 = this.__error("Invalid Record Length: header length is ".concat(columns.length, ", got ").concat(recordLength, " on line ").concat(this.info.lines));
if (_err5 !== undefined) return _err5;
}
} else {
if (err = this.error("Invalid closing quote at line ".concat(this.lines + 1, "; found ").concat(JSON.stringify(this._.nextChar), " instead of delimiter ").concat(JSON.stringify(this.options.delimiter)))) {
return err;
}
}
} else if (this._.nextChar != null && isNextCharTrimable) {
i++;
this._.quoting = false;
this._.closingQuote = 1;
this._.acceptOnlyEmptyChars = true;
continue;
} else {
i++;
this._.quoting = false;
this._.closingQuote = 1;
}
}
if (end && i === l) {
this._.line.push(cast(this._.field || ''));
if (enabled === false) {
return this.__resetRow();
}
this._.field = null;
}
if (skip_lines_with_empty_values === true) {
if (record.map(function (field) {
return field.trim();
}).join('') === '') {
this.__resetRow();
continue;
return;
}
} else if (!this._.field) {
this._.quoting = true;
i++;
continue;
} else if (this._.field != null && !this.options.relax) {
if (err = this.error("Invalid opening quote at line ".concat(this.lines + 1))) {
return err;
}
}
} // Otherwise, treat quote as a regular character
if (this.state.recordHasError === true) {
this.__resetRow();
isRowDelimiter = this.options.rowDelimiter && this.options.rowDelimiter.some(function (rd) {
return chars.substr(i, rd.length) === rd;
});
this.state.recordHasError = false;
return;
}
if (isRowDelimiter || end && i === l - 1) {
this.lines++;
} // Set the commenting flag
this.info.records++;
if (from === 1 || this.info.records >= from) {
if (columns !== false) {
var obj = {}; // Transform record array to an object
wasCommenting = false;
for (var i in record) {
if (columns[i].disabled) continue;
obj[columns[i].name] = record[i];
}
if (!this._.commenting && !this._.quoting && this.options.comment && chars.substr(i, this.options.comment.length) === this.options.comment) {
this._.commenting = true;
} else if (this._.commenting && isRowDelimiter) {
wasCommenting = true;
this._.commenting = false;
}
var objname = this.options.objname;
isDelimiter = chars.substr(i, this.options.delimiter.length) === this.options.delimiter;
if (this._.acceptOnlyEmptyChars) {
if (isDelimiter || isRowDelimiter) {
this._.acceptOnlyEmptyChars = false;
} else {
if (char === ' ' || char === '\t') {
i++;
continue;
if (objname === undefined) {
if (raw === true || info === true) {
this.push(Object.assign({
record: obj
}, raw === true ? {
raw: this.state.rawBuffer.toString()
} : {}, info === true ? {
info: this.state.info
} : {}));
} else {
this.push(obj);
}
} else {
if (raw === true || info === true) {
this.push(Object.assign({
record: [obj[objname], obj]
}, raw === true ? {
raw: this.state.rawBuffer.toString()
} : {}, info === true ? {
info: this.state.info
} : {}));
} else {
this.push([obj[objname], obj]);
}
}
} else {
return this.error('Only trimable characters are accepted after quotes');
if (raw === true || info === true) {
this.push(Object.assign({
record: record
}, raw === true ? {
raw: this.state.rawBuffer.toString()
} : {}, info === true ? {
info: this.state.info
} : {}));
} else {
this.push(record);
}
}
}
this.__resetRow();
}
}, {
key: "__firstLineToColumns",
value: function __firstLineToColumns(record) {
try {
var headers = this.state.firstLineToHeaders.call(null, record);
if (!this._.commenting && !this._.quoting && (isDelimiter || isRowDelimiter)) {
if (isRowDelimiter) {
isRowDelimiterLength = this.options.rowDelimiter.filter(function (rd) {
return chars.substr(i, rd.length) === rd;
})[0].length;
} // Empty lines
if (!Array.isArray(headers)) {
return this.__error("Invalid Header Mapping: expect an array, got ".concat(JSON.stringify(headers)));
}
normalizeColumnsArray(headers);
this.state.expectedRecordLength = headers.length;
this.options.columns = headers;
if (isRowDelimiter && this._.line.length === 0 && this._.field == null) {
if (wasCommenting || this.options.skip_empty_lines) {
i += isRowDelimiterLength;
this._.nextChar = chars.charAt(i);
continue;
}
this.__resetRow();
return;
} catch (err) {
return err;
}
}
}, {
key: "__resetRow",
value: function __resetRow() {
var info = this.options.info;
if (rtrim) {
if (!this._.closingQuote) {
this._.field = (ref2 = this._.field) != null ? ref2.trimRight() : void 0;
}
if (this.options.raw === true) {
this.state.rawBuffer.reset();
}
this._.line.push(cast(this._.field || ''));
this.state.record = [];
this.state.record_length = 0;
}
}, {
key: "__onField",
value: function __onField() {
var _this$options3 = this.options,
cast = _this$options3.cast,
rtrim = _this$options3.rtrim;
var _this$state3 = this.state,
enabled = _this$state3.enabled,
wasQuoting = _this$state3.wasQuoting; // Deal with from_to options
this._.closingQuote = 0;
this._.field = null; // End of field
// Ensure that the delimiter doesnt match as well the rowDelimiter
if (this.options.columns !== true && enabled === false) {
return this.__resetField();
}
if (isDelimiter && !isRowDelimiter) {
i += this.options.delimiter.length;
this._.nextChar = chars.charAt(i);
var field = this.state.field.toString();
if (end && !this._.nextChar) {
isRowDelimiter = true;
this._.line.push('');
}
if (rtrim === true && wasQuoting === false) {
field = field.trimRight();
}
if (isRowDelimiter) {
// End of record
if (!this._.lineHasError) {
err = this.__push(this._.line);
if (cast === true) {
var _this$__cast = this.__cast(field),
_this$__cast2 = _slicedToArray(_this$__cast, 2),
err = _this$__cast2[0],
f = _this$__cast2[1];
if (err) {
return err;
}
}
if (err !== undefined) return err;
field = f;
}
if (this._.lineHasError) {
this._.lineHasError = false;
} // Some cleanup for the next record
this.state.record.push(field);
this.state.record_length += field.length;
this.__resetField();
}
}, {
key: "__resetField",
value: function __resetField() {
this.state.field.reset();
this.state.wasQuoting = false;
}
}, {
key: "__cast",
value: function __cast(field) {
var context = {
column: Array.isArray(this.options.columns) === true ? this.options.columns[this.state.record.length] : this.state.record.length,
empty_lines: this.info.empty_lines,
header: this.options.columns === true,
index: this.state.record.length,
invalid_field_length: this.info.invalid_field_length,
quoting: this.state.wasQuoting,
lines: this.info.lines,
records: this.info.records
};
this._.line = [];
i += isRowDelimiterLength;
this._.nextChar = chars.charAt(i);
continue;
if (this.state.castField !== null) {
try {
return [undefined, this.state.castField.call(null, field, context)];
} catch (err) {
return [err];
}
}
} else if (!this._.commenting && !this._.quoting && (char === ' ' || char === '\t')) {
if (this._.field == null) {
// Left trim unless we are quoting or field already filled
this._.field = '';
}
if (!(ltrim && !this._.field)) {
this._.field += char;
if (this.__isInt(field) === true) {
return [undefined, parseInt(field)];
} else if (this.__isFloat(field)) {
return [undefined, parseFloat(field)];
} else if (this.options.cast_date !== false) {
return [undefined, this.options.cast_date.call(null, field, context)];
}
i++;
} else if (!this._.commenting) {
if (this._.field == null) {
this._.field = '';
return [undefined, field];
}
}, {
key: "__isInt",
value: function __isInt(value) {
return /^(\-|\+)?([1-9]+[0-9]*)$/.test(value);
}
}, {
key: "__isFloat",
value: function __isFloat(value) {
return value - parseFloat(value) + 1 >= 0; // Borrowed from jquery
}
}, {
key: "__compareBytes",
value: function __compareBytes(sourceBuf, targetBuf, pos, firtByte) {
if (sourceBuf[0] !== firtByte) return 0;
var sourceLength = sourceBuf.length;
for (var i = 1; i < sourceLength; i++) {
if (sourceBuf[i] !== targetBuf[pos + i]) return 0;
}
this._.field += char;
i++;
} else {
i++;
return sourceLength;
}
}, {
key: "__needMoreData",
value: function __needMoreData(i, bufLen, end) {
if (end) {
return false;
}
if (!this._.commenting && ((ref3 = this._.field) != null ? ref3.length : void 0) > this.options.max_limit_on_data_read) {
return Error("Field exceeds max_limit_on_data_read: maximum value is ".concat(this.options.max_limit_on_data_read));
var _this$options4 = this.options,
comment = _this$options4.comment,
delimiter = _this$options4.delimiter,
escape = _this$options4.escape;
var _this$state4 = this.state,
quoting = _this$state4.quoting,
recordDelimiterMaxLength = _this$state4.recordDelimiterMaxLength;
var numOfCharLeft = bufLen - i - 1;
var requiredLength = Math.max( // Skip if the remaining buffer smaller than comment
comment ? comment.length : 0, // Skip if the remaining buffer smaller than row delimiter
recordDelimiterMaxLength, // Skip if the remaining buffer can be row delimiter following the closing quote
// 1 is for quote.length
quoting ? 1 + recordDelimiterMaxLength : 0, // Skip if the remaining buffer can be delimiter
delimiter.length, // Skip if the remaining buffer can be escape sequence
// 1 is for escape.length
1);
return numOfCharLeft < requiredLength;
}
}, {
key: "__isDelimiter",
value: function __isDelimiter(chr, buf, pos) {
var delimiter = this.options.delimiter;
var delLength = delimiter.length;
if (delimiter[0] !== chr) return 0;
if (!this._.commenting && ((ref4 = this._.line) != null ? ref4.length : void 0) > this.options.max_limit_on_data_read) {
return Error("Row delimiter not found in the file ".concat(JSON.stringify(this.options.rowDelimiter)));
for (var i = 1; i < delLength; i++) {
if (delimiter[i] !== buf[pos + i]) return 0;
}
return delimiter.length;
}
} // Flush remaining fields and lines
}, {
key: "__isRecordDelimiter",
value: function __isRecordDelimiter(chr, buf, pos) {
var record_delimiter = this.options.record_delimiter;
var recordDelimiterLength = record_delimiter.length;
loop1: for (var i = 0; i < recordDelimiterLength; i++) {
var rd = record_delimiter[i];
var rdLength = rd.length;
if (end) {
if (l === 0) {
this.lines++;
}
if (rd[0] !== chr) {
continue;
}
if (this._.field != null) {
if (rtrim) {
if (!this._.closingQuote) {
this._.field = (ref5 = this._.field) != null ? ref5.trimRight() : void 0;
for (var j = 1; j < rdLength; j++) {
if (rd[j] !== buf[pos + j]) {
continue loop1;
}
}
return rd.length;
}
this._.line.push(cast(this._.field || ''));
this._.field = null;
return 0;
}
}, {
key: "__autoDiscoverRowDelimiter",
value: function __autoDiscoverRowDelimiter(buf, pos) {
var chr = buf[pos];
if (((ref6 = this._.field) != null ? ref6.length : void 0) > this.options.max_limit_on_data_read) {
return Error("Delimiter not found in the file ".concat(JSON.stringify(this.options.delimiter)));
if (chr === cr) {
if (buf[pos + 1] === nl) {
this.options.record_delimiter.push(Buffer.from('\r\n'));
this.state.recordDelimiterMaxLength = 2;
return 2;
} else {
this.options.record_delimiter.push(Buffer.from('\r'));
this.state.recordDelimiterMaxLength = 1;
return 1;
}
} else if (chr === nl) {
this.options.record_delimiter.push(Buffer.from('\n'));
this.state.recordDelimiterMaxLength = 1;
return 1;
}
return 0;
}
}, {
key: "__error",
value: function __error(msg) {
var skip_lines_with_error = this.options.skip_lines_with_error;
var err = new Error(msg);
if (this._.line.length > this.options.max_limit_on_data_read) {
return Error("Row delimiter not found in the file ".concat(JSON.stringify(this.options.rowDelimiter)));
if (skip_lines_with_error) {
this.state.recordHasError = true;
this.emit('skip', err);
return undefined;
} else {
return err;
}
}
} // Store un-parsed chars for next call
}]);
return Parser;
}(Transform);
this._.buf = chars.substr(i);
return null;
};
var parse = function parse() {
var data, options, callback;
Parser.prototype.error = function (msg) {
var err;
err = Error(msg);
for (var i in arguments) {
var argument = arguments[i];
if (!this.options.skip_lines_with_error) {
return err;
} else {
if (!this._.lineHasError) {
this._.lineHasError = true;
this.emit('skip', err);
var type = _typeof(argument);
if (data === undefined && (typeof argument === 'string' || Buffer.isBuffer(argument))) {
data = argument;
} else if (options === undefined && isObject(argument)) {
options = argument;
} else if (callback === undefined && type === 'function') {
callback = argument;
} else {
throw new Error("Invalid argument: got ".concat(JSON.stringify(argument), " at index ").concat(i));
}
}
return null;
}; // ## Utils
var parser = new Parser(options);
if (callback) {
var records = options === undefined || options.objname === undefined ? [] : {};
parser.on('readable', function () {
var record;
isObjLiteral = function isObjLiteral(_obj) {
var _test;
while (record = this.read()) {
if (options === undefined || options.objname === undefined) {
records.push(record);
} else {
records[record[0]] = record[1];
}
}
});
parser.on('error', function (err) {
callback(err, undefined, parser.info);
});
parser.on('end', function () {
callback(undefined, records, parser.info);
});
}
_test = _obj;
if (data !== undefined) {
parser.write(data);
parser.end();
}
if (_typeof(_obj) !== 'object' || _obj === null || Array.isArray(_obj)) {
return false;
} else {
return function () {
while (!false) {
if (Object.getPrototypeOf(_test = Object.getPrototypeOf(_test)) === null) {
break;
}
return parser;
};
parse.Parser = Parser;
module.exports = parse;
var isObject = function isObject(obj) {
return _typeof(obj) === 'object' && obj !== null && !Array.isArray(obj);
};
var firstLineToHeadersDefault = function firstLineToHeadersDefault(record) {
return record.map(function (field) {
return {
header: field,
name: field
};
});
};
var normalizeColumnsArray = function normalizeColumnsArray(columns) {
for (var i = 0; i < columns.length; i++) {
var column = columns[i];
if (column === undefined || column === null || column === false) {
columns[i] = {
disabled: true
};
} else if (typeof column === 'string') {
columns[i] = {
name: column
};
} else if (isObject(column)) {
if (typeof column.name !== 'string') {
throw new Error("Invalid Option columns: property \"name\" is required at position ".concat(i));
}
return Object.getPrototypeOf(_obj === _test);
}();
columns[i] = column;
} else {
throw new Error("Invalid Option columns: expect a string or an object, got ".concat(JSON.stringify(column), " at position ").concat(i));
}
}
};
"use strict";
// Generated by CoffeeScript 2.3.2
// # CSV Parse Sync
// Provides a synchronous alternative to the CSV parser.
// ## Usage
// `const records = parse(data, [options]`
var StringDecoder, parse;
var parse = require('.');
var _require = require('string_decoder');
StringDecoder = _require.StringDecoder;
parse = require('./index');
module.exports = function (data) {
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var chunks, decoder, err, parser;
chunks = options.objname ? {} : [];
if (data instanceof Buffer) {
decoder = new StringDecoder();
data = decoder.write(data);
if (typeof data === 'string') {
data = Buffer.from(data);
}
parser = new parse.Parser(options);
var records = options && options.objname ? {} : [];
var parser = new parse.Parser(options);
parser.push = function (chunk) {
if (options.objname) {
return chunks[chunk[0]] = chunk[1];
} else {
return chunks.push(chunk);
parser.push = function (record) {
if (options.objname === undefined) records.push(record);else {
records[record[0]] = record[1];
}
};
err = parser.__write(data, false);
var err1 = parser.__parse(data, false);
if (err) {
throw err;
}
if (err1 !== undefined) throw err1;
if (data instanceof Buffer) {
err = parser.__write(data.end(), true);
var err2 = parser.__parse(undefined, true);
if (err) {
throw err;
}
}
err = parser.__flush();
if (err) {
throw err;
}
return chunks;
if (err2 !== undefined) throw err2;
return records;
};

@@ -14,4 +14,5 @@ // Original definitions in https://github.com/DefinitelyTyped/DefinitelyTyped by: David Muller <https://github.com/davidm77>

declare namespace parse {
type Callback = (err: any | Error, output: any) => void;
type Callback = (err: Error | undefined, records: any | undefined, info: Info) => void;
type MatcherFunc = (value: any) => boolean;

@@ -23,45 +24,21 @@

constructor(options: Options);
__push(line: any): any;
__write(chars: any, end: any, callback: any): any;
/**
* Internal counter of records being processed.
*/
readonly count: number;
/**
* Internal counter of empty lines
*/
readonly empty_line_count: number;
/**
* Number of non uniform lines skipped when relax_column_count is true.
*/
readonly skipped_line_count: number;
/**
* The number of lines encountered in the source dataset, start at 1 for the first line.
*/
readonly lines: number;
/**
* The regular expression or function used to determine if a value should be cast to an integer.
*/
readonly is_int: RegExp | MatcherFunc;
/**
* The regular expression or function used to determine if a value should be cast to a float.
*/
readonly is_float: RegExp | MatcherFunc
readonly options: Options;
readonly info: Info;
}
interface CastingContext {
column?: string;
count: number;
index: number;
header: boolean;
quoting: boolean;
lines: number;
readonly column?: number | string;
readonly empty_lines: number;
readonly header: boolean;
readonly index: number;
readonly quoting: boolean;
readonly lines: number;
readonly records: number;
readonly invalid_field_length: number;
}

@@ -104,3 +81,3 @@

*/
columns?: any[] | boolean | ((line1: any) => boolean | string[]);
columns?: any[] | boolean | ((record: any) => boolean | string[]);

@@ -115,3 +92,3 @@ /**

*/
delimiter?: string;
delimiter?: string | Buffer;

@@ -121,8 +98,18 @@ /**

*/
escape?: string;
escape?: string | Buffer;
/**
* Start returning records from a particular line.
* Start handling records from the requested number of records.
*/
from?: number;
/**
* Start handling records from the requested line number.
*/
from_line?: number;
/**
* Generate two properties `info` and `record` where `info` is a snapshot of the info object at the time the record was created and `record` is the parsed array or object.
*/
info?: boolean;

@@ -137,6 +124,6 @@ /**

* Maximum numer of characters to be contained in the field and line buffers before an exception is raised,
* used to guard against a wrong delimiter or rowDelimiter,
* used to guard against a wrong delimiter or record_delimiter,
* default to 128000 characters.
*/
max_limit_on_data_read?: number;
max_record_size?: number;

@@ -151,5 +138,10 @@ /**

*/
quote?: string | boolean;
quote?: string | boolean | Buffer;
/**
* Generate two properties raw and row where raw is the original CSV row content and row is the parsed array or object.
*/
raw?: boolean;
/**
* Preserve quotes inside unquoted field.

@@ -165,11 +157,6 @@ */

/**
* Generate two properties raw and row where raw is the original CSV row content and row is the parsed array or object.
*/
raw?: boolean;
/**
* One or multiple characters used to delimit record rows; defaults to auto discovery if not provided.
* Supported auto discovery method are Linux ("\n"), Apple ("\r") and Windows ("\r\n") row delimiters.
*/
rowDelimiter?: string | string[];
record_delimiter?: string | string[] | Buffer | Buffer[];

@@ -199,3 +186,3 @@ /**

/**
* Stop returning records after a particular line.
* Stop handling records after the requested number of records.
*/

@@ -205,2 +192,7 @@ to?: number;

/**
* Stop handling records after the requested line number.
*/
to_line?: number;
/**
* If true, ignore whitespace immediately around the delimiter, defaults to false.

@@ -211,2 +203,25 @@ * Does not remove whitespace in a quoted field.

}
interface Info {
/**
* Count the number of lines being fully commented.
*/
readonly comment_lines: number;
/**
* Count the number of processed empty lines.
*/
readonly empty_lines: number;
/**
* The number of lines encountered in the source dataset, start at 1 for the first line.
*/
readonly lines: number;
/**
* Count the number of processed records.
*/
readonly records: number;
/**
* Number of non uniform records when `relax_column_count` is true.
*/
readonly invalid_field_length: number;
}
}

@@ -1,699 +0,741 @@

// Generated by CoffeeScript 2.3.2
// # CSV Parser
// This module provides a CSV parser tested and used against large datasets. Over the year, it has been enhance and is now full of useful options.
const { Transform } = require('stream')
const ResizeableBuffer = require('./ResizeableBuffer')
// Please look at the [project website](https://csv.js.org/parse/) for additional information.
var Parser, StringDecoder, default_options, isObjLiteral, stream, util;
stream = require('stream');
util = require('util');
({StringDecoder} = require('string_decoder'));
// ## Usage
// Callback approach, for ease of use:
// `parse(data, [options], callback)`
// [Node.js Stream API](http://nodejs.org/api/stream.html), for maximum of power:
// `parse([options], [callback])`
module.exports = function() {
var callback, called, chunks, data, err, options, parser;
if (arguments.length === 3) {
data = arguments[0];
options = arguments[1];
callback = arguments[2];
if (typeof callback !== 'function') {
throw Error(`Invalid callback argument: ${JSON.stringify(callback)}`);
}
if (!(typeof data === 'string' || Buffer.isBuffer(arguments[0]))) {
return callback(Error(`Invalid data argument: ${JSON.stringify(data)}`));
}
} else if (arguments.length === 2) {
// 1st arg is data:string or options:object
if (typeof arguments[0] === 'string' || Buffer.isBuffer(arguments[0])) {
data = arguments[0];
} else if (isObjLiteral(arguments[0])) {
options = arguments[0];
} else {
err = `Invalid first argument: ${JSON.stringify(arguments[0])}`;
}
// 2nd arg is options:object or callback:function
if (typeof arguments[1] === 'function') {
callback = arguments[1];
} else if (isObjLiteral(arguments[1])) {
if (options) {
err = 'Invalid arguments: got options twice as first and second arguments';
} else {
options = arguments[1];
}
} else {
err = `Invalid first argument: ${JSON.stringify(arguments[1])}`;
}
if (err) {
if (!callback) {
throw Error(err);
} else {
return callback(Error(err));
}
}
} else if (arguments.length === 1) {
if (typeof arguments[0] === 'function') {
callback = arguments[0];
} else {
options = arguments[0];
}
}
if (options == null) {
options = {};
}
parser = new Parser(options);
if (data != null) {
process.nextTick(function() {
parser.write(data);
return parser.end();
});
}
if (callback) {
called = false;
chunks = options.objname ? {} : [];
parser.on('readable', function() {
var chunk, results;
results = [];
while (chunk = parser.read()) {
if (options.objname) {
results.push(chunks[chunk[0]] = chunk[1]);
} else {
results.push(chunks.push(chunk));
}
}
return results;
});
parser.on('error', function(err) {
called = true;
return callback(err);
});
parser.on('end', function() {
if (!called) {
return callback(null, chunks);
}
});
}
return parser;
};
// ## `Parser([options])`
// Options are documented [here](http://csv.js.org/parse/options/).
default_options = {
rowDelimiter: null,
delimiter: ',',
quote: '"',
escape: '"',
const default_options = {
// cast: false,
// cast_date: false,
columns: null,
comment: '',
objname: false,
trim: false,
ltrim: false,
rtrim: false,
cast: false,
cast_date: false,
delimiter: Buffer.from(','),
escape: Buffer.from('"'),
from: 1,
from_line: 1,
objname: undefined,
// ltrim: false,
// quote: Buffer.from('"'),
// TODO create a max_comment_size
max_record_size: 0,
relax: false,
relax_column_count: false,
// rtrim: false,
skip_empty_lines: false,
max_limit_on_data_read: 128000,
skip_lines_with_empty_values: false,
skip_lines_with_error: false
};
skip_lines_with_error: false,
to_line: -1,
to: -1,
trim: false
}
Parser = function(opts = {}) {
var k, options, v;
opts.objectMode = true;
stream.Transform.call(this, opts);
options = {};
// Clone options
for (k in opts) {
v = opts[k];
options[k] = v;
}
// Default values
for (k in default_options) {
v = default_options[k];
if (options[k] === void 0) {
options[k] = default_options[k];
const cr = 13
const nl = 10
const space = 32
class Parser extends Transform {
constructor(opts = {}){
const options = {}
for(let i in opts){
options[i] = opts[i]
}
}
this.options = options;
if (typeof options.rowDelimiter === 'string') {
options.rowDelimiter = [options.rowDelimiter];
}
if (options.quote !== void 0 && !options.quote) {
options.quote = '';
}
if (options.auto_parse != null) {
options.cast = options.auto_parse;
}
if (options.auto_parse_date != null) {
options.cast_date = options.auto_parse_date;
}
if (options.cast_date === true) {
options.cast_date = function(value) {
var m;
m = Date.parse(value);
if (!isNaN(m)) {
value = new Date(m);
options.readableObjectMode = true
super(options)
// Import default options
for(let k in default_options){
if(options[k] === undefined){
options[k] = default_options[k]
}
return value;
};
}
// Counters
// lines = count + skipped_line_count + empty_line_count
this.lines = 0; // Number of lines encountered in the source dataset
this.count = 0; // Number of records being processed
this.skipped_line_count = 0; // Number of records skipped due to errors
this.empty_line_count = 0; // Number of empty lines
// Constants
this.is_int = /^(\-|\+)?([1-9]+[0-9]*)$/;
// @is_float = /^(\-|\+)?([0-9]+(\.[0-9]+)([eE][0-9]+)?|Infinity)$/
// @is_float = /^(\-|\+)?((([0-9])|([1-9]+[0-9]*))(\.[0-9]+)([eE][0-9]+)?|Infinity)$/
this.is_float = function(value) {
return (value - parseFloat(value) + 1) >= 0; // Borrowed from jquery
};
// Internal private state
this._ = {
decoder: new StringDecoder(),
quoting: false,
commenting: false,
field: null,
nextChar: null,
closingQuote: 0,
line: [],
chunks: [],
rawBuf: '',
buf: '',
rowDelimiterMaxLength: this.options.rowDelimiter ? Math.max(...this.options.rowDelimiter.map(function(v) {
return v.length;
})) : void 0,
quotedRowDelimiterMaxLength: this.options.rowDelimiter ? options.quote.length + Math.max(...this.options.rowDelimiter.map(function(v) {
return v.length;
})) : void 0,
lineHasError: false,
isEnded: false
};
return this;
};
// ## Internal API
// The Parser implement a [`stream.Transform` class](https://nodejs.org/api/stream.html#stream_class_stream_transform).
// ### Events
// The library extends Node [EventEmitter][event] class and emit all the events of the Writable and Readable [Stream API](http://nodejs.org/api/stream.html).
util.inherits(Parser, stream.Transform);
// For extra flexibility, you can get access to the original Parser class: `require('csv-parse').Parser`.
module.exports.Parser = Parser;
// ### `_transform(chunk, encoding, callback)`
// * `chunk` Buffer | String
// The chunk to be transformed. Will always be a buffer unless the decodeStrings option was set to false.
// * `encoding` String
// If the chunk is a string, then this is the encoding type. (Ignore if decodeStrings chunk is a buffer.)
// * `callback` Function
// Call this function (optionally with an error argument) when you are done processing the supplied chunk.
// Implementation of the [`stream.Transform` API](https://nodejs.org/api/stream.html#stream_class_stream_transform)
Parser.prototype._transform = function(chunk, encoding, callback) {
return setImmediate(() => {
var err;
if (chunk instanceof Buffer) {
chunk = this._.decoder.write(chunk);
}
err = this.__write(chunk, false);
if (err) {
return this.emit('error', err);
// Normalize option `cast`
let fnCastField = null
if(options.cast === undefined || options.cast === null || options.cast === false || options.cast === ''){
options.cast = undefined
}else if(typeof options.cast === 'function'){
fnCastField = options.cast
options.cast = true
}else if(options.cast !== true){
throw new Error('Invalid Option: cast must be true or a function')
}
return callback();
});
};
Parser.prototype._flush = function(callback) {
return callback(this.__flush());
};
Parser.prototype.__flush = function() {
var err;
err = this.__write(this._.decoder.end(), true);
if (err) {
return err;
}
if (this._.quoting) {
err = this.error(`Quoted field not terminated at line ${this.lines + 1}`);
return err;
}
if (this._.line.length > 0) {
return this.__push(this._.line);
}
};
Parser.prototype.__push = function(line) {
var call_column_udf, columnName, columns, err, field, i, j, len, lineAsColumns, record;
if (this._.isEnded) {
return;
}
if (this.options.skip_lines_with_empty_values && line.join('').trim() === '') {
return;
}
record = null;
if (this.options.columns === true) {
this.options.columns = line;
return;
} else if (typeof this.options.columns === 'function') {
call_column_udf = function(fn, line) {
var columns, err;
try {
columns = fn.call(null, line);
return [null, columns];
} catch (error) {
err = error;
return [err];
// Normize option `cast_date`
if(options.cast_date === undefined || options.cast_date === null || options.cast_date === false || options.cast_date === ''){
options.cast_date = false
}else if(options.cast_date === true){
options.cast_date = function(value){
const date = Date.parse(value)
return !isNaN(date) ? new Date(date) : value
}
};
[err, columns] = call_column_udf(this.options.columns, line);
if (err) {
return err;
}else if(typeof options.cast_date !== 'function'){
throw new Error('Invalid Option: cast_date must be true or a function')
}
this.options.columns = columns;
return;
}
if (!this._.line_length && line.length > 0) {
this._.line_length = this.options.columns ? this.options.columns.length : line.length;
}
// Dont check column count on empty lines
if (line.length === 1 && line[0] === '') {
this.empty_line_count++;
} else if (line.length !== this._.line_length) {
// Dont check column count with relax_column_count
if (this.options.relax_column_count) {
this.count++;
this.skipped_line_count++;
} else if (this.options.columns != null) {
// Suggest: Inconsistent header and column numbers: header is 1 and number of columns is 1 on line 1
err = this.error(`Number of columns on line ${this.lines} does not match header`);
return err;
} else {
err = this.error(`Number of columns is inconsistent on line ${this.lines}`);
return err;
}
} else {
this.count++;
}
if (this.options.columns != null) {
lineAsColumns = {};
for (i = j = 0, len = line.length; j < len; i = ++j) {
field = line[i];
columnName = this.options.columns[i];
if (columnName === void 0 || columnName === null || columnName === false) {
continue;
// Normalize option `comment`
if(options.comment === undefined || options.comment === null || options.comment === false || options.comment === ''){
options.comment = null
}else{
if(typeof options.comment === 'string'){
options.comment = Buffer.from(options.comment)
}
if (typeof columnName !== 'string') {
throw Error(`Invalid column name ${JSON.stringify(columnName)}`);
if(!Buffer.isBuffer(options.comment)){
throw new Error(`Invalid Option: comment must be a buffer or a string, got ${JSON.stringify(options.comment)}`)
}
lineAsColumns[columnName] = field;
}
if (this.options.objname) {
record = [lineAsColumns[this.options.objname], lineAsColumns];
} else {
record = lineAsColumns;
// Normalize option `delimiter`
if(typeof options.delimiter === 'string'){
options.delimiter = Buffer.from(options.delimiter)
}
} else {
record = line;
}
if (this.count < this.options.from) {
return;
}
if (this.options.raw) {
this.push({
raw: this._.rawBuf,
row: record
});
this._.rawBuf = '';
} else {
this.push(record);
}
if (this.listenerCount('record')) {
this.emit('record', record);
}
// When to is reached set ignore any future calls
if (this.count >= this.options.to) {
this._.isEnded = true;
return this.push(null);
}
return null;
};
Parser.prototype.__write = function(chars, end) {
var areNextCharsDelimiter, areNextCharsRowDelimiters, cast, char, err, escapeIsQuote, i, isDelimiter, isEscape, isNextCharAComment, isNextCharTrimable, isQuote, isRowDelimiter, isRowDelimiterLength, is_float, is_int, l, ltrim, nextCharPos, numOfCharLeft, ref, ref1, ref2, ref3, ref4, ref5, ref6, remainingBuffer, rowDelimiter, rtrim, wasCommenting;
is_int = (value) => {
if (typeof this.is_int === 'function') {
return this.is_int(value);
} else {
return this.is_int.test(value);
// Normalize option `columns`
let fnFirstLineToHeaders = null
if(options.columns === true){
fnFirstLineToHeaders = firstLineToHeadersDefault
}else if(typeof options.columns === 'function'){
fnFirstLineToHeaders = options.columns
options.columns = true
}else if(Array.isArray(options.columns)){
normalizeColumnsArray(options.columns)
}else if(options.columns === undefined || options.columns === null || options.columns === false){
options.columns = false
}else{
throw new Error(`Invalid Option columns: expect an object or true, got ${JSON.stringify(options.columns)}`)
}
};
is_float = (value) => {
if (typeof this.is_float === 'function') {
return this.is_float(value);
} else {
return this.is_float.test(value);
// Normalize option `escape`
if(typeof options.escape === 'string'){
options.escape = Buffer.from(options.escape)
}
};
cast = (value, context = {}) => {
if (!this.options.cast) {
return value;
if(!Buffer.isBuffer(options.escape)){
throw new Error(`Invalid Option: escape must be a buffer or a string, got ${JSON.stringify(options.escape)}`)
}else if(options.escape.length !== 1){
throw new Error(`Invalid Option Length: escape must be one character, got ${options.escape.length}`)
}else{
options.escape = options.escape[0]
}
if (context.quoting == null) {
context.quoting = !!this._.closingQuote;
// Normalize option `info`
if(options.info === undefined || options.info === null || options.info === false){
options.info = false
}else if(options.info !== true){
throw new Error(`Invalid Option: info must be true, got ${JSON.stringify(options.info)}`)
}
if (context.lines == null) {
context.lines = this.lines;
// Normalize option `quote`
if(options.quote === null || options.quote === false || options.quote === ''){
options.quote = null
}else{
if(options.quote === undefined || options.quote === true){
options.quote = Buffer.from('"')
}else if(typeof options.quote === 'string'){
options.quote = Buffer.from(options.quote)
}
if(!Buffer.isBuffer(options.quote)){
throw new Error(`Invalid Option: quote must be a buffer or a string, got ${JSON.stringify(options.quote)}`)
}else if(options.quote.length !== 1){
throw new Error(`Invalid Option Length: quote must be one character, got ${options.quote.length}`)
}else{
options.quote = options.quote[0]
}
}
if (context.count == null) {
context.count = this.count;
// Normalize options `raw`
if(options.raw === undefined || options.raw === null || options.raw === false){
options.raw = false
}else if(options.raw !== true){
throw new Error(`Invalid Option: raw must be true, got ${JSON.stringify(options.raw)}`)
}
if (context.index == null) {
context.index = this._.line.length;
// Normalize option `record_delimiter`
if(!options.record_delimiter){
options.record_delimiter = []
}else if(!Array.isArray(options.record_delimiter)){
options.record_delimiter = [options.record_delimiter]
}
// context.header ?= if @options.column and @lines is 1 and @count is 0 then true else false
if (context.header == null) {
context.header = this.options.columns === true;
options.record_delimiter = options.record_delimiter.map( function(rd){
if(typeof rd === 'string'){
rd = Buffer.from(rd)
}
return rd
})
// Normalize options `trim`, `ltrim` and `rtrim`
if(options.trim === true && options.ltrim !== false){
options.ltrim = true
}else if(options.ltrim !== true){
options.ltrim = false
}
if (context.column == null) {
context.column = Array.isArray(this.options.columns) ? this.options.columns[context.index] : context.index;
if(options.trim === true && options.rtrim !== false){
options.rtrim = true
}else if(options.rtrim !== true){
options.rtrim = false
}
if (typeof this.options.cast === 'function') {
return this.options.cast(value, context);
this.info = {
comment_lines: 0,
empty_lines: 0,
invalid_field_length: 0,
lines: 1,
records: 0
}
if (is_int(value)) {
value = parseInt(value);
} else if (is_float(value)) {
value = parseFloat(value);
} else if (this.options.cast_date) {
value = this.options.cast_date(value, context);
this.options = options
this.state = {
castField: fnCastField,
commenting: false,
enabled: options.from_line === 1,
escaping: false,
escapeIsQuote: options.escape === options.quote,
expectedRecordLength: options.columns === null ? 0 : options.columns.length,
field: new ResizeableBuffer(20),
firstLineToHeaders: fnFirstLineToHeaders,
info: Object.assign({}, this.info),
previousBuf: undefined,
quoting: false,
stop: false,
rawBuffer: new ResizeableBuffer(100),
record: [],
recordHasError: false,
record_length: 0,
recordDelimiterMaxLength: options.record_delimiter.length === 0 ? 2 : Math.max(...options.record_delimiter.map( (v) => v.length)),
trimChars: [Buffer.from(' ')[0], Buffer.from('\t')[0]],
wasQuoting: false,
wasRowDelimiter: false
}
return value;
};
ltrim = this.options.trim || this.options.ltrim;
rtrim = this.options.trim || this.options.rtrim;
escapeIsQuote = this.options.escape === this.options.quote;
chars = this._.buf + chars;
l = chars.length;
i = 0;
if (this.lines === 0 && 0xFEFF === chars.charCodeAt(0)) {
// Strip BOM header
i++;
}
while (i < l) {
// Ensure we get enough space to look ahead
if (!end) {
numOfCharLeft = l - i;
remainingBuffer = chars.substr(i, numOfCharLeft);
// Skip if row delimiter larger than auto discovered values
// Skip if the remaining buffer smaller than comment
// Skip if the remaining buffer smaller than row delimiter
// Skip if the remaining buffer can be row delimiter following the closing quote
// Skip if the remaining buffer can be delimiter
// Skip if the remaining buffer can be escape sequence
if ((!this.options.rowDelimiter && i + 3 > l) || (!this._.commenting && numOfCharLeft < this.options.comment.length) || (this.options.rowDelimiter && numOfCharLeft < this._.rowDelimiterMaxLength) || (this._.quoting && this.options.rowDelimiter && numOfCharLeft < this._.quotedRowDelimiterMaxLength) || (numOfCharLeft <= this.options.delimiter.length && this.options.delimiter.substr(0, numOfCharLeft) === remainingBuffer) || (numOfCharLeft <= this.options.escape.length && this.options.escape.substr(0, numOfCharLeft) === remainingBuffer)) {
break;
}
_transform(buf, encoding, callback){
if(this.state.stop === true){
return
}
char = this._.nextChar ? this._.nextChar : chars.charAt(i);
this._.nextChar = l > i + 1 ? chars.charAt(i + 1) : null;
if (this.options.raw) {
this._.rawBuf += char;
const err = this.__parse(buf, false)
if(err !== undefined){
this.state.stop = true
}
// Auto discovery of rowDelimiter, unix, mac and windows supported
if (this.options.rowDelimiter == null) {
nextCharPos = i;
rowDelimiter = null;
// First empty line
if (!this._.quoting && (char === '\n' || char === '\r')) {
rowDelimiter = char;
nextCharPos += 1;
} else if (this._.quoting && char === this.options.quote && ((ref = this._.nextChar) === '\n' || ref === '\r')) {
rowDelimiter = this._.nextChar;
nextCharPos += 2;
callback(err)
}
_flush(callback){
if(this.state.stop === true){
return
}
const err = this.__parse(undefined, true)
callback(err)
}
__parse(nextBuf, end){
const {comment, escape, from, from_line, info, ltrim, max_record_size, quote, raw, relax, rtrim, skip_empty_lines, to, to_line} = this.options
let {record_delimiter} = this.options
const {previousBuf, rawBuffer, escapeIsQuote, trimChars} = this.state
let buf
if(previousBuf === undefined && nextBuf !== undefined){
buf = nextBuf
}else if(previousBuf !== undefined && nextBuf === undefined){
buf = previousBuf
}else{
buf = Buffer.concat([previousBuf, nextBuf])
}
const bufLen = buf.length
let pos
// let escaping = this.
for(pos = 0; pos < bufLen; pos++){
// Ensure we get enough space to look ahead
// There should be a way to move this out of the loop
if(this.__needMoreData(pos, bufLen, end)){
break
}
if (rowDelimiter) {
if (rowDelimiter === '\r' && chars.charAt(nextCharPos) === '\n') {
rowDelimiter += '\n';
if(this.state.wasRowDelimiter === true){
this.info.lines++
if(info === true && this.state.record.length === 0 && this.state.field.length === 0 && this.state.wasQuoting === false){
this.state.info = Object.assign({}, this.info)
}
this.options.rowDelimiter = [rowDelimiter];
this._.rowDelimiterMaxLength = rowDelimiter.length;
this.state.wasRowDelimiter = false
}
}
// Parse that damn char
// Note, shouldn't we have sth like chars.substr(i, @options.escape.length)
if (!this._.commenting && char === this.options.escape) {
// Make sure the escape is really here for escaping:
// If escape is same as quote, and escape is first char of a field
// and it's not quoted, then it is a quote
// Next char should be an escape or a quote
isEscape = this._.nextChar === this.options.escape;
isQuote = this._.nextChar === this.options.quote;
if (!(escapeIsQuote && !this._.field && !this._.quoting) && (isEscape || isQuote)) {
i++;
char = this._.nextChar;
this._.nextChar = chars.charAt(i + 1);
if (this._.field == null) {
this._.field = '';
if(to_line !== -1 && this.info.lines > to_line){
this.state.stop = true
this.push(null)
return
}
// Auto discovery of record_delimiter, unix, mac and windows supported
if(this.state.quoting === false && record_delimiter.length === 0){
const recordDelimiterCount = this.__autoDiscoverRowDelimiter(buf, pos)
if(recordDelimiterCount){
record_delimiter = this.options.record_delimiter
}
this._.field += char;
// Since we're skipping the next one, better add it now if in raw mode.
if (this.options.raw) {
this._.rawBuf += char;
}
i++;
continue;
}
}
// Char match quote
if (!this._.commenting && char === this.options.quote) {
if (this._.acceptOnlyEmptyChars && (char !== ' ' && char !== '\t')) {
return this.error('Only trimable characters are accepted after quotes');
const chr = buf[pos]
if(raw === true){
rawBuffer.append(chr)
}
if (this._.quoting) {
// Make sure a closing quote is followed by a delimiter
// If we have a next character and
// it isnt a rowDelimiter and
// it isnt an column delimiter and
// it isnt the begining of a comment
// Otherwise, if this is not "relax" mode, throw an error
isNextCharTrimable = rtrim && ((ref1 = this._.nextChar) === ' ' || ref1 === '\t');
areNextCharsRowDelimiters = this.options.rowDelimiter && this.options.rowDelimiter.some(function(rd) {
return chars.substr(i + 1, rd.length) === rd;
});
areNextCharsDelimiter = chars.substr(i + 1, this.options.delimiter.length) === this.options.delimiter;
isNextCharAComment = this._.nextChar === this.options.comment;
if ((this._.nextChar != null) && !isNextCharTrimable && !areNextCharsRowDelimiters && !areNextCharsDelimiter && !isNextCharAComment) {
if (this.options.relax) {
this._.quoting = false;
if (this._.field) {
this._.field = `${this.options.quote}${this._.field}`;
if((chr === cr || chr === nl) && this.state.wasRowDelimiter === false ){
this.state.wasRowDelimiter = true
}
// Previous char was a valid escape char
// treat the current char as a regular char
if(this.state.escaping === true){
this.state.escaping = false
}else{
// Escape is only active inside quoted fields
if(this.state.quoting === true && chr === escape && pos + 1 < bufLen){
// We are quoting, the char is an escape chr and there is a chr to escape
if(escapeIsQuote){
if(buf[pos+1] === quote){
this.state.escaping = true
continue
}
} else {
if (err = this.error(`Invalid closing quote at line ${this.lines + 1}; found ${JSON.stringify(this._.nextChar)} instead of delimiter ${JSON.stringify(this.options.delimiter)}`)) {
return err;
}else{
this.state.escaping = true
continue
}
}
// Not currently escaping and chr is a quote
// TODO: need to compare bytes instead of single char
if(this.state.commenting === false && chr === quote){
if(this.state.quoting === true){
const nextChr = buf[pos+1]
const isNextChrTrimable = rtrim && this.__isCharTrimable(nextChr)
// const isNextChrComment = nextChr === comment
const isNextChrComment = comment !== null && this.__compareBytes(comment, buf, pos+1, nextChr)
const isNextChrDelimiter = this.__isDelimiter(nextChr, buf, pos+1)
const isNextChrRowDelimiter = record_delimiter.length === 0 ? this.__autoDiscoverRowDelimiter(buf, pos+1) : this.__isRecordDelimiter(nextChr, buf, pos+1)
// Escape a quote
// Treat next char as a regular character
// TODO: need to compare bytes instead of single char
if(chr === escape && nextChr === quote){
pos++
}else if(!nextChr || isNextChrDelimiter || isNextChrRowDelimiter || isNextChrComment || isNextChrTrimable){
this.state.quoting = false
this.state.wasQuoting = true
continue
}else if(relax === false){
const err = this.__error(`Invalid Closing Quote: got "${String.fromCharCode(nextChr)}" at line ${this.info.lines} instead of delimiter, row delimiter, trimable character (if activated) or comment`)
if(err !== undefined) return err
}else{
this.state.quoting = false
this.state.wasQuoting = true
// continue
this.state.field.prepend(quote)
}
}else{
if(this.state.field.length !== 0){
// In relax mode, treat opening quote preceded by chrs as regular
if( relax === false ){
const err = this.__error(`Invalid opening quote at line ${this.info.lines}`)
if(err !== undefined) return err
}
}else{
this.state.quoting = true
continue
}
}
} else if ((this._.nextChar != null) && isNextCharTrimable) {
i++;
this._.quoting = false;
this._.closingQuote = 1;
this._.acceptOnlyEmptyChars = true;
continue;
} else {
i++;
this._.quoting = false;
this._.closingQuote = 1;
if (end && i === l) {
this._.line.push(cast(this._.field || ''));
this._.field = null;
}
if(this.state.quoting === false){
let recordDelimiterLength = this.__isRecordDelimiter(chr, buf, pos)
if(recordDelimiterLength !== 0){
// Do not emit comments which take a full line
const skipCommentLine = this.state.commenting && (this.state.wasQuoting === false && this.state.record.length === 0 && this.state.field.length === 0)
if(skipCommentLine){
this.info.comment_lines++
// Skip full comment line
}else{
// Skip if line is empty and skip_empty_lines activated
if(skip_empty_lines === true && this.state.wasQuoting === false && this.state.record.length === 0 && this.state.field.length === 0){
this.info.empty_lines++
continue
}
// Activate records emition if above from_line
if(this.state.enabled === false && this.info.lines + (this.state.wasRowDelimiter === true ? 1: 0 ) >= from_line){
this.state.enabled = true
this.__resetField()
this.__resetRow()
continue
}else{
const errField = this.__onField()
if(errField !== undefined) return errField
const errRecord = this.__onRow()
if(errRecord !== undefined) return errRecord
}
if(to !== -1 && this.info.records >= to){
this.state.stop = true
this.push(null)
return
}
}
this.state.commenting = false
pos += recordDelimiterLength - 1
continue
}
continue;
if(this.state.commenting){
continue
}
const commentCount = comment === null ? 0 : this.__compareBytes(comment, buf, pos, chr)
if(commentCount !== 0){
this.state.commenting = true
continue
}
let delimiterLength = this.__isDelimiter(chr, buf, pos)
if(delimiterLength !== 0){
const errField = this.__onField()
if(errField !== undefined) return errField
pos += delimiterLength - 1
continue
}
}
} else if (!this._.field) {
this._.quoting = true;
i++;
continue;
} else if ((this._.field != null) && !this.options.relax) {
if (err = this.error(`Invalid opening quote at line ${this.lines + 1}`)) {
return err;
}
if(this.state.commenting === false){
if(max_record_size !== 0 && this.state.record_length + this.state.field.length > max_record_size){
const err = this.__error(`Max Record Size: record exceed the maximum number of tolerated bytes of ${max_record_size} on line ${this.info.lines}`)
if(err !== undefined) return err
}
}
const lappend = ltrim === false || this.state.quoting === true || this.state.field.length !== 0 || !this.__isCharTrimable(chr)
// rtrim in non quoting is handle in __onField
const rappend = rtrim === false || this.state.wasQuoting === false
if( lappend === true && rappend === true ){
this.state.field.append(chr)
}else if(rtrim === true && !this.__isCharTrimable(chr)){
const err = this.__error(`Invalid Closing Quote: found non trimable byte after quote at line ${this.info.lines}`)
if(err !== undefined) return err
}
}
// Otherwise, treat quote as a regular character
isRowDelimiter = this.options.rowDelimiter && this.options.rowDelimiter.some(function(rd) {
return chars.substr(i, rd.length) === rd;
});
if (isRowDelimiter || (end && i === l - 1)) {
this.lines++;
if(end === true){
if(this.state.quoting === true){
const err = this.__error(`Invalid Closing Quote: quote is not closed at line ${this.info.lines}`)
if(err !== undefined) return err
}else{
// Skip last line if it has no characters
if(this.state.wasQuoting === true || this.state.record.length !== 0 || this.state.field.length !== 0){
const errField = this.__onField()
if(errField !== undefined) return errField
const errRecord = this.__onRow()
if(errRecord !== undefined) return errRecord
}else if(this.state.wasRowDelimiter === true){
this.info.empty_lines++
}else if(this.state.commenting === true){
this.info.comment_lines++
}
}
}else{
this.state.previousBuf = buf.slice(pos)
}
// Set the commenting flag
wasCommenting = false;
if (!this._.commenting && !this._.quoting && this.options.comment && chars.substr(i, this.options.comment.length) === this.options.comment) {
this._.commenting = true;
} else if (this._.commenting && isRowDelimiter) {
wasCommenting = true;
this._.commenting = false;
if(this.state.wasRowDelimiter === true){
this.info.lines++
this.state.wasRowDelimiter = false
}
isDelimiter = chars.substr(i, this.options.delimiter.length) === this.options.delimiter;
if (this._.acceptOnlyEmptyChars) {
if (isDelimiter || isRowDelimiter) {
this._.acceptOnlyEmptyChars = false;
} else {
if (char === ' ' || char === '\t') {
i++;
continue;
} else {
return this.error('Only trimable characters are accepted after quotes');
}
__isCharTrimable(chr){
return chr === space || chr === cr || chr === nl
}
__onRow(){
const {columns, info, from, relax_column_count, raw, skip_lines_with_empty_values} = this.options
const {enabled, record} = this.state
// Validate column length
if(columns === true && this.state.firstLineToHeaders){
return this.__firstLineToColumns(record)
}
const recordLength = record.length
if(columns === false && this.info.records === 0){
this.state.expectedRecordLength = recordLength
}else if(enabled === true){
if(recordLength !== this.state.expectedRecordLength){
if(relax_column_count === true){
this.info.invalid_field_length++
}else{
if(columns === false){
const err = this.__error(`Invalid Record Length: expect ${this.state.expectedRecordLength}, got ${recordLength} on line ${this.info.lines}`)
if(err !== undefined) return err
}else{
const err = this.__error(`Invalid Record Length: header length is ${columns.length}, got ${recordLength} on line ${this.info.lines}`)
if(err !== undefined) return err
}
}
}
}
if (!this._.commenting && !this._.quoting && (isDelimiter || isRowDelimiter)) {
if (isRowDelimiter) {
isRowDelimiterLength = this.options.rowDelimiter.filter(function(rd) {
return chars.substr(i, rd.length) === rd;
})[0].length;
if(enabled === false){
return this.__resetRow()
}
if( skip_lines_with_empty_values === true){
if(record.map( (field) => field.trim() ).join('') === ''){
this.__resetRow()
return
}
// Empty lines
if (isRowDelimiter && this._.line.length === 0 && (this._.field == null)) {
if (wasCommenting || this.options.skip_empty_lines) {
i += isRowDelimiterLength;
this._.nextChar = chars.charAt(i);
continue;
}
if(this.state.recordHasError === true){
this.__resetRow()
this.state.recordHasError = false
return
}
this.info.records++
if(from === 1 || this.info.records >= from){
if(columns !== false){
const obj = {}
// Transform record array to an object
for(let i in record){
if(columns[i].disabled) continue
obj[columns[i].name] = record[i]
}
}
if (rtrim) {
if (!this._.closingQuote) {
this._.field = (ref2 = this._.field) != null ? ref2.trimRight() : void 0;
}
}
this._.line.push(cast(this._.field || ''));
this._.closingQuote = 0;
this._.field = null;
// End of field
// Ensure that the delimiter doesnt match as well the rowDelimiter
if (isDelimiter && !isRowDelimiter) {
i += this.options.delimiter.length;
this._.nextChar = chars.charAt(i);
if (end && !this._.nextChar) {
isRowDelimiter = true;
this._.line.push('');
}
}
if (isRowDelimiter) { // End of record
if (!this._.lineHasError) {
err = this.__push(this._.line);
if (err) {
return err;
const {objname} = this.options
if(objname === undefined){
if(raw === true || info === true){
this.push(Object.assign(
{record: obj},
(raw === true ? {raw: this.state.rawBuffer.toString()}: {}),
(info === true ? {info: this.state.info}: {})
))
}else{
this.push(obj)
}
}else{
if(raw === true || info === true){
this.push(Object.assign(
{record: [obj[objname], obj]},
raw === true ? {raw: this.state.rawBuffer.toString()}: {},
info === true ? {info: this.state.info}: {}
))
}else{
this.push([obj[objname], obj])
}
}
if (this._.lineHasError) {
this._.lineHasError = false;
}else{
if(raw === true || info === true){
this.push(Object.assign(
{record: record},
raw === true ? {raw: this.state.rawBuffer.toString()}: {},
info === true ? {info: this.state.info}: {}
))
}else{
this.push(record)
}
// Some cleanup for the next record
this._.line = [];
i += isRowDelimiterLength;
this._.nextChar = chars.charAt(i);
continue;
}
} else if (!this._.commenting && !this._.quoting && (char === ' ' || char === '\t')) {
if (this._.field == null) {
// Left trim unless we are quoting or field already filled
this._.field = '';
}
this.__resetRow()
}
__firstLineToColumns(record){
try{
const headers = this.state.firstLineToHeaders.call(null, record)
if(!Array.isArray(headers)){
return this.__error(`Invalid Header Mapping: expect an array, got ${JSON.stringify(headers)}`)
}
if (!(ltrim && !this._.field)) {
this._.field += char;
normalizeColumnsArray(headers)
this.state.expectedRecordLength = headers.length
this.options.columns = headers
this.__resetRow()
return
}catch(err){
return err
}
}
__resetRow(){
const {info} = this.options
if(this.options.raw === true){
this.state.rawBuffer.reset()
}
this.state.record = []
this.state.record_length = 0
}
__onField(){
const {cast, rtrim} = this.options
const {enabled, wasQuoting} = this.state
// Deal with from_to options
if(this.options.columns !== true && enabled === false){
return this.__resetField()
}
let field = this.state.field.toString()
if(rtrim === true && wasQuoting === false){
field = field.trimRight()
}
if(cast === true){
const [err, f] = this.__cast(field)
if(err !== undefined) return err
field = f
}
this.state.record.push(field)
this.state.record_length += field.length
this.__resetField()
}
__resetField(){
this.state.field.reset()
this.state.wasQuoting = false
}
__cast(field){
const context = {
column: Array.isArray(this.options.columns) === true ? this.options.columns[this.state.record.length] : this.state.record.length,
empty_lines: this.info.empty_lines,
header: this.options.columns === true,
index: this.state.record.length,
invalid_field_length: this.info.invalid_field_length,
quoting: this.state.wasQuoting,
lines: this.info.lines,
records: this.info.records
}
if(this.state.castField !== null){
try{
return [undefined, this.state.castField.call(null, field, context)]
}catch(err){
return [err]
}
i++;
} else if (!this._.commenting) {
if (this._.field == null) {
this._.field = '';
}
this._.field += char;
i++;
} else {
i++;
}
if (!this._.commenting && ((ref3 = this._.field) != null ? ref3.length : void 0) > this.options.max_limit_on_data_read) {
return Error(`Field exceeds max_limit_on_data_read: maximum value is ${this.options.max_limit_on_data_read}`);
if(this.__isInt(field) === true){
return [undefined, parseInt(field)]
}else if(this.__isFloat(field)){
return [undefined, parseFloat(field)]
}else if(this.options.cast_date !== false){
return [undefined, this.options.cast_date.call(null, field, context)]
}
if (!this._.commenting && ((ref4 = this._.line) != null ? ref4.length : void 0) > this.options.max_limit_on_data_read) {
return Error(`Row delimiter not found in the file ${JSON.stringify(this.options.rowDelimiter)}`);
return [undefined, field]
}
__isInt(value){
return /^(\-|\+)?([1-9]+[0-9]*)$/.test(value)
}
__isFloat(value){
return (value - parseFloat( value ) + 1) >= 0 // Borrowed from jquery
}
__compareBytes(sourceBuf, targetBuf, pos, firtByte){
if(sourceBuf[0] !== firtByte) return 0
const sourceLength = sourceBuf.length
for(let i = 1; i < sourceLength; i++){
if(sourceBuf[i] !== targetBuf[pos+i]) return 0
}
return sourceLength
}
// Flush remaining fields and lines
if (end) {
if (l === 0) {
this.lines++;
__needMoreData(i, bufLen, end){
if(end){
return false
}
if (this._.field != null) {
if (rtrim) {
if (!this._.closingQuote) {
this._.field = (ref5 = this._.field) != null ? ref5.trimRight() : void 0;
const {comment, delimiter, escape} = this.options
const {quoting, recordDelimiterMaxLength} = this.state
const numOfCharLeft = bufLen - i - 1
const requiredLength = Math.max(
// Skip if the remaining buffer smaller than comment
comment ? comment.length : 0,
// Skip if the remaining buffer smaller than row delimiter
recordDelimiterMaxLength,
// Skip if the remaining buffer can be row delimiter following the closing quote
// 1 is for quote.length
quoting ? (1 + recordDelimiterMaxLength) : 0,
// Skip if the remaining buffer can be delimiter
delimiter.length,
// Skip if the remaining buffer can be escape sequence
// 1 is for escape.length
1
)
return numOfCharLeft < requiredLength
}
__isDelimiter(chr, buf, pos){
const {delimiter} = this.options
const delLength = delimiter.length
if(delimiter[0] !== chr) return 0
for(let i = 1; i < delLength; i++){
if(delimiter[i] !== buf[pos+i]) return 0
}
return delimiter.length
}
__isRecordDelimiter(chr, buf, pos){
const {record_delimiter} = this.options
const recordDelimiterLength = record_delimiter.length
loop1: for(let i = 0; i < recordDelimiterLength; i++){
const rd = record_delimiter[i]
const rdLength = rd.length
if(rd[0] !== chr){
continue
}
for(let j = 1; j < rdLength; j++){
if(rd[j] !== buf[pos+j]){
continue loop1
}
}
this._.line.push(cast(this._.field || ''));
this._.field = null;
return rd.length
}
if (((ref6 = this._.field) != null ? ref6.length : void 0) > this.options.max_limit_on_data_read) {
return Error(`Delimiter not found in the file ${JSON.stringify(this.options.delimiter)}`);
return 0
}
__autoDiscoverRowDelimiter(buf, pos){
const chr = buf[pos]
if(chr === cr){
if(buf[pos+1] === nl){
this.options.record_delimiter.push(Buffer.from('\r\n'))
this.state.recordDelimiterMaxLength = 2
return 2
}else{
this.options.record_delimiter.push(Buffer.from('\r'))
this.state.recordDelimiterMaxLength = 1
return 1
}
}else if(chr === nl){
this.options.record_delimiter.push(Buffer.from('\n'))
this.state.recordDelimiterMaxLength = 1
return 1
}
if (this._.line.length > this.options.max_limit_on_data_read) {
return Error(`Row delimiter not found in the file ${JSON.stringify(this.options.rowDelimiter)}`);
return 0
}
__error(msg){
const {skip_lines_with_error} = this.options
const err = new Error(msg)
if(skip_lines_with_error){
this.state.recordHasError = true
this.emit('skip', err)
return undefined
}else{
return err
}
}
// Store un-parsed chars for next call
this._.buf = chars.substr(i);
return null;
};
}
Parser.prototype.error = function(msg) {
var err;
err = Error(msg);
if (!this.options.skip_lines_with_error) {
return err;
} else {
if (!this._.lineHasError) {
this._.lineHasError = true;
this.emit('skip', err);
const parse = function(){
let data, options, callback
for(let i in arguments){
const argument = arguments[i]
const type = typeof argument
if(data === undefined && (typeof argument === 'string' || Buffer.isBuffer(argument))){
data = argument
}else if(options === undefined && isObject(argument)){
options = argument
}else if(callback === undefined && type === 'function'){
callback = argument
}else{
throw new Error(`Invalid argument: got ${JSON.stringify(argument)} at index ${i}`)
}
}
return null;
};
// ## Utils
isObjLiteral = function(_obj) {
var _test;
_test = _obj;
if (typeof _obj !== 'object' || _obj === null || Array.isArray(_obj)) {
return false;
} else {
return (function() {
while (!false) {
if (Object.getPrototypeOf(_test = Object.getPrototypeOf(_test)) === null) {
break;
const parser = new Parser(options)
if(callback){
const records = options === undefined || options.objname === undefined ? [] : {}
parser.on('readable', function(){
let record
while(record = this.read()){
if(options === undefined || options.objname === undefined){
records.push(record)
}else{
records[record[0]] = record[1]
}
}
return Object.getPrototypeOf(_obj === _test);
})();
})
parser.on('error', function(err){
callback(err, undefined, parser.info)
})
parser.on('end', function(){
callback(undefined, records, parser.info)
})
}
};
if(data !== undefined){
parser.write(data)
parser.end()
}
return parser
}
parse.Parser = Parser
module.exports = parse
const isObject = function(obj){
return (typeof obj === 'object' && obj !== null && !Array.isArray(obj))
}
const firstLineToHeadersDefault = function(record){
return record.map(function(field){
return {
header: field,
name: field
}
})
}
const normalizeColumnsArray = function(columns){
for(let i=0; i< columns.length; i++){
const column = columns[i]
if(column === undefined || column === null || column === false){
columns[i] = { disabled: true }
}else if(typeof column === 'string'){
columns[i] = { name: column }
}else if(isObject(column)){
if(typeof column.name !== 'string'){
throw new Error(`Invalid Option columns: property "name" is required at position ${i}`)
}
columns[i] = column
}else{
throw new Error(`Invalid Option columns: expect a string or an object, got ${JSON.stringify(column)} at position ${i}`)
}
}
}

@@ -1,45 +0,22 @@

// Generated by CoffeeScript 2.3.2
// # CSV Parse Sync
// Provides a synchronous alternative to the CSV parser.
const parse = require('.')
// ## Usage
// `const records = parse(data, [options]`
var StringDecoder, parse;
({StringDecoder} = require('string_decoder'));
parse = require('./index');
module.exports = function(data, options = {}) {
var chunks, decoder, err, parser;
chunks = options.objname ? {} : [];
if (data instanceof Buffer) {
decoder = new StringDecoder();
data = decoder.write(data);
module.exports = function(data, options={}){
if(typeof data === 'string'){
data = Buffer.from(data)
}
parser = new parse.Parser(options);
parser.push = function(chunk) {
if (options.objname) {
return chunks[chunk[0]] = chunk[1];
} else {
return chunks.push(chunk);
const records = options && options.objname ? {} : []
const parser = new parse.Parser(options)
parser.push = function(record){
if(options.objname === undefined)
records.push(record)
else{
records[record[0]] = record[1]
}
};
err = parser.__write(data, false);
if (err) {
throw err;
}
if (data instanceof Buffer) {
err = parser.__write(data.end(), true);
if (err) {
throw err;
}
}
err = parser.__flush();
if (err) {
throw err;
}
return chunks;
};
const err1 = parser.__parse(data, false)
if(err1 !== undefined) throw err1
const err2 = parser.__parse(undefined, true)
if(err2 !== undefined) throw err2
return records
}
{
"version": "3.2.0",
"version": "4.0.0",
"name": "csv-parse",

@@ -41,9 +41,14 @@ "description": "CSV parsing implementing the Node.js `stream.Transform` API",

"@babel/preset-env": "^7.1.0",
"@types/mocha": "^5.2.5",
"@types/node": "^10.12.3",
"@types/should": "^13.0.0",
"coffeescript": "^2.3.2",
"csv-generate": "^2.2.2",
"stream-transform": "^1.0.7",
"csv-spectrum": "^1.0.0",
"each": "^1.2.1",
"mocha": "^5.2.0",
"should": "^13.2.3"
"should": "^13.2.3",
"stream-transform": "^1.0.7",
"ts-node": "^7.0.1",
"typescript": "^3.1.6"
},

@@ -53,3 +58,3 @@ "optionalDependencies": {},

"scripts": {
"preversion": "rm -rf lib/*.js && npm test && grep '## Trunk' CHANGELOG.md",
"preversion": "npm test && grep '## Trunk' CHANGELOG.md",
"version": "version=`grep '^ \"version\": ' package.json | sed 's/.*\"\\([0-9\\.]*\\)\".*/\\1/'` && sed -i \"s/## Trunk/## Version $version/\" CHANGELOG.md && git add CHANGELOG.md",

@@ -60,7 +65,6 @@ "postversion": "git push && git push --tags && npm publish",

"major": "npm version major -m 'Bump to version %s'",
"coffee": "coffee -b -o lib src && cd lib && babel *.js -d es5 && cd ..",
"pretest": "coffee -b -o lib src && cd lib && babel *.js -d es5 && cd ..",
"test": "mocha test/**/*.coffee"
"pretest": "cd lib && babel *.js -d es5 && cd ..",
"test": "mocha test/**/*.{coffee,ts}"
},
"types": "./lib/index.d.ts"
}

@@ -10,3 +10,3 @@ [![Build Status](https://api.travis-ci.org/adaltas/node-csv-parse.svg)](https://travis-ci.org/#!/adaltas/node-csv-parse)

* [Options](http://csv.js.org/parse/options/)
* [State properties](http://csv.js.org/parse/state/)
* [Info properties](http://csv.js.org/parse/info/)
* [Common errors](http://csv.js.org/parse/errors/)

@@ -23,4 +23,4 @@ * [Examples](http://csv.js.org/parse/examples/)

* Complete test coverage and samples for inspiration
* no external dependencies
* to be used conjointly with `csv-generate`, `stream-transform` and `csv-stringify`
* BSD License
* No external dependencies
* Work nicely with the [csv-generate](https://csv.js.org/generate/), [stream-transform](https://csv.js.org/transform/) and [csv-stringify](https://csv.js.org/stringify/) packages
* MIT License

@@ -21,5 +21,9 @@

[ '2000-01-01T05:00:00.000Z', {
quoting: false, lines: 1, count: 0, index: 1, header: false, column: 1 } ],
column: 1, empty_lines: 0, header: false, index: 1,
invalid_field_length: 0, quoting: false, lines: 1, records: 0
} ],
[ '2050-11-27T05:00:00.000Z', {
quoting: false, lines: 2, count: 1, index: 1, header: false, column: 1 } ]
column: 1, empty_lines: 0, header: false, index: 1,
invalid_field_length: 0, quoting: false, lines: 2, records: 1
} ]
])

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc