csv-stringify
Advanced tools
Comparing version 5.3.6 to 5.4.0
# Changelog | ||
## Version 5.4.0 | ||
* src: complete require in javascript | ||
* bom: new option | ||
## Version 5.3.6 | ||
@@ -5,0 +10,0 @@ |
@@ -28,2 +28,8 @@ /// <reference types="node" /> | ||
/** | ||
* Prepend the byte order mark (BOM) to the output stream. | ||
*/ | ||
bom?: { | ||
boolean?: Cast<boolean> | ||
} | ||
/** | ||
* Key-value object which defines custom cast for certain data types | ||
@@ -30,0 +36,0 @@ */ |
1035
lib/es5/index.js
"use strict"; | ||
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } | ||
function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); } | ||
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; } | ||
function isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } } | ||
function _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); } | ||
function _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; } | ||
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } | ||
@@ -39,101 +43,17 @@ | ||
// Generated by CoffeeScript 2.4.1 | ||
// # CSV Stringifier | ||
// Please look at the [project documentation](https://csv.js.org/stringify/) for additional | ||
// information. | ||
var Stringifier, castPath, charCodeOfDot, get, getTag, isKey, isObject, isSymbol, reEscapeChar, reIsDeepProp, reIsPlainProp, rePropName, stream, stringToPath, toKey, underscore, util; | ||
stream = require('stream'); | ||
util = require('util'); // ## Usage | ||
// This module export a function as its main entry point and return a transform | ||
// stream. | ||
// Refers to the [official prject documentation](http://csv.js.org/stringify/) | ||
// on how to call this function. | ||
/* | ||
CSV Stringify | ||
module.exports = function () { | ||
var callback, chunks, data, options, stringifier; | ||
Please look at the [project documentation](https://csv.js.org/stringify/) for | ||
additional information. | ||
*/ | ||
var _require = require('stream'), | ||
Transform = _require.Transform; | ||
if (arguments.length === 3) { | ||
data = arguments[0]; | ||
options = arguments[1]; | ||
callback = arguments[2]; | ||
} else if (arguments.length === 2) { | ||
if (Array.isArray(arguments[0])) { | ||
data = arguments[0]; | ||
} else { | ||
options = arguments[0]; | ||
} | ||
var bom_utf8 = Buffer.from([239, 187, 191]); | ||
if (typeof arguments[1] === 'function') { | ||
callback = arguments[1]; | ||
} else { | ||
options = arguments[1]; | ||
} | ||
} else if (arguments.length === 1) { | ||
if (typeof arguments[0] === 'function') { | ||
callback = arguments[0]; | ||
} else if (Array.isArray(arguments[0])) { | ||
data = arguments[0]; | ||
} else { | ||
options = arguments[0]; | ||
} | ||
} | ||
if (options == null) { | ||
options = {}; | ||
} | ||
stringifier = new Stringifier(options); | ||
if (data) { | ||
process.nextTick(function () { | ||
var d, j, len; | ||
for (j = 0, len = data.length; j < len; j++) { | ||
d = data[j]; | ||
stringifier.write(d); | ||
} | ||
return stringifier.end(); | ||
}); | ||
} | ||
if (callback) { | ||
chunks = []; | ||
stringifier.on('readable', function () { | ||
var chunk, results; | ||
results = []; | ||
while (chunk = stringifier.read()) { | ||
results.push(chunks.push(chunk)); | ||
} | ||
return results; | ||
}); | ||
stringifier.on('error', function (err) { | ||
return callback(err); | ||
}); | ||
stringifier.on('end', function () { | ||
return callback(null, chunks.join('')); | ||
}); | ||
} | ||
return stringifier; | ||
}; // You can also use *util.promisify* native function (Node.js 8+) in order to wrap callbacks into promises for more convenient use when source is a readable stream and you are OK with storing entire result set in memory: | ||
// ``` | ||
// const { promisify } = require('util'); | ||
// const csv = require('csv'); | ||
// const stringifyAsync = promisify(csv.stringify); | ||
// //returns promise | ||
// function generateCsv(sourceData) { | ||
// return stringifyAsync(sourceData); | ||
// } | ||
// ``` | ||
// ## `Stringifier([options])` | ||
// Options are documented [here](http://csv.adaltas.com/stringify/). | ||
Stringifier = | ||
var Stringifier = | ||
/*#__PURE__*/ | ||
function (_stream$Transform) { | ||
_inherits(Stringifier, _stream$Transform); | ||
function (_Transform) { | ||
_inherits(Stringifier, _Transform); | ||
@@ -147,184 +67,208 @@ function Stringifier() { | ||
var base, base1, base2, base3, base4, isRegExp, isString, j, k, len, options, quoted_match, ref, v; | ||
_this = _possibleConstructorReturn(this, _getPrototypeOf(Stringifier).call(this, _objectSpread({}, { | ||
writableObjectMode: true | ||
}, {}, opts))); | ||
options = {}; | ||
var options = {}; // Merge with user options | ||
for (k in opts) { | ||
v = opts[k]; // Immutable options and camelcase conversion | ||
for (var opt in opts) { | ||
options[underscore(opt)] = opts[opt]; | ||
} // Normalize option `bom` | ||
options[underscore(k)] = v; | ||
if (options.bom === undefined || options.bom === null || options.bom === false) { | ||
options.bom = false; | ||
} else if (options.bom !== true) { | ||
throw new CsvError('CSV_OPTION_BOOLEAN_INVALID_TYPE', ['option `bom` is optional and must be a boolean value,', "got ".concat(JSON.stringify(options.bom))]); | ||
} // Normalize option `delimiter` | ||
if (options.delimiter === null || options.delimiter === void 0) { | ||
if (options.delimiter === undefined || options.delimiter === null) { | ||
options.delimiter = ','; | ||
} else { | ||
if (Buffer.isBuffer(options.delimiter)) { | ||
options.delimiter = options.delimiter.toString(); | ||
} else if (typeof options.delimiter !== 'string') { | ||
throw new Error("Invalid Option: delimiter must be a buffer or a string, got ".concat(JSON.stringify(options.delimiter))); | ||
} | ||
} else if (Buffer.isBuffer(options.delimiter)) { | ||
options.delimiter = options.delimiter.toString(); | ||
} else if (typeof options.delimiter !== 'string') { | ||
throw new CsvError('CSV_OPTION_DELIMITER_INVALID_TYPE', ['option `delimiter` must be a buffer or a string,', "got ".concat(JSON.stringify(options.delimiter))]); | ||
} // Normalize option `quote` | ||
if (options.quote === null || options.quote === void 0) { | ||
if (options.quote === undefined || options.quote === null) { | ||
options.quote = '"'; | ||
} else { | ||
if (options.quote === true) { | ||
options.quote = '"'; | ||
} else if (options.quote === false) { | ||
options.quote = ''; | ||
} else if (Buffer.isBuffer(options.quote)) { | ||
options.quote = options.quote.toString(); | ||
} else if (typeof options.quote !== 'string') { | ||
throw new Error("Invalid Option: quote must be a boolean, a buffer or a string, got ".concat(JSON.stringify(options.quote))); | ||
} | ||
} else if (options.quote === true) { | ||
options.quote = '"'; | ||
} else if (options.quote === false) { | ||
options.quote = ''; | ||
} else if (Buffer.isBuffer(options.quote)) { | ||
options.quote = options.quote.toString(); | ||
} else if (typeof options.quote !== 'string') { | ||
throw new CsvError('CSV_OPTION_QUOTE_INVALID_TYPE', ['option `quote` must be a boolean, a buffer or a string,', "got ".concat(JSON.stringify(options.quote))]); | ||
} // Normalize option `quoted` | ||
if (options.quoted == null) { | ||
if (options.quoted === undefined || options.quoted === null) { | ||
options.quoted = false; | ||
} | ||
} else {} // todo | ||
// Normalize option `quoted_empty` | ||
if (options.quoted_empty == null) { | ||
options.quoted_empty = void 0; | ||
} | ||
if (options.quoted_string == null) { | ||
if (options.quoted_empty === undefined || options.quoted_empty === null) { | ||
options.quoted_empty = undefined; | ||
} else {} // todo | ||
// Normalize option `quoted_string` | ||
if (options.quoted_string === undefined || options.quoted_string === null) { | ||
options.quoted_string = false; | ||
} | ||
} else {} // todo | ||
// Normalize option `eof` | ||
if (options.eof == null) { | ||
if (options.eof === undefined || options.eof === null) { | ||
options.eof = true; | ||
} // Normalize option `escape` | ||
} else {} // todo | ||
// Normalize option `escape` | ||
if (options.escape === null || options.escape === void 0) { | ||
if (options.escape === undefined || options.escape === null) { | ||
options.escape = '"'; | ||
} else { | ||
if (Buffer.isBuffer(options.escape)) { | ||
options.escape = options.escape.toString(); | ||
} | ||
if (typeof options.escape !== 'string') { | ||
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: escape must be one character, got ".concat(options.escape.length, " characters")); | ||
} | ||
} else if (Buffer.isBuffer(options.escape)) { | ||
options.escape = options.escape.toString(); | ||
} else if (typeof options.escape !== 'string') { | ||
throw new Error("Invalid Option: escape must be a buffer or a string, got ".concat(JSON.stringify(options.escape))); | ||
} | ||
if (options.header == null) { | ||
options.header = false; | ||
} // Normalize the columns option | ||
if (options.escape.length > 1) { | ||
throw new Error("Invalid Option: escape must be one character, got ".concat(options.escape.length, " characters")); | ||
} // Normalize option `header` | ||
options.columns = _this.normalize_columns(options.columns); | ||
if (options.header === undefined || options.header === null) { | ||
options.header = false; | ||
} else {} // todo | ||
// Normalize option `columns` | ||
if (options.cast == null) { | ||
options.cast = {}; | ||
} // Normalize option `quoted_match` | ||
options.columns = _this.normalize_columns(options.columns); // Normalize option `quoted` | ||
if (options.quoted_match === void 0 || options.quoted_match === null || options.quoted_match === false) { | ||
options.quoted_match = null; | ||
} else if (!Array.isArray(options.quoted_match)) { | ||
options.quoted_match = [options.quoted_match]; | ||
} | ||
if (options.quoted === undefined || options.quoted === null) { | ||
options.quoted = false; | ||
} else {} // todo | ||
// Normalize option `cast` | ||
if (options.quoted_match) { | ||
ref = options.quoted_match; | ||
for (j = 0, len = ref.length; j < len; j++) { | ||
quoted_match = ref[j]; | ||
isString = typeof quoted_match === 'string'; | ||
isRegExp = quoted_match instanceof RegExp; | ||
if (options.cast === undefined || options.cast === null) { | ||
options.cast = {}; | ||
} else {} // todo | ||
// Normalize option cast.boolean | ||
if (!isString && !isRegExp) { | ||
throw new Error("Invalid Option: quoted_match must be a string or a regex, got ".concat(JSON.stringify(quoted_match))); | ||
} | ||
} | ||
} | ||
if (options.cast.bool) { | ||
// Backward compatibility | ||
options.cast["boolean"] = options.cast.bool; | ||
} // Custom cast | ||
if (options.cast["boolean"] === undefined || options.cast["boolean"] === null) { | ||
// Cast boolean to string by default | ||
options.cast["boolean"] = function (value) { | ||
return value ? '1' : ''; | ||
}; | ||
} // Normalize option cast.date | ||
if ((base = options.cast)["boolean"] == null) { | ||
base["boolean"] = function (value) { | ||
// Cast boolean to string by default | ||
if (value) { | ||
return '1'; | ||
} else { | ||
return ''; | ||
} | ||
}; | ||
} | ||
if ((base1 = options.cast).date == null) { | ||
base1.date = function (value) { | ||
// Cast date to timestamp string by default | ||
if (options.cast.date === undefined || options.cast.date === null) { | ||
// Cast date to timestamp string by default | ||
options.cast.date = function (value) { | ||
return '' + value.getTime(); | ||
}; | ||
} | ||
} // Normalize option cast.number | ||
if ((base2 = options.cast).number == null) { | ||
base2.number = function (value) { | ||
// Cast number to string using native casting by default | ||
if (options.cast.number === undefined || options.cast.number === null) { | ||
// Cast number to string using native casting by default | ||
options.cast.number = function (value) { | ||
return '' + value; | ||
}; | ||
} | ||
} // Normalize option cast.object | ||
if ((base3 = options.cast).object == null) { | ||
base3.object = function (value) { | ||
// Stringify object as JSON by default | ||
if (options.cast.object === undefined || options.cast.object === null) { | ||
// Stringify object as JSON by default | ||
options.cast.object = function (value) { | ||
return JSON.stringify(value); | ||
}; | ||
} | ||
} // Normalize option cast.string | ||
if ((base4 = options.cast).string == null) { | ||
base4.string = function (value) { | ||
if (options.cast.string === undefined || options.cast.string === null) { | ||
// Leave string untouched | ||
options.cast.string = function (value) { | ||
return value; | ||
}; | ||
} // Normalize option `record_delimiter` | ||
} // Normalize option `quoted_match` | ||
if (options.record_delimiter === void 0 || options.record_delimiter === null) { | ||
if (options.record_delimiter == null) { | ||
options.record_delimiter = '\n'; | ||
if (options.quoted_match === undefined || options.quoted_match === null || options.quoted_match === false) { | ||
options.quoted_match = null; | ||
} else if (!Array.isArray(options.quoted_match)) { | ||
options.quoted_match = [options.quoted_match]; | ||
} | ||
if (options.quoted_match) { | ||
var _iteratorNormalCompletion = true; | ||
var _didIteratorError = false; | ||
var _iteratorError = undefined; | ||
try { | ||
for (var _iterator = options.quoted_match[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { | ||
var quoted_match = _step.value; | ||
var isString = typeof quoted_match === 'string'; | ||
var isRegExp = quoted_match instanceof RegExp; | ||
if (!isString && !isRegExp) { | ||
throw new Error("Invalid Option: quoted_match must be a string or a regex, got ".concat(JSON.stringify(quoted_match))); | ||
} | ||
} | ||
} catch (err) { | ||
_didIteratorError = true; | ||
_iteratorError = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion && _iterator["return"] != null) { | ||
_iterator["return"](); | ||
} | ||
} finally { | ||
if (_didIteratorError) { | ||
throw _iteratorError; | ||
} | ||
} | ||
} | ||
} else { | ||
if (Buffer.isBuffer(options.record_delimiter)) { | ||
options.record_delimiter = options.record_delimiter.toString(); | ||
} else if (typeof options.record_delimiter !== 'string') { | ||
throw new Error("Invalid Option: record_delimiter must be a buffer or a string, got ".concat(JSON.stringify(options.record_delimiter))); | ||
} | ||
} // Normalize option `record_delimiter` | ||
switch (options.record_delimiter) { | ||
case 'auto': | ||
options.record_delimiter = null; | ||
break; | ||
case 'unix': | ||
options.record_delimiter = "\n"; | ||
break; | ||
if (options.record_delimiter === undefined || options.record_delimiter === null) { | ||
options.record_delimiter = '\n'; | ||
} else if (Buffer.isBuffer(options.record_delimiter)) { | ||
options.record_delimiter = options.record_delimiter.toString(); | ||
} else if (typeof options.record_delimiter !== 'string') { | ||
throw new Error("Invalid Option: record_delimiter must be a buffer or a string, got ".concat(JSON.stringify(options.record_delimiter))); | ||
} | ||
case 'mac': | ||
options.record_delimiter = "\r"; | ||
break; | ||
switch (options.record_delimiter) { | ||
case 'auto': | ||
options.record_delimiter = null; | ||
break; | ||
case 'windows': | ||
options.record_delimiter = "\r\n"; | ||
break; | ||
case 'unix': | ||
options.record_delimiter = "\n"; | ||
break; | ||
case 'ascii': | ||
options.record_delimiter = "\x1E"; | ||
break; | ||
case 'mac': | ||
options.record_delimiter = "\r"; | ||
break; | ||
case 'unicode': | ||
options.record_delimiter = "\u2028"; | ||
} | ||
case 'windows': | ||
options.record_delimiter = "\r\n"; | ||
break; | ||
case 'ascii': | ||
options.record_delimiter = "\x1E"; | ||
break; | ||
case 'unicode': | ||
options.record_delimiter = "\u2028"; | ||
break; | ||
} // Expose options | ||
@@ -343,14 +287,14 @@ | ||
if (options.bom === true) { | ||
_this.push(bom_utf8); | ||
} | ||
_assertThisInitialized(_this); | ||
return _this; | ||
} // ## `Stringifier.prototype._transform(chunk, encoding, callback)` | ||
// Implementation of the [transform._transform function](https://nodejs.org/api/stream.html#stream_transform_transform_chunk_encoding_callback). | ||
} | ||
_createClass(Stringifier, [{ | ||
key: "_transform", | ||
value: function _transform(chunk, encoding, callback) { | ||
var base, e; | ||
if (this.state.stop === true) { | ||
@@ -361,3 +305,3 @@ return; | ||
if (!(Array.isArray(chunk) || _typeof(chunk) === 'object')) { | ||
if (!Array.isArray(chunk) && _typeof(chunk) !== 'object') { | ||
this.state.stop = true; | ||
@@ -374,21 +318,18 @@ return callback(Error("Invalid Record: expect an array or an object, got ".concat(JSON.stringify(chunk)))); | ||
} | ||
} else { | ||
if ((base = this.options).columns == null) { | ||
base.columns = this.normalize_columns(Object.keys(chunk)); | ||
} | ||
} else if (this.options.columns === undefined || this.options.columns === null) { | ||
this.options.columns = this.normalize_columns(Object.keys(chunk)); | ||
} | ||
} | ||
} // Emit the header | ||
if (this.info.records === 0) { | ||
// Emit the header | ||
this.headers(); | ||
} | ||
} // Emit and stringify the record if an object or an array | ||
try { | ||
// Emit and stringify the record if an object or an array | ||
this.emit('record', chunk, this.info.records); | ||
} catch (error) { | ||
e = error; | ||
} catch (err) { | ||
this.state.stop = true; | ||
return this.emit('error', e); | ||
return this.emit('error', err); | ||
} // Convert the record into a string | ||
@@ -400,17 +341,17 @@ | ||
if (chunk == null) { | ||
if (chunk === undefined) { | ||
return; | ||
} else { | ||
chunk = chunk + this.options.record_delimiter; | ||
} | ||
chunk = chunk + this.options.record_delimiter; | ||
} else { | ||
chunk = this.stringify(chunk); | ||
if (chunk == null) { | ||
if (chunk === undefined) { | ||
return; | ||
} else { | ||
if (this.options.header || this.info.records) { | ||
chunk = this.options.record_delimiter + chunk; | ||
} | ||
} | ||
if (this.options.header || this.info.records) { | ||
chunk = this.options.record_delimiter + chunk; | ||
} | ||
} // Emit the csv | ||
@@ -421,6 +362,5 @@ | ||
this.push(chunk); | ||
return callback(); | ||
} // ## `Stringifier.prototype._flush(callback)` | ||
// Implementation of the [transform._flush function](https://nodejs.org/api/stream.html#stream_transform_flush_callback). | ||
callback(); | ||
null; | ||
} | ||
}, { | ||
@@ -433,11 +373,11 @@ key: "_flush", | ||
return callback(); | ||
} // ## `Stringifier.prototype.stringify(line)` | ||
// Convert a line to a string. Line may be an object, an array or a string. | ||
callback(); | ||
null; | ||
} | ||
}, { | ||
key: "stringify", | ||
value: function stringify(chunk) { | ||
var _this2 = this; | ||
var chunkIsHeader = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; | ||
var column, columns, containsEscape, containsQuote, containsRowDelimiter, containsdelimiter, csvrecord, delimiter, err, escape, field, header, i, j, l, len, m, options, quote, quoted, quotedMatch, quotedString, quoted_empty, quoted_match, quoted_string, record, record_delimiter, ref, ref1, regexp, shouldQuote, value; | ||
@@ -448,11 +388,11 @@ if (_typeof(chunk) !== 'object') { | ||
var _this$options = this.options; | ||
columns = _this$options.columns; | ||
header = _this$options.header; | ||
record = []; // Record is an array | ||
var _this$options = this.options, | ||
columns = _this$options.columns, | ||
header = _this$options.header; | ||
var record = []; // Record is an array | ||
if (Array.isArray(chunk)) { | ||
// We are getting an array but the user has specified output columns. In | ||
// this case, we respect the columns indexes | ||
if (columns) { | ||
// We are getting an array but the user has specified output columns. In | ||
// this case, we respect the columns indexes | ||
chunk.splice(columns.length); | ||
@@ -462,17 +402,15 @@ } // Cast record elements | ||
for (i = j = 0, len = chunk.length; j < len; i = ++j) { | ||
field = chunk[i]; | ||
for (var _i = 0; _i < chunk.length; _i++) { | ||
var field = chunk[_i]; | ||
var _this$__cast = this.__cast(field, { | ||
index: i, | ||
column: i, | ||
index: _i, | ||
column: _i, | ||
records: this.info.records, | ||
header: chunkIsHeader | ||
}); | ||
}), | ||
_this$__cast2 = _slicedToArray(_this$__cast, 2), | ||
err = _this$__cast2[0], | ||
value = _this$__cast2[1]; | ||
var _this$__cast2 = _slicedToArray(_this$__cast, 2); | ||
err = _this$__cast2[0]; | ||
value = _this$__cast2[1]; | ||
if (err) { | ||
@@ -483,51 +421,67 @@ this.emit('error', err); | ||
record[i] = [value, field]; | ||
} | ||
record[_i] = [value, field]; | ||
} // Record is a literal object | ||
} else { | ||
// Record is a literal object | ||
if (columns) { | ||
for (i = l = 0, ref = columns.length; 0 <= ref ? l < ref : l > ref; i = 0 <= ref ? ++l : --l) { | ||
field = get(chunk, columns[i].key); | ||
for (var _i2 = 0; _i2 < columns.length; _i2++) { | ||
var _field = get(chunk, columns[_i2].key); | ||
var _this$__cast3 = this.__cast(field, { | ||
index: i, | ||
column: columns[i].key, | ||
var _this$__cast3 = this.__cast(_field, { | ||
index: _i2, | ||
column: columns[_i2].key, | ||
records: this.info.records, | ||
header: chunkIsHeader | ||
}); | ||
}), | ||
_this$__cast4 = _slicedToArray(_this$__cast3, 2), | ||
_err = _this$__cast4[0], | ||
_value = _this$__cast4[1]; | ||
var _this$__cast4 = _slicedToArray(_this$__cast3, 2); | ||
err = _this$__cast4[0]; | ||
value = _this$__cast4[1]; | ||
if (err) { | ||
this.emit('error', err); | ||
if (_err) { | ||
this.emit('error', _err); | ||
return; | ||
} | ||
record[i] = [value, field]; | ||
record[_i2] = [_value, _field]; | ||
} | ||
} else { | ||
for (column in chunk) { | ||
field = chunk[column]; | ||
var _iteratorNormalCompletion2 = true; | ||
var _didIteratorError2 = false; | ||
var _iteratorError2 = undefined; | ||
var _this$__cast5 = this.__cast(field, { | ||
index: i, | ||
column: columns[i].key, | ||
records: this.info.records, | ||
header: chunkIsHeader | ||
}); | ||
try { | ||
for (var _iterator2 = chunk[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { | ||
var column = _step2.value; | ||
var _field2 = chunk[column]; | ||
var _this$__cast6 = _slicedToArray(_this$__cast5, 2); | ||
var _this$__cast5 = this.__cast(_field2, { | ||
index: i, | ||
column: columns[i].key, | ||
records: this.info.records, | ||
header: chunkIsHeader | ||
}), | ||
_this$__cast6 = _slicedToArray(_this$__cast5, 2), | ||
_err2 = _this$__cast6[0], | ||
_value2 = _this$__cast6[1]; | ||
err = _this$__cast6[0]; | ||
value = _this$__cast6[1]; | ||
if (_err2) { | ||
this.emit('error', _err2); | ||
return; | ||
} | ||
if (err) { | ||
this.emit('error', err); | ||
return; | ||
record.push([_value2, _field2]); | ||
} | ||
record.push([value, field]); | ||
} catch (err) { | ||
_didIteratorError2 = true; | ||
_iteratorError2 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion2 && _iterator2["return"] != null) { | ||
_iterator2["return"](); | ||
} | ||
} finally { | ||
if (_didIteratorError2) { | ||
throw _iteratorError2; | ||
} | ||
} | ||
} | ||
@@ -537,52 +491,62 @@ } | ||
csvrecord = ''; | ||
var csvrecord = ''; | ||
for (i = m = 0, ref1 = record.length; 0 <= ref1 ? m < ref1 : m > ref1; i = 0 <= ref1 ? ++m : --m) { | ||
var _record$i = _slicedToArray(record[i], 2); | ||
var _loop = function _loop(_i3) { | ||
var options = void 0; | ||
value = _record$i[0]; | ||
field = _record$i[1]; | ||
var _record$_i = _slicedToArray(record[_i3], 2), | ||
value = _record$_i[0], | ||
field = _record$_i[1]; | ||
if (typeof value === 'string') { | ||
options = this.options; | ||
if (typeof value === "string") { | ||
options = _this2.options; | ||
} else if (isObject(value)) { | ||
var _value = value; | ||
value = _value.value; | ||
options = _objectWithoutProperties(_value, ["value"]); | ||
// let { value, ...options } = value | ||
options = value; | ||
value = options.value; | ||
if (!(typeof value === 'string' || value === void 0 || value === null)) { | ||
this.emit('error', Error("Invalid Casting Value: returned value must return a string, null or undefined, got ".concat(JSON.stringify(value)))); | ||
return; | ||
if (typeof value !== "string" && value !== undefined && value !== null) { | ||
_this2.emit("error", Error("Invalid Casting Value: returned value must return a string, null or undefined, got ".concat(JSON.stringify(value)))); | ||
return { | ||
v: void 0 | ||
}; | ||
} | ||
options = _objectSpread({}, this.options, {}, options); | ||
} else if (value === void 0 || value === null) { | ||
options = this.options; | ||
options = _objectSpread({}, _this2.options, {}, options); | ||
} else if (value === undefined || value === null) { | ||
options = _this2.options; | ||
} else { | ||
this.emit('error', Error("Invalid Casting Value: returned value must return a string, an object, null or undefined, got ".concat(JSON.stringify(value)))); | ||
return; | ||
_this2.emit("error", Error("Invalid Casting Value: returned value must return a string, an object, null or undefined, got ".concat(JSON.stringify(value)))); | ||
return { | ||
v: void 0 | ||
}; | ||
} | ||
var _options = options; | ||
delimiter = _options.delimiter; | ||
escape = _options.escape; | ||
quote = _options.quote; | ||
quoted = _options.quoted; | ||
quoted_empty = _options.quoted_empty; | ||
quoted_string = _options.quoted_string; | ||
quoted_match = _options.quoted_match; | ||
record_delimiter = _options.record_delimiter; | ||
var _options = options, | ||
delimiter = _options.delimiter, | ||
escape = _options.escape, | ||
quote = _options.quote, | ||
quoted = _options.quoted, | ||
quoted_empty = _options.quoted_empty, | ||
quoted_string = _options.quoted_string, | ||
quoted_match = _options.quoted_match, | ||
record_delimiter = _options.record_delimiter; | ||
if (value) { | ||
if (typeof value !== 'string') { | ||
this.emit('error', Error("Formatter must return a string, null or undefined, got ".concat(JSON.stringify(value)))); | ||
return null; | ||
_this2.emit("error", Error("Formatter must return a string, null or undefined, got ".concat(JSON.stringify(value)))); | ||
return { | ||
v: null | ||
}; | ||
} | ||
containsdelimiter = delimiter.length && value.indexOf(delimiter) >= 0; | ||
containsQuote = quote !== '' && value.indexOf(quote) >= 0; | ||
containsEscape = value.indexOf(escape) >= 0 && escape !== quote; | ||
containsRowDelimiter = value.indexOf(record_delimiter) >= 0; | ||
quotedString = quoted_string && typeof field === 'string'; | ||
quotedMatch = quoted_match && typeof field === 'string' && quoted_match.filter(function (quoted_match) { | ||
var containsdelimiter = delimiter.length && value.indexOf(delimiter) >= 0; | ||
var containsQuote = quote !== '' && value.indexOf(quote) >= 0; | ||
var containsEscape = value.indexOf(escape) >= 0 && escape !== quote; | ||
var containsRecordDelimiter = value.indexOf(record_delimiter) >= 0; | ||
var quotedString = quoted_string && typeof field === 'string'; | ||
var quotedMatch = quoted_match && typeof field === 'string' && quoted_match.filter(function (quoted_match) { | ||
if (typeof quoted_match === 'string') { | ||
@@ -595,6 +559,6 @@ return value.indexOf(quoted_match) !== -1; | ||
quotedMatch = quotedMatch && quotedMatch.length > 0; | ||
shouldQuote = containsQuote === true || containsdelimiter || containsRowDelimiter || quoted || quotedString || quotedMatch; | ||
var shouldQuote = containsQuote === true || containsdelimiter || containsRecordDelimiter || quoted || quotedString || quotedMatch; | ||
if (shouldQuote === true && containsEscape === true) { | ||
regexp = escape === '\\' ? new RegExp(escape + escape, 'g') : new RegExp(escape, 'g'); | ||
var regexp = escape === '\\' ? new RegExp(escape + escape, 'g') : new RegExp(escape, 'g'); | ||
value = value.replace(regexp, escape + escape); | ||
@@ -604,4 +568,5 @@ } | ||
if (containsQuote === true) { | ||
regexp = new RegExp(quote, 'g'); | ||
value = value.replace(regexp, escape + quote); | ||
var _regexp = new RegExp(quote, 'g'); | ||
value = value.replace(_regexp, escape + quote); | ||
} | ||
@@ -614,29 +579,31 @@ | ||
csvrecord += value; | ||
} else if (quoted_empty === true || quoted_empty == null && field === '' && quoted_string !== false) { | ||
} else if (quoted_empty === true || field === '' && quoted_string === true && quoted_empty !== false) { | ||
csvrecord += quote + quote; | ||
} | ||
if (i !== record.length - 1) { | ||
if (_i3 !== record.length - 1) { | ||
csvrecord += delimiter; | ||
} | ||
}; | ||
for (var _i3 = 0; _i3 < record.length; _i3++) { | ||
var _ret = _loop(_i3); | ||
if (_typeof(_ret) === "object") return _ret.v; | ||
} | ||
return csvrecord; | ||
} // ## `Stringifier.prototype.headers` | ||
// Print the header line if the option "header" is "true". | ||
} | ||
}, { | ||
key: "headers", | ||
value: function headers() { | ||
var headers; | ||
if (!this.options.header) { | ||
if (this.options.header === false) { | ||
return; | ||
} | ||
if (!this.options.columns) { | ||
if (this.options.columns === undefined) { | ||
return; | ||
} | ||
headers = this.options.columns.map(function (column) { | ||
var headers = this.options.columns.map(function (column) { | ||
return column.header; | ||
@@ -651,3 +618,3 @@ }); | ||
return this.push(headers); | ||
this.push(headers); | ||
} | ||
@@ -657,4 +624,3 @@ }, { | ||
value: function __cast(value, context) { | ||
var err, type; | ||
type = _typeof(value); | ||
var type = _typeof(value); | ||
@@ -664,128 +630,264 @@ try { | ||
// Fine for 99% of the cases | ||
return [void 0, this.options.cast.string(value, context)]; | ||
return [undefined, this.options.cast.string(value, context)]; | ||
} else if (type === 'number') { | ||
return [void 0, this.options.cast.number(value, context)]; | ||
return [undefined, this.options.cast.number(value, context)]; | ||
} else if (type === 'boolean') { | ||
return [void 0, this.options.cast["boolean"](value, context)]; | ||
return [undefined, this.options.cast["boolean"](value, context)]; | ||
} else if (value instanceof Date) { | ||
return [void 0, this.options.cast.date(value, context)]; | ||
return [undefined, this.options.cast.date(value, context)]; | ||
} else if (type === 'object' && value !== null) { | ||
return [void 0, this.options.cast.object(value, context)]; | ||
return [undefined, this.options.cast.object(value, context)]; | ||
} else { | ||
return [void 0, value, value]; | ||
return [undefined, value, value]; | ||
} | ||
} catch (error) { | ||
err = error; | ||
} catch (err) { | ||
return [err]; | ||
} | ||
} // ## `Stringifier.prototype.normalize_columns` | ||
} | ||
}, { | ||
key: "normalize_columns", | ||
value: function normalize_columns(columns) { | ||
var column, k, v; | ||
if (columns === undefined || columns === null) { | ||
return undefined; | ||
} | ||
if (columns == null) { | ||
return null; | ||
if (_typeof(columns) !== 'object') { | ||
throw Error('Invalid option "columns": expect an array or an object'); | ||
} | ||
if (columns != null) { | ||
if (_typeof(columns) !== 'object') { | ||
throw Error('Invalid option "columns": expect an array or an object'); | ||
if (!Array.isArray(columns)) { | ||
var newcolumns = []; | ||
for (var k in columns) { | ||
newcolumns.push({ | ||
key: k, | ||
header: columns[k] | ||
}); | ||
} | ||
if (!Array.isArray(columns)) { | ||
columns = function () { | ||
var results; | ||
results = []; | ||
columns = newcolumns; | ||
} else { | ||
var _newcolumns = []; | ||
var _iteratorNormalCompletion3 = true; | ||
var _didIteratorError3 = false; | ||
var _iteratorError3 = undefined; | ||
for (k in columns) { | ||
v = columns[k]; | ||
results.push({ | ||
key: k, | ||
header: v | ||
try { | ||
for (var _iterator3 = columns[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { | ||
var column = _step3.value; | ||
if (typeof column === 'string') { | ||
_newcolumns.push({ | ||
key: column, | ||
header: column | ||
}); | ||
} else if (_typeof(column) === 'object' && column !== undefined && !Array.isArray(column)) { | ||
if (!column.key) { | ||
throw Error('Invalid column definition: property "key" is required'); | ||
} | ||
if (column.header === undefined) { | ||
column.header = column.key; | ||
} | ||
_newcolumns.push(column); | ||
} else { | ||
throw Error('Invalid column definition: expect a string or an object'); | ||
} | ||
} | ||
} catch (err) { | ||
_didIteratorError3 = true; | ||
_iteratorError3 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion3 && _iterator3["return"] != null) { | ||
_iterator3["return"](); | ||
} | ||
} finally { | ||
if (_didIteratorError3) { | ||
throw _iteratorError3; | ||
} | ||
} | ||
} | ||
return results; | ||
}(); | ||
} else { | ||
columns = function () { | ||
var j, len, results; | ||
results = []; | ||
columns = _newcolumns; | ||
} | ||
for (j = 0, len = columns.length; j < len; j++) { | ||
column = columns[j]; | ||
return columns; | ||
} | ||
}]); | ||
if (typeof column === 'string') { | ||
results.push({ | ||
key: column, | ||
header: column | ||
}); | ||
} else if (_typeof(column) === 'object' && column != null && !Array.isArray(column)) { | ||
if (!column.key) { | ||
throw Error('Invalid column definition: property "key" is required'); | ||
} | ||
return Stringifier; | ||
}(Transform); | ||
if (column.header == null) { | ||
column.header = column.key; | ||
} | ||
var stringify = function stringify() { | ||
var data, options, callback; | ||
results.push(column); | ||
} else { | ||
throw Error('Invalid column definition: expect a string or an object'); | ||
} | ||
for (var _i4 in arguments) { | ||
var argument = arguments[_i4]; | ||
var _type = _typeof(argument); | ||
if (data === undefined && Array.isArray(argument)) { | ||
data = argument; | ||
} else if (options === undefined && isObject(argument)) { | ||
options = argument; | ||
} else if (callback === undefined && _type === 'function') { | ||
callback = argument; | ||
} else { | ||
throw new CsvError('CSV_INVALID_ARGUMENT', ['Invalid argument:', "got ".concat(JSON.stringify(argument), " at index ").concat(_i4)]); | ||
} | ||
} | ||
var stringifier = new Stringifier(options); | ||
if (callback) { | ||
var chunks = []; | ||
stringifier.on('readable', function () { | ||
var chunk; | ||
while ((chunk = this.read()) !== null) { | ||
chunks.push(chunk); | ||
} | ||
}); | ||
stringifier.on('error', function (err) { | ||
callback(err); | ||
}); | ||
stringifier.on('end', function () { | ||
callback(undefined, chunks.join('')); | ||
}); | ||
} | ||
if (data !== undefined) { | ||
// Give a chance for events to be registered later | ||
if (typeof setImmediate === 'function') { | ||
setImmediate(function () { | ||
var _iteratorNormalCompletion4 = true; | ||
var _didIteratorError4 = false; | ||
var _iteratorError4 = undefined; | ||
try { | ||
for (var _iterator4 = data[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) { | ||
var record = _step4.value; | ||
stringifier.write(record); | ||
} | ||
} catch (err) { | ||
_didIteratorError4 = true; | ||
_iteratorError4 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion4 && _iterator4["return"] != null) { | ||
_iterator4["return"](); | ||
} | ||
} finally { | ||
if (_didIteratorError4) { | ||
throw _iteratorError4; | ||
} | ||
} | ||
} | ||
return results; | ||
}(); | ||
stringifier.end(); | ||
}); | ||
} else { | ||
var _iteratorNormalCompletion5 = true; | ||
var _didIteratorError5 = false; | ||
var _iteratorError5 = undefined; | ||
try { | ||
for (var _iterator5 = data[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) { | ||
var record = _step5.value; | ||
stringifier.write(record); | ||
} | ||
} catch (err) { | ||
_didIteratorError5 = true; | ||
_iteratorError5 = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion5 && _iterator5["return"] != null) { | ||
_iterator5["return"](); | ||
} | ||
} finally { | ||
if (_didIteratorError5) { | ||
throw _iteratorError5; | ||
} | ||
} | ||
} | ||
return columns; | ||
stringifier.end(); | ||
} | ||
}]); | ||
} | ||
return Stringifier; | ||
}(stream.Transform); | ||
return stringifier; | ||
}; | ||
module.exports.Stringifier = Stringifier; | ||
var CsvError = | ||
/*#__PURE__*/ | ||
function (_Error) { | ||
_inherits(CsvError, _Error); | ||
isObject = function isObject(obj) { | ||
function CsvError(code, message) { | ||
var _this3; | ||
_classCallCheck(this, CsvError); | ||
if (Array.isArray(message)) message = message.join(' '); | ||
_this3 = _possibleConstructorReturn(this, _getPrototypeOf(CsvError).call(this, message)); | ||
if (Error.captureStackTrace !== undefined) { | ||
Error.captureStackTrace(_assertThisInitialized(_this3), CsvError); | ||
} | ||
_this3.code = code; | ||
for (var _len = arguments.length, contexts = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { | ||
contexts[_key - 2] = arguments[_key]; | ||
} | ||
for (var _i5 = 0, _contexts = contexts; _i5 < _contexts.length; _i5++) { | ||
var context = _contexts[_i5]; | ||
for (var key in context) { | ||
var value = context[key]; | ||
_this3[key] = Buffer.isBuffer(value) ? value.toString() : value == null ? value : JSON.parse(JSON.stringify(value)); | ||
} | ||
} | ||
return _this3; | ||
} | ||
return CsvError; | ||
}(_wrapNativeSuper(Error)); | ||
stringify.Stringifier = Stringifier; | ||
stringify.CsvError = CsvError; | ||
module.exports = stringify; | ||
var isObject = function isObject(obj) { | ||
return _typeof(obj) === 'object' && obj !== null && !Array.isArray(obj); | ||
}; | ||
underscore = function underscore(str) { | ||
return str.replace(/([A-Z])/g, function (_, match, index) { | ||
var underscore = function underscore(str) { | ||
return str.replace(/([A-Z])/g, function (_, match) { | ||
return '_' + match.toLowerCase(); | ||
}); | ||
}; // ## Lodash implementation of `get` | ||
}; // Lodash implementation of `get` | ||
charCodeOfDot = '.'.charCodeAt(0); | ||
reEscapeChar = /\\(\\)?/g; // Match anything that isn't a dot or bracket. | ||
// Or match property names within brackets. | ||
// Match a non-string expression. | ||
// Or match strings (supports escaping characters). | ||
// Or match "" as the space between consecutive dots or empty brackets. | ||
var charCodeOfDot = '.'.charCodeAt(0); | ||
var reEscapeChar = /\\(\\)?/g; | ||
var rePropName = RegExp( // Match anything that isn't a dot or bracket. | ||
'[^.[\\]]+' + '|' + // Or match property names within brackets. | ||
'\\[(?:' + // Match a non-string expression. | ||
'([^"\'][^[]*)' + '|' + // Or match strings (supports escaping characters). | ||
'(["\'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2' + ')\\]' + '|' + // Or match "" as the space between consecutive dots or empty brackets. | ||
'(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))', 'g'); | ||
var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/; | ||
var reIsPlainProp = /^\w*$/; | ||
rePropName = RegExp('[^.[\\]]+' + '|' + '\\[(?:' + '([^"\'][^[]*)' + '|' + '(["\'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2' + ')\\]' + '|' + '(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))', 'g'); | ||
reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/; | ||
reIsPlainProp = /^\w*$/; | ||
getTag = function getTag(value) { | ||
if (value != null) { | ||
if (value === void 0) { | ||
'[object Undefined]'; | ||
} else { | ||
'[object Null]'; | ||
} | ||
} | ||
var getTag = function getTag(value) { | ||
if (!value) value === undefined ? '[object Undefined]' : '[object Null]'; | ||
return Object.prototype.toString.call(value); | ||
}; | ||
isKey = function isKey(value, object) { | ||
var type; | ||
var isKey = function isKey(value, object) { | ||
if (Array.isArray(value)) { | ||
@@ -795,5 +897,5 @@ return false; | ||
type = _typeof(value); | ||
var type = _typeof(value); | ||
if (type === 'number' || type === 'symbol' || type === 'boolean' || value == null || isSymbol(value)) { | ||
if (type === 'number' || type === 'symbol' || type === 'boolean' || !value || isSymbol(value)) { | ||
return true; | ||
@@ -805,11 +907,9 @@ } | ||
isSymbol = function isSymbol(value) { | ||
var type; | ||
var isSymbol = function isSymbol(value) { | ||
type = _typeof(value); | ||
return type === 'symbol' || type === 'object' && value != null && getTag(value) === '[object Symbol]'; | ||
return type === 'symbol' || type === 'object' && value && getTag(value) === '[object Symbol]'; | ||
}; | ||
stringToPath = function stringToPath(string) { | ||
var result; | ||
result = []; | ||
var stringToPath = function stringToPath(string) { | ||
var result = []; | ||
@@ -821,4 +921,3 @@ if (string.charCodeAt(0) === charCodeOfDot) { | ||
string.replace(rePropName, function (match, expression, quote, subString) { | ||
var key; | ||
key = match; | ||
var key = match; | ||
@@ -831,3 +930,3 @@ if (quote) { | ||
return result.push(key); | ||
result.push(key); | ||
}); | ||
@@ -837,32 +936,20 @@ return result; | ||
castPath = function castPath(value, object) { | ||
var castPath = function castPath(value, object) { | ||
if (Array.isArray(value)) { | ||
return value; | ||
} else { | ||
if (isKey(value, object)) { | ||
return [value]; | ||
} else { | ||
return stringToPath(value); | ||
} | ||
return isKey(value, object) ? [value] : stringToPath(value); | ||
} | ||
}; | ||
toKey = function toKey(value) { | ||
var ref, result; | ||
if (typeof value === 'string' || isSymbol(value)) { | ||
return value; | ||
} | ||
result = "".concat(value); | ||
return (ref = result === '0' && 1 / value === -INFINITY) != null ? ref : { | ||
'-0': result | ||
}; | ||
var toKey = function toKey(value) { | ||
if (typeof value === 'string' || isSymbol(value)) return value; | ||
var result = "".concat(value); | ||
return result == '0' && 1 / value == -INFINITY ? '-0' : result; | ||
}; | ||
get = function get(object, path) { | ||
var index, length; | ||
path = Array.isArray(path) ? path : castPath(path, object); | ||
index = 0; | ||
length = path.length; | ||
var get = function get(object, path) { | ||
path = castPath(path, object); | ||
var index = 0; | ||
var length = path.length; | ||
@@ -873,7 +960,3 @@ while (object != null && index < length) { | ||
if (index && index === length) { | ||
return object; | ||
} else { | ||
return void 0; | ||
} | ||
return index && index === length ? object : undefined; | ||
}; |
"use strict"; | ||
// Generated by CoffeeScript 2.4.1 | ||
// # CSV Stringify Sync | ||
// Provides a synchronous alternative to the CSV stringifier. | ||
// ## Usage | ||
// `const csv = stringify(records, [options]` | ||
var StringDecoder, stringify; | ||
var stringify = require('.'); | ||
var _require = require('string_decoder'); | ||
var _require = require('string_decoder'), | ||
StringDecoder = _require.StringDecoder; | ||
StringDecoder = _require.StringDecoder; | ||
stringify = require('./index'); | ||
module.exports = function (records) { | ||
var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
var data, decoder, i, len, record, stringifier; | ||
data = []; | ||
var data = []; | ||
if (records instanceof Buffer) { | ||
decoder = new StringDecoder(); | ||
if (Buffer.isBuffer(records)) { | ||
var decoder = new StringDecoder(); | ||
records = decoder.write(records); | ||
} | ||
stringifier = new stringify.Stringifier(options); | ||
var stringifier = new stringify.Stringifier(options); | ||
stringifier.push = function (record) { | ||
if (record) { | ||
return data.push(record.toString()); | ||
data.push(record.toString()); | ||
} | ||
}; | ||
for (i = 0, len = records.length; i < len; i++) { | ||
record = records[i]; | ||
stringifier.write(record); | ||
var _iteratorNormalCompletion = true; | ||
var _didIteratorError = false; | ||
var _iteratorError = undefined; | ||
try { | ||
for (var _iterator = records[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { | ||
var record = _step.value; | ||
stringifier.write(record); | ||
} | ||
} catch (err) { | ||
_didIteratorError = true; | ||
_iteratorError = err; | ||
} finally { | ||
try { | ||
if (!_iteratorNormalCompletion && _iterator["return"] != null) { | ||
_iterator["return"](); | ||
} | ||
} finally { | ||
if (_didIteratorError) { | ||
throw _iteratorError; | ||
} | ||
} | ||
} | ||
@@ -37,0 +48,0 @@ |
@@ -28,2 +28,8 @@ /// <reference types="node" /> | ||
/** | ||
* Prepend the byte order mark (BOM) to the output stream. | ||
*/ | ||
bom?: { | ||
boolean?: Cast<boolean> | ||
} | ||
/** | ||
* Key-value object which defines custom cast for certain data types | ||
@@ -30,0 +36,0 @@ */ |
1072
lib/index.js
@@ -1,673 +0,611 @@ | ||
// Generated by CoffeeScript 2.4.1 | ||
// # CSV Stringifier | ||
// Please look at the [project documentation](https://csv.js.org/stringify/) for additional | ||
// information. | ||
var Stringifier, castPath, charCodeOfDot, get, getTag, isKey, isObject, isSymbol, reEscapeChar, reIsDeepProp, reIsPlainProp, rePropName, stream, stringToPath, toKey, underscore, util; | ||
/* | ||
CSV Stringify | ||
stream = require('stream'); | ||
Please look at the [project documentation](https://csv.js.org/stringify/) for | ||
additional information. | ||
*/ | ||
util = require('util'); | ||
const { Transform } = require('stream') | ||
const bom_utf8 = Buffer.from([239, 187, 191]) | ||
// ## Usage | ||
// This module export a function as its main entry point and return a transform | ||
// stream. | ||
// Refers to the [official prject documentation](http://csv.js.org/stringify/) | ||
// on how to call this function. | ||
module.exports = function() { | ||
var callback, chunks, data, options, stringifier; | ||
if (arguments.length === 3) { | ||
data = arguments[0]; | ||
options = arguments[1]; | ||
callback = arguments[2]; | ||
} else if (arguments.length === 2) { | ||
if (Array.isArray(arguments[0])) { | ||
data = arguments[0]; | ||
} else { | ||
options = arguments[0]; | ||
class Stringifier extends Transform { | ||
constructor(opts = {}){ | ||
super({...{writableObjectMode: true}, ...opts}) | ||
const options = {} | ||
// Merge with user options | ||
for(let opt in opts){ | ||
options[underscore(opt)] = opts[opt] | ||
} | ||
if (typeof arguments[1] === 'function') { | ||
callback = arguments[1]; | ||
} else { | ||
options = arguments[1]; | ||
// Normalize option `bom` | ||
if(options.bom === undefined || options.bom === null || options.bom === false){ | ||
options.bom = false | ||
}else if(options.bom !== true){ | ||
throw new CsvError('CSV_OPTION_BOOLEAN_INVALID_TYPE', [ | ||
'option `bom` is optional and must be a boolean value,', | ||
`got ${JSON.stringify(options.bom)}` | ||
]) | ||
} | ||
} else if (arguments.length === 1) { | ||
if (typeof arguments[0] === 'function') { | ||
callback = arguments[0]; | ||
} else if (Array.isArray(arguments[0])) { | ||
data = arguments[0]; | ||
} else { | ||
options = arguments[0]; | ||
} | ||
} | ||
if (options == null) { | ||
options = {}; | ||
} | ||
stringifier = new Stringifier(options); | ||
if (data) { | ||
process.nextTick(function() { | ||
var d, j, len; | ||
for (j = 0, len = data.length; j < len; j++) { | ||
d = data[j]; | ||
stringifier.write(d); | ||
} | ||
return stringifier.end(); | ||
}); | ||
} | ||
if (callback) { | ||
chunks = []; | ||
stringifier.on('readable', function() { | ||
var chunk, results; | ||
results = []; | ||
while (chunk = stringifier.read()) { | ||
results.push(chunks.push(chunk)); | ||
} | ||
return results; | ||
}); | ||
stringifier.on('error', function(err) { | ||
return callback(err); | ||
}); | ||
stringifier.on('end', function() { | ||
return callback(null, chunks.join('')); | ||
}); | ||
} | ||
return stringifier; | ||
}; | ||
// You can also use *util.promisify* native function (Node.js 8+) in order to wrap callbacks into promises for more convenient use when source is a readable stream and you are OK with storing entire result set in memory: | ||
// ``` | ||
// const { promisify } = require('util'); | ||
// const csv = require('csv'); | ||
// const stringifyAsync = promisify(csv.stringify); | ||
// //returns promise | ||
// function generateCsv(sourceData) { | ||
// return stringifyAsync(sourceData); | ||
// } | ||
// ``` | ||
// ## `Stringifier([options])` | ||
// Options are documented [here](http://csv.adaltas.com/stringify/). | ||
Stringifier = class Stringifier extends stream.Transform { | ||
constructor(opts = {}) { | ||
var base, base1, base2, base3, base4, isRegExp, isString, j, k, len, options, quoted_match, ref, v; | ||
super({...{ | ||
writableObjectMode: true | ||
}, ...opts}); | ||
options = {}; | ||
for (k in opts) { | ||
v = opts[k]; | ||
// Immutable options and camelcase conversion | ||
options[underscore(k)] = v; | ||
} | ||
// Normalize option `delimiter` | ||
if (options.delimiter === null || options.delimiter === void 0) { | ||
options.delimiter = ','; | ||
} else { | ||
if (Buffer.isBuffer(options.delimiter)) { | ||
options.delimiter = options.delimiter.toString(); | ||
} else if (typeof options.delimiter !== 'string') { | ||
throw new Error(`Invalid Option: delimiter must be a buffer or a string, got ${JSON.stringify(options.delimiter)}`); | ||
} | ||
if(options.delimiter === undefined || options.delimiter === null){ | ||
options.delimiter = ',' | ||
}else if(Buffer.isBuffer(options.delimiter)){ | ||
options.delimiter = options.delimiter.toString() | ||
}else if(typeof options.delimiter !== 'string'){ | ||
throw new CsvError('CSV_OPTION_DELIMITER_INVALID_TYPE', [ | ||
'option `delimiter` must be a buffer or a string,', | ||
`got ${JSON.stringify(options.delimiter)}` | ||
]) | ||
} | ||
// Normalize option `quote` | ||
if (options.quote === null || options.quote === void 0) { | ||
options.quote = '"'; | ||
} else { | ||
if (options.quote === true) { | ||
options.quote = '"'; | ||
} else if (options.quote === false) { | ||
options.quote = ''; | ||
} else if (Buffer.isBuffer(options.quote)) { | ||
options.quote = options.quote.toString(); | ||
} else if (typeof options.quote !== 'string') { | ||
throw new Error(`Invalid Option: quote must be a boolean, a buffer or a string, got ${JSON.stringify(options.quote)}`); | ||
} | ||
if(options.quote === undefined || options.quote === null){ | ||
options.quote = '"' | ||
}else if(options.quote === true){ | ||
options.quote = '"' | ||
}else if(options.quote === false){ | ||
options.quote = '' | ||
}else if (Buffer.isBuffer(options.quote)){ | ||
options.quote = options.quote.toString() | ||
}else if(typeof options.quote !== 'string'){ | ||
throw new CsvError('CSV_OPTION_QUOTE_INVALID_TYPE', [ | ||
'option `quote` must be a boolean, a buffer or a string,', | ||
`got ${JSON.stringify(options.quote)}` | ||
]) | ||
} | ||
// Normalize option `quoted` | ||
if (options.quoted == null) { | ||
options.quoted = false; | ||
if(options.quoted === undefined || options.quoted === null){ | ||
options.quoted = false | ||
}else{ | ||
// todo | ||
} | ||
if (options.quoted_empty == null) { | ||
options.quoted_empty = void 0; | ||
// Normalize option `quoted_empty` | ||
if(options.quoted_empty === undefined || options.quoted_empty === null){ | ||
options.quoted_empty = undefined | ||
}else{ | ||
// todo | ||
} | ||
if (options.quoted_string == null) { | ||
options.quoted_string = false; | ||
// Normalize option `quoted_string` | ||
if(options.quoted_string === undefined || options.quoted_string === null){ | ||
options.quoted_string = false | ||
}else{ | ||
// todo | ||
} | ||
if (options.eof == null) { | ||
options.eof = true; | ||
// Normalize option `eof` | ||
if(options.eof === undefined || options.eof === null){ | ||
options.eof = true | ||
}else{ | ||
// todo | ||
} | ||
// Normalize option `escape` | ||
if (options.escape === null || options.escape === void 0) { | ||
options.escape = '"'; | ||
} else { | ||
if (Buffer.isBuffer(options.escape)) { | ||
options.escape = options.escape.toString(); | ||
} | ||
if (typeof options.escape !== 'string') { | ||
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: escape must be one character, got ${options.escape.length} characters`); | ||
} | ||
if(options.escape === undefined || options.escape === null){ | ||
options.escape = '"' | ||
}else if(Buffer.isBuffer(options.escape)){ | ||
options.escape = options.escape.toString() | ||
}else if(typeof options.escape !== 'string'){ | ||
throw new Error(`Invalid Option: escape must be a buffer or a string, got ${JSON.stringify(options.escape)}`) | ||
} | ||
if (options.header == null) { | ||
options.header = false; | ||
if (options.escape.length > 1){ | ||
throw new Error(`Invalid Option: escape must be one character, got ${options.escape.length} characters`) | ||
} | ||
// Normalize the columns option | ||
options.columns = this.normalize_columns(options.columns); | ||
if (options.cast == null) { | ||
options.cast = {}; | ||
// Normalize option `header` | ||
if(options.header === undefined || options.header === null){ | ||
options.header = false | ||
}else{ | ||
// todo | ||
} | ||
// Normalize option `quoted_match` | ||
if (options.quoted_match === void 0 || options.quoted_match === null || options.quoted_match === false) { | ||
options.quoted_match = null; | ||
} else if (!Array.isArray(options.quoted_match)) { | ||
options.quoted_match = [options.quoted_match]; | ||
// Normalize option `columns` | ||
options.columns = this.normalize_columns(options.columns) | ||
// Normalize option `quoted` | ||
if(options.quoted === undefined || options.quoted === null){ | ||
options.quoted = false | ||
}else{ | ||
// todo | ||
} | ||
if (options.quoted_match) { | ||
ref = options.quoted_match; | ||
for (j = 0, len = ref.length; j < len; j++) { | ||
quoted_match = ref[j]; | ||
isString = typeof quoted_match === 'string'; | ||
isRegExp = quoted_match instanceof RegExp; | ||
if (!isString && !isRegExp) { | ||
throw new Error(`Invalid Option: quoted_match must be a string or a regex, got ${JSON.stringify(quoted_match)}`); | ||
} | ||
} | ||
// Normalize option `cast` | ||
if(options.cast === undefined || options.cast === null){ | ||
options.cast = {} | ||
}else{ | ||
// todo | ||
} | ||
if (options.cast.bool) { | ||
// Backward compatibility | ||
options.cast.boolean = options.cast.bool; | ||
// Normalize option cast.boolean | ||
if(options.cast.boolean === undefined || options.cast.boolean === null){ | ||
// Cast boolean to string by default | ||
options.cast.boolean = value => value ? '1' : '' | ||
} | ||
// Custom cast | ||
if ((base = options.cast).boolean == null) { | ||
base.boolean = function(value) { | ||
// Cast boolean to string by default | ||
if (value) { | ||
return '1'; | ||
} else { | ||
return ''; | ||
} | ||
}; | ||
// Normalize option cast.date | ||
if(options.cast.date === undefined || options.cast.date === null){ | ||
// Cast date to timestamp string by default | ||
options.cast.date = value => '' + value.getTime() | ||
} | ||
if ((base1 = options.cast).date == null) { | ||
base1.date = function(value) { | ||
// Cast date to timestamp string by default | ||
return '' + value.getTime(); | ||
}; | ||
// Normalize option cast.number | ||
if(options.cast.number === undefined || options.cast.number === null){ | ||
// Cast number to string using native casting by default | ||
options.cast.number = value => '' + value | ||
} | ||
if ((base2 = options.cast).number == null) { | ||
base2.number = function(value) { | ||
// Cast number to string using native casting by default | ||
return '' + value; | ||
}; | ||
// Normalize option cast.object | ||
if(options.cast.object === undefined || options.cast.object === null){ | ||
// Stringify object as JSON by default | ||
options.cast.object = value => JSON.stringify(value) | ||
} | ||
if ((base3 = options.cast).object == null) { | ||
base3.object = function(value) { | ||
// Stringify object as JSON by default | ||
return JSON.stringify(value); | ||
}; | ||
// Normalize option cast.string | ||
if(options.cast.string === undefined || options.cast.string === null){ | ||
// Leave string untouched | ||
options.cast.string = function(value){return value} | ||
} | ||
if ((base4 = options.cast).string == null) { | ||
base4.string = function(value) { | ||
return value; | ||
}; | ||
// Normalize option `quoted_match` | ||
if(options.quoted_match === undefined || options.quoted_match === null || options.quoted_match === false){ | ||
options.quoted_match = null | ||
}else if(!Array.isArray(options.quoted_match)){ | ||
options.quoted_match = [options.quoted_match] | ||
} | ||
// Normalize option `record_delimiter` | ||
if (options.record_delimiter === void 0 || options.record_delimiter === null) { | ||
if (options.record_delimiter == null) { | ||
options.record_delimiter = '\n'; | ||
if(options.quoted_match){ | ||
for(let quoted_match of options.quoted_match){ | ||
const isString = typeof quoted_match === 'string' | ||
const isRegExp = quoted_match instanceof RegExp | ||
if(!isString && !isRegExp){ | ||
throw new Error(`Invalid Option: quoted_match must be a string or a regex, got ${JSON.stringify(quoted_match)}`) | ||
} | ||
} | ||
} else { | ||
if (Buffer.isBuffer(options.record_delimiter)) { | ||
options.record_delimiter = options.record_delimiter.toString(); | ||
} else if (typeof options.record_delimiter !== 'string') { | ||
throw new Error(`Invalid Option: record_delimiter must be a buffer or a string, got ${JSON.stringify(options.record_delimiter)}`); | ||
} | ||
switch (options.record_delimiter) { | ||
case 'auto': | ||
options.record_delimiter = null; | ||
break; | ||
case 'unix': | ||
options.record_delimiter = "\n"; | ||
break; | ||
case 'mac': | ||
options.record_delimiter = "\r"; | ||
break; | ||
case 'windows': | ||
options.record_delimiter = "\r\n"; | ||
break; | ||
case 'ascii': | ||
options.record_delimiter = "\u001e"; | ||
break; | ||
case 'unicode': | ||
options.record_delimiter = "\u2028"; | ||
} | ||
} | ||
// Normalize option `record_delimiter` | ||
if(options.record_delimiter === undefined || options.record_delimiter === null){ | ||
options.record_delimiter = '\n' | ||
}else if(Buffer.isBuffer(options.record_delimiter)){ | ||
options.record_delimiter = options.record_delimiter.toString() | ||
}else if(typeof options.record_delimiter !== 'string'){ | ||
throw new Error(`Invalid Option: record_delimiter must be a buffer or a string, got ${JSON.stringify(options.record_delimiter)}`) | ||
} | ||
switch(options.record_delimiter){ | ||
case 'auto': | ||
options.record_delimiter = null | ||
break | ||
case 'unix': | ||
options.record_delimiter = "\n" | ||
break | ||
case 'mac': | ||
options.record_delimiter = "\r" | ||
break | ||
case 'windows': | ||
options.record_delimiter = "\r\n" | ||
break | ||
case 'ascii': | ||
options.record_delimiter = "\u001e" | ||
break | ||
case 'unicode': | ||
options.record_delimiter = "\u2028" | ||
break | ||
} | ||
// Expose options | ||
this.options = options; | ||
this.options = options | ||
// Internal state | ||
this.state = { | ||
stop: false | ||
}; | ||
} | ||
// Information | ||
this.info = { | ||
records: 0 | ||
}; | ||
this; | ||
} | ||
if(options.bom === true){ | ||
this.push(bom_utf8) | ||
} | ||
this | ||
} | ||
// ## `Stringifier.prototype._transform(chunk, encoding, callback)` | ||
// Implementation of the [transform._transform function](https://nodejs.org/api/stream.html#stream_transform_transform_chunk_encoding_callback). | ||
_transform(chunk, encoding, callback) { | ||
var base, e; | ||
if (this.state.stop === true) { | ||
return; | ||
_transform(chunk, encoding, callback){ | ||
if(this.state.stop === true){ | ||
return | ||
} | ||
// Chunk validation | ||
if (!(Array.isArray(chunk) || typeof chunk === 'object')) { | ||
this.state.stop = true; | ||
return callback(Error(`Invalid Record: expect an array or an object, got ${JSON.stringify(chunk)}`)); | ||
if(!Array.isArray(chunk) && typeof chunk !== 'object'){ | ||
this.state.stop = true | ||
return callback(Error(`Invalid Record: expect an array or an object, got ${JSON.stringify(chunk)}`)) | ||
} | ||
// Detect columns from the first record | ||
if (this.info.records === 0) { | ||
if (Array.isArray(chunk)) { | ||
if (this.options.header === true && !this.options.columns) { | ||
this.state.stop = true; | ||
return callback(Error('Undiscoverable Columns: header option requires column option or object records')); | ||
if(this.info.records === 0){ | ||
if(Array.isArray(chunk)){ | ||
if(this.options.header === true && !this.options.columns){ | ||
this.state.stop = true | ||
return callback(Error('Undiscoverable Columns: header option requires column option or object records')) | ||
} | ||
} else { | ||
if ((base = this.options).columns == null) { | ||
base.columns = this.normalize_columns(Object.keys(chunk)); | ||
} | ||
}else if(this.options.columns === undefined || this.options.columns === null){ | ||
this.options.columns = this.normalize_columns(Object.keys(chunk)) | ||
} | ||
} | ||
if (this.info.records === 0) { | ||
// Emit the header | ||
this.headers(); | ||
// Emit the header | ||
if(this.info.records === 0){ | ||
this.headers() | ||
} | ||
try { | ||
// Emit and stringify the record if an object or an array | ||
this.emit('record', chunk, this.info.records); | ||
} catch (error) { | ||
e = error; | ||
this.state.stop = true; | ||
return this.emit('error', e); | ||
// Emit and stringify the record if an object or an array | ||
try{ | ||
this.emit('record', chunk, this.info.records) | ||
}catch(err){ | ||
this.state.stop = true | ||
return this.emit('error', err) | ||
} | ||
// Convert the record into a string | ||
if (this.options.eof) { | ||
chunk = this.stringify(chunk); | ||
if (chunk == null) { | ||
return; | ||
if(this.options.eof){ | ||
chunk = this.stringify(chunk) | ||
if(chunk === undefined){ | ||
return | ||
}else{ | ||
chunk = chunk + this.options.record_delimiter | ||
} | ||
chunk = chunk + this.options.record_delimiter; | ||
} else { | ||
chunk = this.stringify(chunk); | ||
if (chunk == null) { | ||
return; | ||
}else{ | ||
chunk = this.stringify(chunk) | ||
if(chunk === undefined){ | ||
return | ||
}else{ | ||
if(this.options.header || this.info.records){ | ||
chunk = this.options.record_delimiter + chunk | ||
} | ||
} | ||
if (this.options.header || this.info.records) { | ||
chunk = this.options.record_delimiter + chunk; | ||
} | ||
} | ||
// Emit the csv | ||
this.info.records++; | ||
this.push(chunk); | ||
return callback(); | ||
this.info.records++ | ||
this.push(chunk) | ||
callback() | ||
null | ||
} | ||
// ## `Stringifier.prototype._flush(callback)` | ||
// Implementation of the [transform._flush function](https://nodejs.org/api/stream.html#stream_transform_flush_callback). | ||
_flush(callback) { | ||
if (this.info.records === 0) { | ||
this.headers(); | ||
_flush(callback){ | ||
if(this.info.records === 0){ | ||
this.headers() | ||
} | ||
return callback(); | ||
callback() | ||
null | ||
} | ||
// ## `Stringifier.prototype.stringify(line)` | ||
// Convert a line to a string. Line may be an object, an array or a string. | ||
stringify(chunk, chunkIsHeader = false) { | ||
var column, columns, containsEscape, containsQuote, containsRowDelimiter, containsdelimiter, csvrecord, delimiter, err, escape, field, header, i, j, l, len, m, options, quote, quoted, quotedMatch, quotedString, quoted_empty, quoted_match, quoted_string, record, record_delimiter, ref, ref1, regexp, shouldQuote, value; | ||
if (typeof chunk !== 'object') { | ||
return chunk; | ||
stringify(chunk, chunkIsHeader=false){ | ||
if(typeof chunk !== 'object'){ | ||
return chunk | ||
} | ||
({columns, header} = this.options); | ||
record = []; | ||
const {columns, header} = this.options | ||
const record = [] | ||
// Record is an array | ||
if (Array.isArray(chunk)) { | ||
if (columns) { | ||
// We are getting an array but the user has specified output columns. In | ||
// this case, we respect the columns indexes | ||
chunk.splice(columns.length); | ||
if(Array.isArray(chunk)){ | ||
// We are getting an array but the user has specified output columns. In | ||
// this case, we respect the columns indexes | ||
if(columns){ | ||
chunk.splice(columns.length) | ||
} | ||
// Cast record elements | ||
for (i = j = 0, len = chunk.length; j < len; i = ++j) { | ||
field = chunk[i]; | ||
[err, value] = this.__cast(field, { | ||
index: i, | ||
column: i, | ||
records: this.info.records, | ||
header: chunkIsHeader | ||
}); | ||
if (err) { | ||
this.emit('error', err); | ||
return; | ||
// Cast record elements | ||
for(let i=0; i<chunk.length; i++){ | ||
const field = chunk[i] | ||
const [err, value] = this.__cast(field, { | ||
index: i, column: i, records: this.info.records, header: chunkIsHeader | ||
}) | ||
if(err){ | ||
this.emit('error', err) | ||
return | ||
} | ||
record[i] = [value, field]; | ||
record[i] = [value, field] | ||
} | ||
} else { | ||
// Record is a literal object | ||
if (columns) { | ||
for (i = l = 0, ref = columns.length; (0 <= ref ? l < ref : l > ref); i = 0 <= ref ? ++l : --l) { | ||
field = get(chunk, columns[i].key); | ||
[err, value] = this.__cast(field, { | ||
index: i, | ||
column: columns[i].key, | ||
records: this.info.records, | ||
header: chunkIsHeader | ||
}); | ||
if (err) { | ||
this.emit('error', err); | ||
return; | ||
// Record is a literal object | ||
}else{ | ||
if(columns){ | ||
for(let i=0; i<columns.length; i++){ | ||
const field = get(chunk, columns[i].key) | ||
const [err, value] = this.__cast(field, { | ||
index: i, column: columns[i].key, records: this.info.records, header: chunkIsHeader | ||
}) | ||
if(err){ | ||
this.emit('error', err) | ||
return | ||
} | ||
record[i] = [value, field]; | ||
record[i] = [value, field] | ||
} | ||
} else { | ||
for (column in chunk) { | ||
field = chunk[column]; | ||
[err, value] = this.__cast(field, { | ||
index: i, | ||
column: columns[i].key, | ||
records: this.info.records, | ||
header: chunkIsHeader | ||
}); | ||
if (err) { | ||
this.emit('error', err); | ||
return; | ||
}else{ | ||
for(let column of chunk){ | ||
const field = chunk[column] | ||
const [err, value] = this.__cast(field, { | ||
index: i, column: columns[i].key, records: this.info.records, header: chunkIsHeader | ||
}) | ||
if(err){ | ||
this.emit('error', err) | ||
return | ||
} | ||
record.push([value, field]); | ||
record.push([value, field]) | ||
} | ||
} | ||
} | ||
csvrecord = ''; | ||
for (i = m = 0, ref1 = record.length; (0 <= ref1 ? m < ref1 : m > ref1); i = 0 <= ref1 ? ++m : --m) { | ||
[value, field] = record[i]; | ||
if (typeof value === 'string') { | ||
options = this.options; | ||
} else if (isObject(value)) { | ||
({value, ...options} = value); | ||
if (!(typeof value === 'string' || value === void 0 || value === null)) { | ||
this.emit('error', Error(`Invalid Casting Value: returned value must return a string, null or undefined, got ${JSON.stringify(value)}`)); | ||
return; | ||
let csvrecord = '' | ||
for(let i=0; i<record.length; i++){ | ||
let options | ||
let [value, field] = record[i] | ||
if(typeof value === "string"){ | ||
options = this.options | ||
}else if(isObject(value)){ | ||
// let { value, ...options } = value | ||
options = value | ||
value = options.value | ||
if(typeof value !== "string" && value !== undefined && value !== null){ | ||
this.emit("error", Error(`Invalid Casting Value: returned value must return a string, null or undefined, got ${JSON.stringify(value)}`)) | ||
return | ||
} | ||
options = {...this.options, ...options}; | ||
} else if (value === void 0 || value === null) { | ||
options = this.options; | ||
} else { | ||
this.emit('error', Error(`Invalid Casting Value: returned value must return a string, an object, null or undefined, got ${JSON.stringify(value)}`)); | ||
return; | ||
options = {...this.options, ...options} | ||
}else if(value === undefined || value === null){ | ||
options = this.options | ||
}else{ | ||
this.emit("error", Error(`Invalid Casting Value: returned value must return a string, an object, null or undefined, got ${JSON.stringify(value)}`)) | ||
return | ||
} | ||
({delimiter, escape, quote, quoted, quoted_empty, quoted_string, quoted_match, record_delimiter} = options); | ||
if (value) { | ||
if (typeof value !== 'string') { | ||
this.emit('error', Error(`Formatter must return a string, null or undefined, got ${JSON.stringify(value)}`)); | ||
return null; | ||
const {delimiter, escape, quote, quoted, quoted_empty, quoted_string, quoted_match, record_delimiter} = options | ||
if(value){ | ||
if(typeof value !== 'string'){ | ||
this.emit("error", Error(`Formatter must return a string, null or undefined, got ${JSON.stringify(value)}`)) | ||
return null | ||
} | ||
containsdelimiter = delimiter.length && value.indexOf(delimiter) >= 0; | ||
containsQuote = (quote !== '') && value.indexOf(quote) >= 0; | ||
containsEscape = value.indexOf(escape) >= 0 && (escape !== quote); | ||
containsRowDelimiter = value.indexOf(record_delimiter) >= 0; | ||
quotedString = quoted_string && typeof field === 'string'; | ||
quotedMatch = quoted_match && typeof field === 'string' && quoted_match.filter(function(quoted_match) { | ||
if (typeof quoted_match === 'string') { | ||
return value.indexOf(quoted_match) !== -1; | ||
} else { | ||
return quoted_match.test(value); | ||
const containsdelimiter = delimiter.length && value.indexOf(delimiter) >= 0 | ||
const containsQuote = (quote !== '') && value.indexOf(quote) >= 0 | ||
const containsEscape = value.indexOf(escape) >= 0 && (escape !== quote) | ||
const containsRecordDelimiter = value.indexOf(record_delimiter) >= 0 | ||
const quotedString = quoted_string && typeof field === 'string' | ||
let quotedMatch = quoted_match && typeof field === 'string' && quoted_match.filter( quoted_match => { | ||
if(typeof quoted_match === 'string'){ | ||
return value.indexOf(quoted_match) !== -1 | ||
}else{ | ||
return quoted_match.test(value) | ||
} | ||
}); | ||
quotedMatch = quotedMatch && quotedMatch.length > 0; | ||
shouldQuote = containsQuote === true || containsdelimiter || containsRowDelimiter || quoted || quotedString || quotedMatch; | ||
if (shouldQuote === true && containsEscape === true) { | ||
regexp = escape === '\\' ? new RegExp(escape + escape, 'g') : new RegExp(escape, 'g'); | ||
value = value.replace(regexp, escape + escape); | ||
}) | ||
quotedMatch = quotedMatch && quotedMatch.length > 0 | ||
const shouldQuote = containsQuote === true || containsdelimiter || containsRecordDelimiter || quoted || quotedString || quotedMatch | ||
if(shouldQuote === true && containsEscape === true){ | ||
const regexp = escape === '\\' | ||
? new RegExp(escape + escape, 'g') | ||
: new RegExp(escape, 'g') | ||
value = value.replace(regexp, escape + escape) | ||
} | ||
if (containsQuote === true) { | ||
regexp = new RegExp(quote, 'g'); | ||
value = value.replace(regexp, escape + quote); | ||
if(containsQuote === true){ | ||
const regexp = new RegExp(quote,'g') | ||
value = value.replace(regexp, escape + quote) | ||
} | ||
if (shouldQuote === true) { | ||
value = quote + value + quote; | ||
if(shouldQuote === true){ | ||
value = quote + value + quote | ||
} | ||
csvrecord += value; | ||
} else if (quoted_empty === true || ((quoted_empty == null) && field === '' && quoted_string !== false)) { | ||
csvrecord += quote + quote; | ||
csvrecord += value | ||
}else if(quoted_empty === true || (field === '' && quoted_string === true && quoted_empty !== false)){ | ||
csvrecord += quote + quote | ||
} | ||
if (i !== record.length - 1) { | ||
csvrecord += delimiter; | ||
if(i !== record.length - 1){ | ||
csvrecord += delimiter | ||
} | ||
} | ||
return csvrecord; | ||
return csvrecord | ||
} | ||
// ## `Stringifier.prototype.headers` | ||
// Print the header line if the option "header" is "true". | ||
headers() { | ||
var headers; | ||
if (!this.options.header) { | ||
return; | ||
headers(){ | ||
if(this.options.header === false){ | ||
return | ||
} | ||
if (!this.options.columns) { | ||
return; | ||
if(this.options.columns === undefined){ | ||
return | ||
} | ||
headers = this.options.columns.map(function(column) { | ||
return column.header; | ||
}); | ||
if (this.options.eof) { | ||
headers = this.stringify(headers, true) + this.options.record_delimiter; | ||
} else { | ||
headers = this.stringify(headers); | ||
let headers = this.options.columns.map(column => column.header) | ||
if(this.options.eof){ | ||
headers = this.stringify(headers, true) + this.options.record_delimiter | ||
}else{ | ||
headers = this.stringify(headers) | ||
} | ||
return this.push(headers); | ||
this.push(headers) | ||
} | ||
__cast(value, context) { | ||
var err, type; | ||
type = typeof value; | ||
try { | ||
if (type === 'string') { | ||
// Fine for 99% of the cases | ||
return [void 0, this.options.cast.string(value, context)]; | ||
} else if (type === 'number') { | ||
return [void 0, this.options.cast.number(value, context)]; | ||
} else if (type === 'boolean') { | ||
return [void 0, this.options.cast.boolean(value, context)]; | ||
} else if (value instanceof Date) { | ||
return [void 0, this.options.cast.date(value, context)]; | ||
} else if (type === 'object' && value !== null) { | ||
return [void 0, this.options.cast.object(value, context)]; | ||
} else { | ||
return [void 0, value, value]; | ||
__cast(value, context){ | ||
const type = typeof value | ||
try{ | ||
if(type === 'string'){ // Fine for 99% of the cases | ||
return [undefined, this.options.cast.string(value, context)] | ||
}else if(type === 'number'){ | ||
return [undefined, this.options.cast.number(value, context)] | ||
}else if(type === 'boolean'){ | ||
return [undefined, this.options.cast.boolean(value, context)] | ||
}else if(value instanceof Date){ | ||
return [undefined, this.options.cast.date(value, context)] | ||
}else if(type === 'object' && value !== null){ | ||
return [undefined, this.options.cast.object(value, context)] | ||
}else{ | ||
return [undefined, value, value] | ||
} | ||
} catch (error) { | ||
err = error; | ||
return [err]; | ||
}catch(err){ | ||
return [err] | ||
} | ||
} | ||
// ## `Stringifier.prototype.normalize_columns` | ||
normalize_columns(columns) { | ||
var column, k, v; | ||
if (columns == null) { | ||
return null; | ||
normalize_columns(columns){ | ||
if(columns === undefined || columns === null){ | ||
return undefined | ||
} | ||
if (columns != null) { | ||
if (typeof columns !== 'object') { | ||
throw Error('Invalid option "columns": expect an array or an object'); | ||
if(typeof columns !== 'object'){ | ||
throw Error('Invalid option "columns": expect an array or an object') | ||
} | ||
if(!Array.isArray(columns)){ | ||
const newcolumns = [] | ||
for(let k in columns){ | ||
newcolumns.push({ | ||
key: k, | ||
header: columns[k] | ||
}) | ||
} | ||
if (!Array.isArray(columns)) { | ||
columns = (function() { | ||
var results; | ||
results = []; | ||
for (k in columns) { | ||
v = columns[k]; | ||
results.push({ | ||
key: k, | ||
header: v | ||
}); | ||
columns = newcolumns | ||
}else{ | ||
const newcolumns = [] | ||
for(let column of columns){ | ||
if(typeof column === 'string'){ | ||
newcolumns.push({ | ||
key: column, | ||
header: column | ||
}) | ||
}else if(typeof column === 'object' && column !== undefined && !Array.isArray(column)){ | ||
if(!column.key){ | ||
throw Error('Invalid column definition: property "key" is required') | ||
} | ||
return results; | ||
})(); | ||
} else { | ||
columns = (function() { | ||
var j, len, results; | ||
results = []; | ||
for (j = 0, len = columns.length; j < len; j++) { | ||
column = columns[j]; | ||
if (typeof column === 'string') { | ||
results.push({ | ||
key: column, | ||
header: column | ||
}); | ||
} else if (typeof column === 'object' && (column != null) && !Array.isArray(column)) { | ||
if (!column.key) { | ||
throw Error('Invalid column definition: property "key" is required'); | ||
} | ||
if (column.header == null) { | ||
column.header = column.key; | ||
} | ||
results.push(column); | ||
} else { | ||
throw Error('Invalid column definition: expect a string or an object'); | ||
} | ||
if(column.header === undefined){ | ||
column.header = column.key | ||
} | ||
return results; | ||
})(); | ||
newcolumns.push(column) | ||
}else{ | ||
throw Error('Invalid column definition: expect a string or an object') | ||
} | ||
} | ||
columns = newcolumns | ||
} | ||
return columns; | ||
return columns | ||
} | ||
} | ||
}; | ||
const stringify = function(){ | ||
let data, options, callback | ||
for(let i in arguments){ | ||
const argument = arguments[i] | ||
const type = typeof argument | ||
if(data === undefined && (Array.isArray(argument))){ | ||
data = argument | ||
}else if(options === undefined && isObject(argument)){ | ||
options = argument | ||
}else if(callback === undefined && type === 'function'){ | ||
callback = argument | ||
}else{ | ||
throw new CsvError('CSV_INVALID_ARGUMENT', [ | ||
'Invalid argument:', | ||
`got ${JSON.stringify(argument)} at index ${i}` | ||
]) | ||
} | ||
} | ||
const stringifier = new Stringifier(options) | ||
if(callback){ | ||
const chunks = [] | ||
stringifier.on('readable', function(){ | ||
let chunk | ||
while((chunk = this.read()) !== null){ | ||
chunks.push(chunk) | ||
} | ||
}) | ||
stringifier.on('error', function(err){ | ||
callback(err) | ||
}) | ||
stringifier.on('end', function(){ | ||
callback(undefined, chunks.join('')) | ||
}) | ||
} | ||
if(data !== undefined){ | ||
// Give a chance for events to be registered later | ||
if(typeof setImmediate === 'function'){ | ||
setImmediate(function(){ | ||
for(let record of data){ | ||
stringifier.write(record) | ||
} | ||
stringifier.end() | ||
}) | ||
}else{ | ||
for(let record of data){ | ||
stringifier.write(record) | ||
} | ||
stringifier.end() | ||
} | ||
} | ||
return stringifier | ||
} | ||
module.exports.Stringifier = Stringifier; | ||
class CsvError extends Error { | ||
constructor(code, message, ...contexts) { | ||
if(Array.isArray(message)) message = message.join(' ') | ||
super(message) | ||
if(Error.captureStackTrace !== undefined){ | ||
Error.captureStackTrace(this, CsvError) | ||
} | ||
this.code = code | ||
for(const context of contexts){ | ||
for(const key in context){ | ||
const value = context[key] | ||
this[key] = Buffer.isBuffer(value) ? value.toString() : value == null ? value : JSON.parse(JSON.stringify(value)) | ||
} | ||
} | ||
} | ||
} | ||
isObject = function(obj) { | ||
return typeof obj === 'object' && obj !== null && !Array.isArray(obj); | ||
}; | ||
stringify.Stringifier = Stringifier | ||
underscore = function(str) { | ||
return str.replace(/([A-Z])/g, function(_, match, index) { | ||
return '_' + match.toLowerCase(); | ||
}); | ||
}; | ||
stringify.CsvError = CsvError | ||
// ## Lodash implementation of `get` | ||
charCodeOfDot = '.'.charCodeAt(0); | ||
module.exports = stringify | ||
reEscapeChar = /\\(\\)?/g; | ||
const isObject = function(obj){ | ||
return typeof obj === 'object' && obj !== null && ! Array.isArray(obj) | ||
} | ||
// Match anything that isn't a dot or bracket. | ||
// Or match property names within brackets. | ||
// Match a non-string expression. | ||
// Or match strings (supports escaping characters). | ||
// Or match "" as the space between consecutive dots or empty brackets. | ||
rePropName = RegExp('[^.[\\]]+' + '|' + '\\[(?:' + '([^"\'][^[]*)' + '|' + '(["\'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2' + ')\\]' + '|' + '(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))', 'g'); | ||
const underscore = function(str){ | ||
return str.replace(/([A-Z])/g, function(_, match){ | ||
return '_' + match.toLowerCase() | ||
}) | ||
} | ||
reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/; | ||
// Lodash implementation of `get` | ||
reIsPlainProp = /^\w*$/; | ||
getTag = function(value) { | ||
if (value != null) { | ||
if (value === void 0) { | ||
'[object Undefined]'; | ||
} else { | ||
'[object Null]'; | ||
} | ||
const charCodeOfDot = '.'.charCodeAt(0) | ||
const reEscapeChar = /\\(\\)?/g | ||
const rePropName = RegExp( | ||
// Match anything that isn't a dot or bracket. | ||
'[^.[\\]]+' + '|' + | ||
// Or match property names within brackets. | ||
'\\[(?:' + | ||
// Match a non-string expression. | ||
'([^"\'][^[]*)' + '|' + | ||
// Or match strings (supports escaping characters). | ||
'(["\'])((?:(?!\\2)[^\\\\]|\\\\.)*?)\\2' + | ||
')\\]'+ '|' + | ||
// Or match "" as the space between consecutive dots or empty brackets. | ||
'(?=(?:\\.|\\[\\])(?:\\.|\\[\\]|$))' | ||
, 'g') | ||
const reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/ | ||
const reIsPlainProp = /^\w*$/ | ||
const getTag = function(value){ | ||
if(!value) | ||
value === undefined ? '[object Undefined]' : '[object Null]' | ||
return Object.prototype.toString.call(value) | ||
} | ||
const isKey = function(value, object){ | ||
if(Array.isArray(value)){ | ||
return false | ||
} | ||
return Object.prototype.toString.call(value); | ||
}; | ||
isKey = function(value, object) { | ||
var type; | ||
if (Array.isArray(value)) { | ||
return false; | ||
const type = typeof value | ||
if(type === 'number' || type === 'symbol' || type === 'boolean' || !value || isSymbol(value)){ | ||
return true | ||
} | ||
type = typeof value; | ||
if (type === 'number' || type === 'symbol' || type === 'boolean' || (value == null) || isSymbol(value)) { | ||
return true; | ||
return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || | ||
(object != null && value in Object(object)) | ||
} | ||
const isSymbol = function(value){ | ||
type = typeof value | ||
return type === 'symbol' || (type === 'object' && value && getTag(value) === '[object Symbol]') | ||
} | ||
const stringToPath = function(string){ | ||
const result = [] | ||
if(string.charCodeAt(0) === charCodeOfDot){ | ||
result.push('') | ||
} | ||
return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || ((object != null) && value in Object(object)); | ||
}; | ||
isSymbol = function(value) { | ||
var type; | ||
type = typeof value; | ||
return type === 'symbol' || (type === 'object' && (value != null) && getTag(value) === '[object Symbol]'); | ||
}; | ||
stringToPath = function(string) { | ||
var result; | ||
result = []; | ||
if (string.charCodeAt(0) === charCodeOfDot) { | ||
result.push(''); | ||
} | ||
string.replace(rePropName, function(match, expression, quote, subString) { | ||
var key; | ||
key = match; | ||
if (quote) { | ||
key = subString.replace(reEscapeChar, '$1'); | ||
} else if (expression) { | ||
key = expression.trim(); | ||
string.replace(rePropName, function(match, expression, quote, subString){ | ||
let key = match | ||
if(quote){ | ||
key = subString.replace(reEscapeChar, '$1') | ||
}else if(expression){ | ||
key = expression.trim() | ||
} | ||
return result.push(key); | ||
}); | ||
return result; | ||
}; | ||
castPath = function(value, object) { | ||
if (Array.isArray(value)) { | ||
return value; | ||
result.push(key) | ||
}) | ||
return result | ||
} | ||
const castPath = function(value, object){ | ||
if(Array.isArray(value)){ | ||
return value | ||
} else { | ||
if (isKey(value, object)) { | ||
return [value]; | ||
} else { | ||
return stringToPath(value); | ||
} | ||
return isKey(value, object) ? [value] : stringToPath(value) | ||
} | ||
}; | ||
toKey = function(value) { | ||
var ref, result; | ||
if (typeof value === 'string' || isSymbol(value)) { | ||
return value; | ||
} | ||
const toKey = function(value){ | ||
if(typeof value === 'string' || isSymbol(value)) | ||
return value | ||
const result = `${value}` | ||
return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result | ||
} | ||
const get = function(object, path){ | ||
path = castPath(path, object) | ||
let index = 0 | ||
const length = path.length | ||
while(object != null && index < length){ | ||
object = object[toKey(path[index++])] | ||
} | ||
result = `${value}`; | ||
return (ref = result === '0' && (1 / value) === -INFINITY) != null ? ref : { | ||
'-0': result | ||
}; | ||
}; | ||
get = function(object, path) { | ||
var index, length; | ||
path = Array.isArray(path) ? path : castPath(path, object); | ||
index = 0; | ||
length = path.length; | ||
while ((object != null) && index < length) { | ||
object = object[toKey(path[index++])]; | ||
} | ||
if (index && index === length) { | ||
return object; | ||
} else { | ||
return void 0; | ||
} | ||
}; | ||
return (index && index === length) ? object : undefined | ||
} |
@@ -1,34 +0,22 @@ | ||
// Generated by CoffeeScript 2.4.1 | ||
// # CSV Stringify Sync | ||
// Provides a synchronous alternative to the CSV stringifier. | ||
const stringify = require('.') | ||
const {StringDecoder} = require('string_decoder') | ||
// ## Usage | ||
// `const csv = stringify(records, [options]` | ||
var StringDecoder, stringify; | ||
({StringDecoder} = require('string_decoder')); | ||
stringify = require('./index'); | ||
module.exports = function(records, options = {}) { | ||
var data, decoder, i, len, record, stringifier; | ||
data = []; | ||
if (records instanceof Buffer) { | ||
decoder = new StringDecoder(); | ||
records = decoder.write(records); | ||
module.exports = function(records, options={}){ | ||
const data = [] | ||
if(Buffer.isBuffer(records)){ | ||
const decoder = new StringDecoder() | ||
records = decoder.write(records) | ||
} | ||
stringifier = new stringify.Stringifier(options); | ||
stringifier.push = function(record) { | ||
if (record) { | ||
return data.push(record.toString()); | ||
const stringifier = new stringify.Stringifier(options) | ||
stringifier.push = function(record){ | ||
if(record){ | ||
data.push(record.toString()) | ||
} | ||
}; | ||
for (i = 0, len = records.length; i < len; i++) { | ||
record = records[i]; | ||
stringifier.write(record); | ||
} | ||
stringifier.end(); | ||
return data.join(''); | ||
}; | ||
for(let record of records){ | ||
stringifier.write(record) | ||
} | ||
stringifier.end() | ||
return data.join('') | ||
} |
{ | ||
"version": "5.3.6", | ||
"version": "5.4.0", | ||
"name": "csv-stringify", | ||
@@ -51,3 +51,3 @@ "description": "CSV stringifier implementing the Node.js `stream.Transform` API", | ||
"scripts": { | ||
"preversion": "grep '## Trunk' CHANGELOG.md && rm -rf lib/*.js && npm test && cp lib/*.ts lib/es5 && git add lib/es5/*.ts", | ||
"preversion": "grep '## Trunk' CHANGELOG.md && npm test && cp lib/*.ts lib/es5 && git add lib/es5/*.ts", | ||
"version": "version=`grep '^ \"version\": ' package.json | sed 's/.*\"\\([0-9\\.]*\\)\".*/\\1/'` && sed -i \"s/## Trunk/## Version $version/\" CHANGELOG.md && git add CHANGELOG.md", | ||
@@ -58,3 +58,3 @@ "postversion": "git push && git push --tags && npm publish", | ||
"major": "npm version major -m 'Bump to version %s'", | ||
"build": "coffee -b -o lib src && cd lib && babel *.js -d es5 && cd ..", | ||
"build": "cd lib && babel *.js -d es5 && cd ..", | ||
"pretest": "npm run build", | ||
@@ -61,0 +61,0 @@ "test": "mocha test/**/*.{coffee,ts}" |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
71849
1616
1