csv-stringify
Advanced tools
Comparing version 5.4.1 to 5.4.2
# Changelog | ||
## Version 5.4.2 | ||
Fix: | ||
* quoted_match: apply on all types and not just string | ||
* cast: validate and normalize local options | ||
Project management: | ||
* samples: add quoted examples | ||
## Version 5.4.1 | ||
@@ -5,0 +14,0 @@ |
@@ -69,228 +69,234 @@ "use strict"; | ||
}, {}, opts))); | ||
var options = {}; // Merge with user options | ||
var options = {}; | ||
var err; // Merge with user options | ||
for (var opt in opts) { | ||
options[underscore(opt)] = opts[opt]; | ||
} // Normalize option `bom` | ||
} | ||
if (err = _this.normalize(options)) throw err; | ||
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` | ||
switch (options.record_delimiter) { | ||
case 'auto': | ||
options.record_delimiter = null; | ||
break; | ||
case 'unix': | ||
options.record_delimiter = "\n"; | ||
break; | ||
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 ".concat(JSON.stringify(options.delimiter))]); | ||
} // Normalize option `quote` | ||
case 'mac': | ||
options.record_delimiter = "\r"; | ||
break; | ||
case 'windows': | ||
options.record_delimiter = "\r\n"; | ||
break; | ||
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 ".concat(JSON.stringify(options.quote))]); | ||
} // Normalize option `quoted` | ||
case 'ascii': | ||
options.record_delimiter = "\x1E"; | ||
break; | ||
case 'unicode': | ||
options.record_delimiter = "\u2028"; | ||
break; | ||
} // Expose options | ||
if (options.quoted === undefined || options.quoted === null) { | ||
options.quoted = false; | ||
} else {} // todo | ||
// Normalize option `quoted_empty` | ||
_this.options = options; // Internal state | ||
if (options.quoted_empty === undefined || options.quoted_empty === null) { | ||
options.quoted_empty = undefined; | ||
} else {} // todo | ||
// Normalize option `quoted_string` | ||
_this.state = { | ||
stop: false | ||
}; // Information | ||
_this.info = { | ||
records: 0 | ||
}; | ||
if (options.quoted_string === undefined || options.quoted_string === null) { | ||
options.quoted_string = false; | ||
} else {} // todo | ||
// Normalize option `eof` | ||
if (options.bom === true) { | ||
_this.push(bom_utf8); | ||
} | ||
_assertThisInitialized(_this); | ||
if (options.eof === undefined || options.eof === null) { | ||
options.eof = true; | ||
} else {} // todo | ||
// Normalize option `escape` | ||
return _this; | ||
} | ||
_createClass(Stringifier, [{ | ||
key: "normalize", | ||
value: function normalize(options) { | ||
// Normalize option `bom` | ||
if (options.bom === undefined || options.bom === null || options.bom === false) { | ||
options.bom = false; | ||
} else if (options.bom !== true) { | ||
return 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.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 ".concat(JSON.stringify(options.escape))); | ||
} | ||
if (options.escape.length > 1) { | ||
throw new Error("Invalid Option: escape must be one character, got ".concat(options.escape.length, " characters")); | ||
} // Normalize option `header` | ||
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') { | ||
return 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.header === undefined || options.header === null) { | ||
options.header = false; | ||
} else {} // todo | ||
// Normalize option `columns` | ||
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') { | ||
return 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` | ||
options.columns = _this.normalize_columns(options.columns); // Normalize option `quoted` | ||
if (options.quoted === undefined || options.quoted === null) { | ||
options.quoted = false; | ||
} else {} // todo | ||
// Normalize option `quoted_empty` | ||
if (options.quoted === undefined || options.quoted === null) { | ||
options.quoted = false; | ||
} else {} // todo | ||
// Normalize option `cast` | ||
if (options.quoted_empty === undefined || options.quoted_empty === null) { | ||
options.quoted_empty = undefined; | ||
} else {} // todo | ||
// Normalize option `quoted_match` | ||
if (options.cast === undefined || options.cast === null) { | ||
options.cast = {}; | ||
} else {} // todo | ||
// Normalize option cast.boolean | ||
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.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 (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 (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 (!isString && !isRegExp) { | ||
return 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; | ||
} | ||
} | ||
} | ||
} // Normalize option `quoted_string` | ||
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 (options.quoted_string === undefined || options.quoted_string === null) { | ||
options.quoted_string = false; | ||
} else {} // todo | ||
// Normalize option `eof` | ||
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 (options.eof === undefined || options.eof === null) { | ||
options.eof = true; | ||
} else {} // todo | ||
// Normalize option `escape` | ||
if (options.cast.string === undefined || options.cast.string === null) { | ||
// Leave string untouched | ||
options.cast.string = function (value) { | ||
return value; | ||
}; | ||
} // Normalize option `quoted_match` | ||
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') { | ||
return Error("Invalid Option: escape must be a buffer or a string, got ".concat(JSON.stringify(options.escape))); | ||
} | ||
if (options.escape.length > 1) { | ||
return Error("Invalid Option: escape must be one character, got ".concat(options.escape.length, " characters")); | ||
} // Normalize option `header` | ||
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; | ||
if (options.header === undefined || options.header === null) { | ||
options.header = false; | ||
} else {} // todo | ||
// Normalize option `columns` | ||
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; | ||
} | ||
} | ||
} | ||
} // Normalize option `record_delimiter` | ||
options.columns = this.normalize_columns(options.columns); // Normalize option `quoted` | ||
if (options.quoted === undefined || options.quoted === null) { | ||
options.quoted = false; | ||
} else {} // todo | ||
// Normalize option `cast` | ||
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))); | ||
} | ||
switch (options.record_delimiter) { | ||
case 'auto': | ||
options.record_delimiter = null; | ||
break; | ||
if (options.cast === undefined || options.cast === null) { | ||
options.cast = {}; | ||
} else {} // todo | ||
// Normalize option cast.boolean | ||
case 'unix': | ||
options.record_delimiter = "\n"; | ||
break; | ||
case 'mac': | ||
options.record_delimiter = "\r"; | ||
break; | ||
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 | ||
case 'windows': | ||
options.record_delimiter = "\r\n"; | ||
break; | ||
case 'ascii': | ||
options.record_delimiter = "\x1E"; | ||
break; | ||
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 | ||
case 'unicode': | ||
options.record_delimiter = "\u2028"; | ||
break; | ||
} // Expose options | ||
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 | ||
_this.options = options; // Internal state | ||
_this.state = { | ||
stop: false | ||
}; // Information | ||
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 | ||
_this.info = { | ||
records: 0 | ||
}; | ||
if (options.bom === true) { | ||
_this.push(bom_utf8); | ||
} | ||
if (options.cast.string === undefined || options.cast.string === null) { | ||
// Leave string untouched | ||
options.cast.string = function (value) { | ||
return value; | ||
}; | ||
} // Normalize option `record_delimiter` | ||
_assertThisInitialized(_this); | ||
return _this; | ||
} | ||
_createClass(Stringifier, [{ | ||
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') { | ||
return Error("Invalid Option: record_delimiter must be a buffer or a string, got ".concat(JSON.stringify(options.record_delimiter))); | ||
} | ||
} | ||
}, { | ||
key: "_transform", | ||
@@ -484,3 +490,4 @@ value: function _transform(chunk, encoding, callback) { | ||
var _loop = function _loop(_i3) { | ||
var options = void 0; | ||
var options = void 0, | ||
err = void 0; | ||
@@ -497,2 +504,3 @@ var _record$_i = _slicedToArray(record[_i3], 2), | ||
value = options.value; | ||
delete options.value; | ||
@@ -508,2 +516,10 @@ if (typeof value !== "string" && value !== undefined && value !== null) { | ||
options = _objectSpread({}, _this2.options, {}, options); | ||
if (err = _this2.normalize(options)) { | ||
_this2.emit("error", err); | ||
return { | ||
v: void 0 | ||
}; | ||
} | ||
} else if (value === undefined || value === null) { | ||
@@ -543,3 +559,3 @@ options = _this2.options; | ||
var quotedString = quoted_string && typeof field === 'string'; | ||
var quotedMatch = quoted_match && typeof field === 'string' && quoted_match.filter(function (quoted_match) { | ||
var quotedMatch = quoted_match && quoted_match.filter(function (quoted_match) { | ||
if (typeof quoted_match === 'string') { | ||
@@ -546,0 +562,0 @@ return value.indexOf(quoted_match) !== -1; |
123
lib/index.js
@@ -16,2 +16,3 @@ | ||
const options = {} | ||
let err | ||
// Merge with user options | ||
@@ -21,2 +22,39 @@ for(let opt in opts){ | ||
} | ||
if(err = this.normalize(options)) throw err | ||
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 | ||
// Internal state | ||
this.state = { | ||
stop: false | ||
} | ||
// Information | ||
this.info = { | ||
records: 0 | ||
} | ||
if(options.bom === true){ | ||
this.push(bom_utf8) | ||
} | ||
this | ||
} | ||
normalize(options){ | ||
// Normalize option `bom` | ||
@@ -26,3 +64,3 @@ if(options.bom === undefined || options.bom === null || options.bom === false){ | ||
}else if(options.bom !== true){ | ||
throw new CsvError('CSV_OPTION_BOOLEAN_INVALID_TYPE', [ | ||
return new CsvError('CSV_OPTION_BOOLEAN_INVALID_TYPE', [ | ||
'option `bom` is optional and must be a boolean value,', | ||
@@ -38,3 +76,3 @@ `got ${JSON.stringify(options.bom)}` | ||
}else if(typeof options.delimiter !== 'string'){ | ||
throw new CsvError('CSV_OPTION_DELIMITER_INVALID_TYPE', [ | ||
return new CsvError('CSV_OPTION_DELIMITER_INVALID_TYPE', [ | ||
'option `delimiter` must be a buffer or a string,', | ||
@@ -54,3 +92,3 @@ `got ${JSON.stringify(options.delimiter)}` | ||
}else if(typeof options.quote !== 'string'){ | ||
throw new CsvError('CSV_OPTION_QUOTE_INVALID_TYPE', [ | ||
return new CsvError('CSV_OPTION_QUOTE_INVALID_TYPE', [ | ||
'option `quote` must be a boolean, a buffer or a string,', | ||
@@ -72,2 +110,17 @@ `got ${JSON.stringify(options.quote)}` | ||
} | ||
// 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] | ||
} | ||
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){ | ||
return Error(`Invalid Option: quoted_match must be a string or a regex, got ${JSON.stringify(quoted_match)}`) | ||
} | ||
} | ||
} | ||
// Normalize option `quoted_string` | ||
@@ -91,6 +144,6 @@ if(options.quoted_string === undefined || options.quoted_string === null){ | ||
}else if(typeof options.escape !== 'string'){ | ||
throw new Error(`Invalid Option: escape must be a buffer or a string, got ${JSON.stringify(options.escape)}`) | ||
return Error(`Invalid Option: escape must be a buffer or a string, got ${JSON.stringify(options.escape)}`) | ||
} | ||
if (options.escape.length > 1){ | ||
throw new Error(`Invalid Option: escape must be one character, got ${options.escape.length} characters`) | ||
return Error(`Invalid Option: escape must be one character, got ${options.escape.length} characters`) | ||
} | ||
@@ -142,17 +195,2 @@ // Normalize option `header` | ||
} | ||
// 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] | ||
} | ||
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)}`) | ||
} | ||
} | ||
} | ||
// Normalize option `record_delimiter` | ||
@@ -164,38 +202,4 @@ if(options.record_delimiter === undefined || options.record_delimiter === null){ | ||
}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)}`) | ||
return 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 | ||
// Internal state | ||
this.state = { | ||
stop: false | ||
} | ||
// Information | ||
this.info = { | ||
records: 0 | ||
} | ||
if(options.bom === true){ | ||
this.push(bom_utf8) | ||
} | ||
this | ||
} | ||
@@ -319,3 +323,3 @@ _transform(chunk, encoding, callback){ | ||
for(let i=0; i<record.length; i++){ | ||
let options | ||
let options, err | ||
let [value, field] = record[i] | ||
@@ -328,2 +332,3 @@ if(typeof value === "string"){ | ||
value = options.value | ||
delete options.value | ||
if(typeof value !== "string" && value !== undefined && value !== null){ | ||
@@ -334,2 +339,6 @@ this.emit("error", Error(`Invalid Casting Value: returned value must return a string, null or undefined, got ${JSON.stringify(value)}`)) | ||
options = {...this.options, ...options} | ||
if(err = this.normalize(options)){ | ||
this.emit("error", err) | ||
return | ||
} | ||
}else if(value === undefined || value === null){ | ||
@@ -352,3 +361,3 @@ options = this.options | ||
const quotedString = quoted_string && typeof field === 'string' | ||
let quotedMatch = quoted_match && typeof field === 'string' && quoted_match.filter( quoted_match => { | ||
let quotedMatch = quoted_match && quoted_match.filter( quoted_match => { | ||
if(typeof quoted_match === 'string'){ | ||
@@ -355,0 +364,0 @@ return value.indexOf(quoted_match) !== -1 |
{ | ||
"version": "5.4.1", | ||
"version": "5.4.2", | ||
"name": "csv-stringify", | ||
@@ -4,0 +4,0 @@ "description": "CSV stringifier implementing the Node.js `stream.Transform` API", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
72765
1636