Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

csv-writer

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

csv-writer - npm Package Compare versions

Comparing version 1.4.0 to 1.5.0

dist/lib/default-field-stringifier.js

4

CHANGELOG.md

@@ -8,2 +8,6 @@ # Changelog

## [1.5.0] - 2019-07-13
### Added
- Added `alwaysQuote` flag to always double-quote all fields. [#21](https://github.com/ryu1kn/csv-writer/pull/21)
## [1.4.0] - 2019-06-19

@@ -10,0 +14,0 @@ ### Added

19

dist/lib/csv-stringifier-factory.js

@@ -6,4 +6,2 @@ "use strict";

var object_1 = require("./csv-stringifiers/object");
var DEFAULT_FIELD_DELIMITER = ',';
var VALID_FIELD_DELIMITERS = [DEFAULT_FIELD_DELIMITER, ';'];
var CsvStringifierFactory = /** @class */ (function () {

@@ -13,12 +11,8 @@ function CsvStringifierFactory() {

CsvStringifierFactory.prototype.createArrayCsvStringifier = function (params) {
var fieldDelimiter = params.fieldDelimiter || DEFAULT_FIELD_DELIMITER;
_validateFieldDelimiter(fieldDelimiter);
var fieldStringifier = new field_stringifier_1.FieldStringifier(fieldDelimiter);
return new array_1.ArrayCsvStringifier(fieldStringifier, fieldDelimiter, params.recordDelimiter, params.header);
var fieldStringifier = field_stringifier_1.createFieldStringifier(params.fieldDelimiter, params.alwaysQuote);
return new array_1.ArrayCsvStringifier(fieldStringifier, params.recordDelimiter, params.header);
};
CsvStringifierFactory.prototype.createObjectCsvStringifier = function (params) {
var fieldDelimiter = params.fieldDelimiter || DEFAULT_FIELD_DELIMITER;
_validateFieldDelimiter(fieldDelimiter);
var fieldStringifier = new field_stringifier_1.FieldStringifier(fieldDelimiter);
return new object_1.ObjectCsvStringifier(fieldStringifier, fieldDelimiter, params.header, params.recordDelimiter);
var fieldStringifier = field_stringifier_1.createFieldStringifier(params.fieldDelimiter, params.alwaysQuote);
return new object_1.ObjectCsvStringifier(fieldStringifier, params.header, params.recordDelimiter);
};

@@ -28,7 +22,2 @@ return CsvStringifierFactory;

exports.CsvStringifierFactory = CsvStringifierFactory;
function _validateFieldDelimiter(delimiter) {
if (VALID_FIELD_DELIMITERS.indexOf(delimiter) === -1) {
throw new Error("Invalid field delimiter `" + delimiter + "` is specified");
}
}
//# sourceMappingURL=csv-stringifier-factory.js.map

@@ -6,5 +6,5 @@ "use strict";

var CsvStringifier = /** @class */ (function () {
function CsvStringifier(fieldStringifier, fieldDelimiter, recordDelimiter) {
function CsvStringifier(fieldStringifier, recordDelimiter) {
this.fieldStringifier = fieldStringifier;
this.fieldDelimiter = fieldDelimiter;
this.fieldDelimiter = fieldStringifier.fieldDelimiter;
this.recordDelimiter = recordDelimiter || DEFAULT_RECORD_DELIMITER;

@@ -11,0 +11,0 @@ _validateRecordDelimiter(this.recordDelimiter);

@@ -19,4 +19,4 @@ "use strict";

__extends(ArrayCsvStringifier, _super);
function ArrayCsvStringifier(fieldStringifier, fieldDelimiter, recordDelimiter, header) {
var _this = _super.call(this, fieldStringifier, fieldDelimiter, recordDelimiter) || this;
function ArrayCsvStringifier(fieldStringifier, recordDelimiter, header) {
var _this = _super.call(this, fieldStringifier, recordDelimiter) || this;
_this.header = header;

@@ -23,0 +23,0 @@ return _this;

@@ -19,4 +19,4 @@ "use strict";

__extends(ObjectCsvStringifier, _super);
function ObjectCsvStringifier(fieldStringifier, fieldDelimiter, header, recordDelimiter) {
var _this = _super.call(this, fieldStringifier, fieldDelimiter, recordDelimiter) || this;
function ObjectCsvStringifier(fieldStringifier, header, recordDelimiter) {
var _this = _super.call(this, fieldStringifier, recordDelimiter) || this;
_this.header = header;

@@ -23,0 +23,0 @@ return _this;

@@ -12,3 +12,4 @@ "use strict";

fieldDelimiter: params.fieldDelimiter,
recordDelimiter: params.recordDelimiter
recordDelimiter: params.recordDelimiter,
alwaysQuote: params.alwaysQuote
});

@@ -21,3 +22,4 @@ return new csv_writer_1.CsvWriter(csvStringifier, params.path, params.encoding, params.append);

fieldDelimiter: params.fieldDelimiter,
recordDelimiter: params.recordDelimiter
recordDelimiter: params.recordDelimiter,
alwaysQuote: params.alwaysQuote
});

@@ -24,0 +26,0 @@ return new csv_writer_1.CsvWriter(csvStringifier, params.path, params.encoding, params.append);

"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var DEFAULT_FIELD_DELIMITER = ',';
var VALID_FIELD_DELIMITERS = [DEFAULT_FIELD_DELIMITER, ';'];
var FieldStringifier = /** @class */ (function () {
function FieldStringifier(fieldDelimiter) {
this.fieldDelimiter = fieldDelimiter;
this._fieldDelimiter = fieldDelimiter;
}
FieldStringifier.prototype.stringify = function (value) {
if (typeof value === 'undefined' || value === null)
Object.defineProperty(FieldStringifier.prototype, "fieldDelimiter", {
get: function () {
return this._fieldDelimiter;
},
enumerable: true,
configurable: true
});
FieldStringifier.prototype.isEmpty = function (value) {
return typeof value === 'undefined' || value === null || value === '';
};
FieldStringifier.prototype.quoteField = function (field) {
return "\"" + field.replace(/"/g, '""') + "\"";
};
return FieldStringifier;
}());
exports.FieldStringifier = FieldStringifier;
var DefaultFieldStringifier = /** @class */ (function (_super) {
__extends(DefaultFieldStringifier, _super);
function DefaultFieldStringifier() {
return _super !== null && _super.apply(this, arguments) || this;
}
DefaultFieldStringifier.prototype.stringify = function (value) {
if (this.isEmpty(value))
return '';
var str = String(value);
return this.needsQuote(str) ? "\"" + str.replace(/"/g, '""') + "\"" : str;
return this.needsQuote(str) ? this.quoteField(str) : str;
};
FieldStringifier.prototype.needsQuote = function (str) {
DefaultFieldStringifier.prototype.needsQuote = function (str) {
return str.includes(this.fieldDelimiter) || str.includes('\n') || str.includes('"');
};
return FieldStringifier;
}());
exports.FieldStringifier = FieldStringifier;
return DefaultFieldStringifier;
}(FieldStringifier));
var ForceQuoteFieldStringifier = /** @class */ (function (_super) {
__extends(ForceQuoteFieldStringifier, _super);
function ForceQuoteFieldStringifier() {
return _super !== null && _super.apply(this, arguments) || this;
}
ForceQuoteFieldStringifier.prototype.stringify = function (value) {
return this.isEmpty(value) ? '' : this.quoteField(String(value));
};
return ForceQuoteFieldStringifier;
}(FieldStringifier));
function createFieldStringifier(fieldDelimiter, alwaysQuote) {
if (fieldDelimiter === void 0) { fieldDelimiter = DEFAULT_FIELD_DELIMITER; }
if (alwaysQuote === void 0) { alwaysQuote = false; }
_validateFieldDelimiter(fieldDelimiter);
return alwaysQuote ? new ForceQuoteFieldStringifier(fieldDelimiter) : new DefaultFieldStringifier(fieldDelimiter);
}
exports.createFieldStringifier = createFieldStringifier;
function _validateFieldDelimiter(delimiter) {
if (VALID_FIELD_DELIMITERS.indexOf(delimiter) === -1) {
throw new Error("Invalid field delimiter `" + delimiter + "` is specified");
}
}
//# sourceMappingURL=field-stringifier.js.map

@@ -30,5 +30,5 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var assert = require("assert");
var delimiter_1 = require("../helper/delimiter");
var index_1 = require("../../index");
var assert_1 = require("assert");
describe('ArrayCsvStringifier', function () {

@@ -43,3 +43,3 @@ var records = [

it('throws an exception', function () {
assert.throws(function () {
assert_1.throws(function () {
index_1.createArrayCsvStringifier({ fieldDelimiter: '/' });

@@ -51,3 +51,3 @@ });

it('throws an exception', function () {
assert.throws(function () {
assert_1.throws(function () {
index_1.createArrayCsvStringifier({ recordDelimiter: '\r' });

@@ -75,5 +75,17 @@ });

it('converts the records into CSV', function () {
assert.equal(stringifier.stringifyRecords(recordGenerator()), 'FIELD_A1,FIELD_B1\nFIELD_A2,FIELD_B2\n');
assert_1.strictEqual(stringifier.stringifyRecords(recordGenerator()), 'FIELD_A1,FIELD_B1\nFIELD_A2,FIELD_B2\n');
});
});
describe('When `alwaysQuote` flag is set', function () {
var stringifier = index_1.createArrayCsvStringifier({
header: ['TITLE_A', 'TITLE_B'],
alwaysQuote: true
});
it('quotes all header fields', function () {
assert_1.strictEqual(stringifier.getHeaderString(), '"TITLE_A","TITLE_B"\n');
});
it('quotes all data fields', function () {
assert_1.strictEqual(stringifier.stringifyRecords(records), '"FIELD_A1","FIELD_B1"\n"FIELD_A2","FIELD_B2"\n');
});
});
function generateTestCases(fieldDelimiter) {

@@ -88,6 +100,6 @@ var delim = delimiter_1.resolveDelimiterChar(fieldDelimiter);

it("returns a header line with field separated by \"" + delim + "\"", function () {
assert.equal(stringifier.getHeaderString(), "TITLE_A" + delim + "TITLE_B\n");
assert_1.strictEqual(stringifier.getHeaderString(), "TITLE_A" + delim + "TITLE_B\n");
});
it("converts given data records into CSV lines with field separated by \"" + delim + "\"", function () {
assert.equal(stringifier.stringifyRecords(records), "FIELD_A1" + delim + "FIELD_B1\nFIELD_A2" + delim + "FIELD_B2\n");
assert_1.strictEqual(stringifier.stringifyRecords(records), "FIELD_A1" + delim + "FIELD_B1\nFIELD_A2" + delim + "FIELD_B2\n");
});

@@ -98,6 +110,6 @@ });

it('returns null for header line', function () {
assert.equal(stringifier.getHeaderString(), null);
assert_1.strictEqual(stringifier.getHeaderString(), null);
});
it("converts given data records into CSV lines with field separated by \"" + delim + "\"", function () {
assert.equal(stringifier.stringifyRecords(records), "FIELD_A1" + delim + "FIELD_B1\nFIELD_A2" + delim + "FIELD_B2\n");
assert_1.strictEqual(stringifier.stringifyRecords(records), "FIELD_A1" + delim + "FIELD_B1\nFIELD_A2" + delim + "FIELD_B2\n");
});

@@ -104,0 +116,0 @@ });

@@ -30,5 +30,5 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
var assert = require("assert");
var delimiter_1 = require("../helper/delimiter");
var index_1 = require("../../index");
var assert_1 = require("assert");
describe('ObjectCsvStringifier', function () {

@@ -43,3 +43,3 @@ var records = [

it('throws an exception', function () {
assert.throws(function () {
assert_1.throws(function () {
index_1.createObjectCsvStringifier({

@@ -54,3 +54,3 @@ header: ['FIELD_A', 'FIELD_B'],

it('throws an exception', function () {
assert.throws(function () {
assert_1.throws(function () {
index_1.createObjectCsvStringifier({

@@ -81,5 +81,20 @@ header: ['FIELD_A', 'FIELD_B'],

it('converts the records into CSV', function () {
assert.equal(stringifier.stringifyRecords(recordGenerator()), 'VALUE_A1,VALUE_B1\nVALUE_A2,VALUE_B2\n');
assert_1.strictEqual(stringifier.stringifyRecords(recordGenerator()), 'VALUE_A1,VALUE_B1\nVALUE_A2,VALUE_B2\n');
});
});
describe('When `alwaysQuote` flag is set', function () {
var stringifier = index_1.createObjectCsvStringifier({
header: [
{ id: 'FIELD_A', title: 'TITLE_A' },
{ id: 'FIELD_B', title: 'TITLE_B' }
],
alwaysQuote: true
});
it('quotes all header fields', function () {
assert_1.strictEqual(stringifier.getHeaderString(), '"TITLE_A","TITLE_B"\n');
});
it('quotes all data fields', function () {
assert_1.strictEqual(stringifier.stringifyRecords(records), '"VALUE_A1","VALUE_B1"\n"VALUE_A2","VALUE_B2"\n');
});
});
function generateTestCases(fieldDelimiter) {

@@ -97,6 +112,6 @@ var delim = delimiter_1.resolveDelimiterChar(fieldDelimiter);

it("returns a header line with field separated by \"" + delim + "\"", function () {
assert.equal(stringifier.getHeaderString(), "TITLE_A" + delim + "TITLE_B\n");
assert_1.strictEqual(stringifier.getHeaderString(), "TITLE_A" + delim + "TITLE_B\n");
});
it("converts given data records into CSV lines with field separated by \"" + delim + "\"", function () {
assert.equal(stringifier.stringifyRecords(records), "VALUE_A1" + delim + "VALUE_B1\nVALUE_A2" + delim + "VALUE_B2\n");
assert_1.strictEqual(stringifier.stringifyRecords(records), "VALUE_A1" + delim + "VALUE_B1\nVALUE_A2" + delim + "VALUE_B2\n");
});

@@ -110,6 +125,6 @@ });

it('returns null for header line', function () {
assert.equal(stringifier.getHeaderString(), null);
assert_1.strictEqual(stringifier.getHeaderString(), null);
});
it("converts given data records into CSV lines with field separated by \"" + delim + "\"", function () {
assert.equal(stringifier.stringifyRecords(records), "VALUE_A1" + delim + "VALUE_B1\nVALUE_A2" + delim + "VALUE_B2\n");
assert_1.strictEqual(stringifier.stringifyRecords(records), "VALUE_A1" + delim + "VALUE_B1\nVALUE_A2" + delim + "VALUE_B2\n");
});

@@ -126,3 +141,3 @@ });

it("layouts fields with the order of headers given with field separated by \"" + delim + "\"", function () {
assert.equal(stringifier.stringifyRecords(records), "VALUE_B1" + delim + "VALUE_A1\nVALUE_B2" + delim + "VALUE_A2\n");
assert_1.strictEqual(stringifier.stringifyRecords(records), "VALUE_B1" + delim + "VALUE_A1\nVALUE_B2" + delim + "VALUE_A2\n");
});

@@ -129,0 +144,0 @@ });

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var assert = require("assert");
var delimiter_1 = require("./helper/delimiter");
var field_stringifier_1 = require("../lib/field-stringifier");
describe('FieldStringifier', function () {
var assert_1 = require("assert");
describe('DefaultFieldStringifier', function () {
describe('When field delimiter is comma', generateTestCases(','));
describe('When field delimiter is semicolon', generateTestCases(';'));
describe('When all fields needs to be quoted', function () {
var stringifier = field_stringifier_1.createFieldStringifier(',', true);
it('quotes a field', function () {
assert_1.strictEqual(stringifier.stringify('VALUE'), '"VALUE"');
});
it('does not quote a field of value undefined', function () {
assert_1.strictEqual(stringifier.stringify(), '');
});
it('does not quote a field of value null', function () {
assert_1.strictEqual(stringifier.stringify(null), '');
});
it('does not quote a field of value empty string', function () {
assert_1.strictEqual(stringifier.stringify(''), '');
});
});
function generateTestCases(fieldDelimiter) {
var delim = delimiter_1.resolveDelimiterChar(fieldDelimiter);
return function () {
var stringifier = new field_stringifier_1.FieldStringifier(fieldDelimiter);
var stringifier = field_stringifier_1.createFieldStringifier(fieldDelimiter);
it('returns the same string', function () {
assert.equal(stringifier.stringify('VALUE'), 'VALUE');
assert_1.strictEqual(stringifier.stringify('VALUE'), 'VALUE');
});
it('preserves the whitespace characters', function () {
assert.equal(stringifier.stringify(' VALUE\tA '), ' VALUE\tA ');
assert_1.strictEqual(stringifier.stringify(' VALUE\tA '), ' VALUE\tA ');
});
it("wraps a field value with double quotes if the field contains \"" + delim + "\"", function () {
assert.equal(stringifier.stringify("VALUE" + delim + "A"), "\"VALUE" + delim + "A\"");
assert_1.strictEqual(stringifier.stringify("VALUE" + delim + "A"), "\"VALUE" + delim + "A\"");
});
it('wraps a field value with double quotes if the field contains newline', function () {
assert.equal(stringifier.stringify('VALUE\nA'), '"VALUE\nA"');
assert_1.strictEqual(stringifier.stringify('VALUE\nA'), '"VALUE\nA"');
});
it('wraps a field value with double quotes and escape the double quotes if they are used in the field', function () {
assert.equal(stringifier.stringify('VALUE"A'), '"VALUE""A"');
assert_1.strictEqual(stringifier.stringify('VALUE"A'), '"VALUE""A"');
});
it('escapes double quotes even if double quotes are only on the both edges of the field', function () {
assert.equal(stringifier.stringify('"VALUE"'), '"""VALUE"""');
assert_1.strictEqual(stringifier.stringify('"VALUE"'), '"""VALUE"""');
});
it('converts a number into a string', function () {
assert.equal(stringifier.stringify(1), '1');
assert_1.strictEqual(stringifier.stringify(1), '1');
});
it('converts undefined into an empty string', function () {
assert.equal(stringifier.stringify(), '');
assert_1.strictEqual(stringifier.stringify(), '');
});
it('converts null into an empty string', function () {
assert.equal(stringifier.stringify(null), '');
assert_1.strictEqual(stringifier.stringify(null), '');
});

@@ -45,3 +60,3 @@ it('converts an object into toString-ed value', function () {

};
assert.equal(stringifier.stringify(obj), 'Name: OBJECT_NAME');
assert_1.strictEqual(stringifier.stringify(obj), 'Name: OBJECT_NAME');
});

@@ -53,3 +68,3 @@ it("wraps a toString-ed field value with double quote if the value contains \"" + delim + "\"", function () {

};
assert.equal(stringifier.stringify(obj), "\"Name: OBJECT" + delim + "NAME\"");
assert_1.strictEqual(stringifier.stringify(obj), "\"Name: OBJECT" + delim + "NAME\"");
});

@@ -61,3 +76,3 @@ it('escapes double quotes in a toString-ed field value if the value has double quotes', function () {

};
assert.equal(stringifier.stringify(obj), '"Name: OBJECT_NAME"""');
assert_1.strictEqual(stringifier.stringify(obj), '"Name: OBJECT_NAME"""');
});

@@ -64,0 +79,0 @@ };

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var assert = require("assert");
var assert_1 = require("assert");
var fs = require('fs');

@@ -8,6 +8,6 @@ exports.testFilePath = function (id) { return "./test-tmp/" + id + ".csv"; };

var actualContents = fs.readFileSync(path, encoding || 'utf8');
assert.equal(actualContents, expectedContents);
assert_1.strictEqual(actualContents, expectedContents);
};
exports.assertContain = function (expectedSubstring, actualString) {
assert.ok(expectedSubstring.includes(actualString), actualString + " does not contain " + expectedSubstring);
assert_1.ok(expectedSubstring.includes(actualString), actualString + " does not contain " + expectedSubstring);
};

@@ -14,0 +14,0 @@ function mockType(params) {

@@ -40,3 +40,3 @@ "use strict";

var promise_1 = require("../../lib/lang/promise");
var assert = require("assert");
var assert_1 = require("assert");
describe('Promise', function () {

@@ -52,11 +52,11 @@ var greetAsync = function (name, callback) {

it('promisify node style callback', function () { return __awaiter(_this, void 0, void 0, function () {
var promisifiedFn, _a, _b;
return __generator(this, function (_c) {
switch (_c.label) {
var promisifiedFn, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
promisifiedFn = promise_1.promisify(greetAsync);
_b = (_a = assert).equal;
_a = assert_1.strictEqual;
return [4 /*yield*/, promisifiedFn('foo')];
case 1:
_b.apply(_a, [_c.sent(), 'Hello, foo!']);
_a.apply(void 0, [_b.sent(), 'Hello, foo!']);
return [2 /*return*/];

@@ -68,5 +68,5 @@ }

var promisifiedFn = promise_1.promisify(greetAsync);
return promisifiedFn('bar').then(function () { return new Error('Should not have been called'); }, function (e) { assert.equal(e.message, "We don't know bar"); });
return promisifiedFn('bar').then(function () { return new Error('Should not have been called'); }, function (e) { assert_1.strictEqual(e.message, "We don't know bar"); });
});
});
//# sourceMappingURL=promise.test.js.map

@@ -154,3 +154,22 @@ "use strict";

});
describe('When `alwaysQuote` flag is set', function () {
var filePath = makeFilePath('always-quote');
var writer = createArrayCsvWriter({
path: filePath,
header: ['NAME', 'LANGUAGE'],
alwaysQuote: true
});
it('quotes all fields', function () { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, writer.writeRecords(records)];
case 1:
_a.sent();
helper_1.assertFile(filePath, '"NAME","LANGUAGE"\n"Bob","French"\n"Mary","English"\n');
return [2 /*return*/];
}
});
}); });
});
});
//# sourceMappingURL=write-array-records.test.js.map

@@ -172,3 +172,22 @@ "use strict";

});
describe('When `alwaysQuote` flag is set', function () {
var filePath = makeFilePath('always-quote');
var writer = createObjectCsvWriter({
path: filePath,
header: [{ id: 'name', title: 'NAME' }, { id: 'lang', title: 'LANGUAGE' }],
alwaysQuote: true
});
it('quotes all fields', function () { return __awaiter(_this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, writer.writeRecords(records)];
case 1:
_a.sent();
helper_1.assertFile(filePath, '"NAME","LANGUAGE"\n"Bob","French"\n"Mary","English"\n');
return [2 /*return*/];
}
});
}); });
});
});
//# sourceMappingURL=write-object-records.test.js.map
{
"name": "csv-writer",
"version": "1.4.0",
"version": "1.5.0",
"description": "Convert objects/arrays into a CSV string or write them into a CSV file",

@@ -34,11 +34,11 @@ "main": "dist/index.js",

"@types/mocha": "^5.2.7",
"@types/node": "^12.0.7",
"@types/node": "^12.6.2",
"codeclimate-test-reporter": "^0.5.0",
"coveralls": "^3.0.4",
"coveralls": "^3.0.5",
"mocha": "^6.1.4",
"nyc": "^14.1.1",
"ts-node": "^8.2.0",
"tslint": "^5.17.0",
"typescript": "^3.5.1"
"ts-node": "^8.3.0",
"tslint": "^5.18.0",
"typescript": "^3.5.3"
}
}

@@ -145,2 +145,6 @@ [![Build Status](https://travis-ci.org/ryu1kn/csv-writer.svg?branch=master)](https://travis-ci.org/ryu1kn/csv-writer)

* alwaysQuote `<boolean>` (optional)
Default: `false`. Set it to `true` to double-quote all fields regardless of their values.
* encoding `<string>` (optional)

@@ -183,2 +187,6 @@

* alwaysQuote `<boolean>` (optional)
Default: `false`. Set it to `true` to double-quote all fields regardless of their values.
* encoding `<string>` (optional)

@@ -230,3 +238,7 @@

Default: `\n`. Only either LF (`\n`) or CRLF (`\r\n`) is allowed.
* alwaysQuote `<boolean>` (optional)
Default: `false`. Set it to `true` to double-quote all fields regardless of their values.
##### Returns:

@@ -269,2 +281,6 @@

* alwaysQuote `<boolean>` (optional)
Default: `false`. Set it to `true` to double-quote all fields regardless of their values.
##### Returns:

@@ -271,0 +287,0 @@

import {ArrayCsvStringifier} from './csv-stringifiers/array';
import {FieldStringifier} from './field-stringifier';
import {createFieldStringifier} from './field-stringifier';
import {ObjectCsvStringifier} from './csv-stringifiers/object';
import {ObjectStringifierHeader} from './record';
const DEFAULT_FIELD_DELIMITER = ',';
const VALID_FIELD_DELIMITERS = [DEFAULT_FIELD_DELIMITER, ';'];
export interface ArrayCsvStringifierParams {

@@ -13,2 +10,3 @@ header?: string[];

recordDelimiter?: string;
alwaysQuote?: boolean;
}

@@ -20,2 +18,3 @@

recordDelimiter?: string;
alwaysQuote?: boolean;
}

@@ -26,21 +25,11 @@

createArrayCsvStringifier(params: ArrayCsvStringifierParams) {
const fieldDelimiter = params.fieldDelimiter || DEFAULT_FIELD_DELIMITER;
_validateFieldDelimiter(fieldDelimiter);
const fieldStringifier = new FieldStringifier(fieldDelimiter);
return new ArrayCsvStringifier(fieldStringifier, fieldDelimiter, params.recordDelimiter, params.header);
const fieldStringifier = createFieldStringifier(params.fieldDelimiter, params.alwaysQuote);
return new ArrayCsvStringifier(fieldStringifier, params.recordDelimiter, params.header);
}
createObjectCsvStringifier(params: ObjectCsvStringifierParams) {
const fieldDelimiter = params.fieldDelimiter || DEFAULT_FIELD_DELIMITER;
_validateFieldDelimiter(fieldDelimiter);
const fieldStringifier = new FieldStringifier(fieldDelimiter);
return new ObjectCsvStringifier(fieldStringifier, fieldDelimiter, params.header, params.recordDelimiter);
const fieldStringifier = createFieldStringifier(params.fieldDelimiter, params.alwaysQuote);
return new ObjectCsvStringifier(fieldStringifier, params.header, params.recordDelimiter);
}
}
function _validateFieldDelimiter(delimiter: string): void {
if (VALID_FIELD_DELIMITERS.indexOf(delimiter) === -1) {
throw new Error(`Invalid field delimiter \`${delimiter}\` is specified`);
}
}

@@ -12,5 +12,5 @@ import {FieldStringifier} from '../field-stringifier';

constructor(fieldStringifier: FieldStringifier, fieldDelimiter: string, recordDelimiter?: string) {
constructor(fieldStringifier: FieldStringifier, recordDelimiter?: string) {
this.fieldStringifier = fieldStringifier;
this.fieldDelimiter = fieldDelimiter;
this.fieldDelimiter = fieldStringifier.fieldDelimiter;
this.recordDelimiter = recordDelimiter || DEFAULT_RECORD_DELIMITER;

@@ -17,0 +17,0 @@ _validateRecordDelimiter(this.recordDelimiter);

@@ -8,4 +8,4 @@ import {CsvStringifier} from './abstract';

constructor(fieldStringifier: FieldStringifier, fieldDelimiter: string, recordDelimiter?: string, header?: string[]) {
super(fieldStringifier, fieldDelimiter, recordDelimiter);
constructor(fieldStringifier: FieldStringifier, recordDelimiter?: string, header?: string[]) {
super(fieldStringifier, recordDelimiter);
this.header = header;

@@ -12,0 +12,0 @@ }

@@ -9,4 +9,4 @@ import {CsvStringifier} from './abstract';

constructor(fieldStringifier: FieldStringifier, fieldDelimiter: string, header: ObjectStringifierHeader, recordDelimiter?: string) {
super(fieldStringifier, fieldDelimiter, recordDelimiter);
constructor(fieldStringifier: FieldStringifier, header: ObjectStringifierHeader, recordDelimiter?: string) {
super(fieldStringifier, recordDelimiter);
this.header = header;

@@ -13,0 +13,0 @@ }

@@ -10,2 +10,3 @@ import {CsvWriter} from './csv-writer';

recordDelimiter?: string;
alwaysQuote?: boolean;
encoding?: string;

@@ -20,2 +21,3 @@ append?: boolean;

recordDelimiter?: string;
alwaysQuote?: boolean;
encoding?: string;

@@ -36,3 +38,4 @@ append?: boolean;

fieldDelimiter: params.fieldDelimiter,
recordDelimiter: params.recordDelimiter
recordDelimiter: params.recordDelimiter,
alwaysQuote: params.alwaysQuote
});

@@ -46,3 +49,4 @@ return new CsvWriter(csvStringifier, params.path, params.encoding, params.append);

fieldDelimiter: params.fieldDelimiter,
recordDelimiter: params.recordDelimiter
recordDelimiter: params.recordDelimiter,
alwaysQuote: params.alwaysQuote
});

@@ -49,0 +53,0 @@ return new CsvWriter(csvStringifier, params.path, params.encoding, params.append);

import {Field} from './record';
export class FieldStringifier {
private readonly fieldDelimiter: string;
const DEFAULT_FIELD_DELIMITER = ',';
const VALID_FIELD_DELIMITERS = [DEFAULT_FIELD_DELIMITER, ';'];
export abstract class FieldStringifier {
private readonly _fieldDelimiter: string;
constructor(fieldDelimiter: string) {
this.fieldDelimiter = fieldDelimiter;
this._fieldDelimiter = fieldDelimiter;
}
get fieldDelimiter(): string {
return this._fieldDelimiter;
}
abstract stringify(value?: Field): string;
protected isEmpty(value?: Field): boolean {
return typeof value === 'undefined' || value === null || value === '';
}
protected quoteField(field: string): string {
return `"${field.replace(/"/g, '""')}"`;
}
}
class DefaultFieldStringifier extends FieldStringifier {
stringify(value?: Field): string {
if (typeof value === 'undefined' || value === null) return '';
if (this.isEmpty(value)) return '';
const str = String(value);
return this.needsQuote(str) ? `"${str.replace(/"/g, '""')}"` : str;
return this.needsQuote(str) ? this.quoteField(str) : str;
}

@@ -20,1 +39,18 @@

}
class ForceQuoteFieldStringifier extends FieldStringifier {
stringify(value?: Field): string {
return this.isEmpty(value) ? '' : this.quoteField(String(value));
}
}
export function createFieldStringifier(fieldDelimiter: string = DEFAULT_FIELD_DELIMITER, alwaysQuote = false) {
_validateFieldDelimiter(fieldDelimiter);
return alwaysQuote ? new ForceQuoteFieldStringifier(fieldDelimiter) : new DefaultFieldStringifier(fieldDelimiter);
}
function _validateFieldDelimiter(delimiter: string): void {
if (VALID_FIELD_DELIMITERS.indexOf(delimiter) === -1) {
throw new Error(`Invalid field delimiter \`${delimiter}\` is specified`);
}
}

@@ -1,4 +0,4 @@

import * as assert from 'assert';
import {resolveDelimiterChar} from '../helper/delimiter';
import {createArrayCsvStringifier} from '../../index';
import {strictEqual, throws} from 'assert';

@@ -17,3 +17,3 @@ describe('ArrayCsvStringifier', () => {

it('throws an exception', () => {
assert.throws(() => {
throws(() => {
createArrayCsvStringifier({fieldDelimiter: '/'});

@@ -26,3 +26,3 @@ });

it('throws an exception', () => {
assert.throws(() => {
throws(() => {
createArrayCsvStringifier({recordDelimiter: '\r'});

@@ -43,3 +43,3 @@ });

it('converts the records into CSV', () => {
assert.equal(
strictEqual(
stringifier.stringifyRecords(recordGenerator()),

@@ -51,2 +51,17 @@ 'FIELD_A1,FIELD_B1\nFIELD_A2,FIELD_B2\n'

describe('When `alwaysQuote` flag is set', () => {
const stringifier = createArrayCsvStringifier({
header: ['TITLE_A', 'TITLE_B'],
alwaysQuote: true
});
it('quotes all header fields', () => {
strictEqual(stringifier.getHeaderString(), '"TITLE_A","TITLE_B"\n');
});
it('quotes all data fields', () => {
strictEqual(stringifier.stringifyRecords(records), '"FIELD_A1","FIELD_B1"\n"FIELD_A2","FIELD_B2"\n');
});
});
function generateTestCases(fieldDelimiter?: string) {

@@ -62,7 +77,7 @@ const delim = resolveDelimiterChar(fieldDelimiter);

it(`returns a header line with field separated by "${delim}"`, () => {
assert.equal(stringifier.getHeaderString(), `TITLE_A${delim}TITLE_B\n`);
strictEqual(stringifier.getHeaderString(), `TITLE_A${delim}TITLE_B\n`);
});
it(`converts given data records into CSV lines with field separated by "${delim}"`, () => {
assert.equal(
strictEqual(
stringifier.stringifyRecords(records),

@@ -78,7 +93,7 @@ `FIELD_A1${delim}FIELD_B1\nFIELD_A2${delim}FIELD_B2\n`

it('returns null for header line', () => {
assert.equal(stringifier.getHeaderString(), null);
strictEqual(stringifier.getHeaderString(), null);
});
it(`converts given data records into CSV lines with field separated by "${delim}"`, () => {
assert.equal(
strictEqual(
stringifier.stringifyRecords(records),

@@ -85,0 +100,0 @@ `FIELD_A1${delim}FIELD_B1\nFIELD_A2${delim}FIELD_B2\n`

@@ -1,4 +0,4 @@

import * as assert from 'assert';
import {resolveDelimiterChar} from '../helper/delimiter';
import {createObjectCsvStringifier} from '../../index';
import {strictEqual, throws} from 'assert';

@@ -17,3 +17,3 @@ describe('ObjectCsvStringifier', () => {

it('throws an exception', () => {
assert.throws(() => {
throws(() => {
createObjectCsvStringifier({

@@ -29,3 +29,3 @@ header: ['FIELD_A', 'FIELD_B'],

it('throws an exception', () => {
assert.throws(() => {
throws(() => {
createObjectCsvStringifier({

@@ -49,3 +49,3 @@ header: ['FIELD_A', 'FIELD_B'],

it('converts the records into CSV', () => {
assert.equal(
strictEqual(
stringifier.stringifyRecords(recordGenerator()),

@@ -57,2 +57,20 @@ 'VALUE_A1,VALUE_B1\nVALUE_A2,VALUE_B2\n'

describe('When `alwaysQuote` flag is set', () => {
const stringifier = createObjectCsvStringifier({
header: [
{id: 'FIELD_A', title: 'TITLE_A'},
{id: 'FIELD_B', title: 'TITLE_B'}
],
alwaysQuote: true
});
it('quotes all header fields', () => {
strictEqual(stringifier.getHeaderString(), '"TITLE_A","TITLE_B"\n');
});
it('quotes all data fields', () => {
strictEqual(stringifier.stringifyRecords(records), '"VALUE_A1","VALUE_B1"\n"VALUE_A2","VALUE_B2"\n');
});
});
function generateTestCases(fieldDelimiter?: string) {

@@ -71,7 +89,7 @@ const delim = resolveDelimiterChar(fieldDelimiter);

it(`returns a header line with field separated by "${delim}"`, () => {
assert.equal(stringifier.getHeaderString(), `TITLE_A${delim}TITLE_B\n`);
strictEqual(stringifier.getHeaderString(), `TITLE_A${delim}TITLE_B\n`);
});
it(`converts given data records into CSV lines with field separated by "${delim}"`, () => {
assert.equal(
strictEqual(
stringifier.stringifyRecords(records),

@@ -90,7 +108,7 @@ `VALUE_A1${delim}VALUE_B1\nVALUE_A2${delim}VALUE_B2\n`

it('returns null for header line', () => {
assert.equal(stringifier.getHeaderString(), null);
strictEqual(stringifier.getHeaderString(), null);
});
it(`converts given data records into CSV lines with field separated by "${delim}"`, () => {
assert.equal(
strictEqual(
stringifier.stringifyRecords(records),

@@ -112,3 +130,3 @@ `VALUE_A1${delim}VALUE_B1\nVALUE_A2${delim}VALUE_B2\n`

it(`layouts fields with the order of headers given with field separated by "${delim}"`, () => {
assert.equal(
strictEqual(
stringifier.stringifyRecords(records),

@@ -115,0 +133,0 @@ `VALUE_B1${delim}VALUE_A1\nVALUE_B2${delim}VALUE_A2\n`

@@ -1,6 +0,6 @@

import * as assert from 'assert';
import {resolveDelimiterChar} from './helper/delimiter';
import {FieldStringifier} from '../lib/field-stringifier';
import {createFieldStringifier} from '../lib/field-stringifier';
import {strictEqual} from 'assert';
describe('FieldStringifier', () => {
describe('DefaultFieldStringifier', () => {

@@ -11,41 +11,61 @@ describe('When field delimiter is comma', generateTestCases(','));

describe('When all fields needs to be quoted', () => {
const stringifier = createFieldStringifier(',', true);
it('quotes a field', () => {
strictEqual(stringifier.stringify('VALUE'), '"VALUE"');
});
it('does not quote a field of value undefined', () => {
strictEqual(stringifier.stringify(), '');
});
it('does not quote a field of value null', () => {
strictEqual(stringifier.stringify(null), '');
});
it('does not quote a field of value empty string', () => {
strictEqual(stringifier.stringify(''), '');
});
});
function generateTestCases(fieldDelimiter: string) {
const delim = resolveDelimiterChar(fieldDelimiter);
return () => {
const stringifier = new FieldStringifier(fieldDelimiter);
const stringifier = createFieldStringifier(fieldDelimiter);
it('returns the same string', () => {
assert.equal(stringifier.stringify('VALUE'), 'VALUE');
strictEqual(stringifier.stringify('VALUE'), 'VALUE');
});
it('preserves the whitespace characters', () => {
assert.equal(stringifier.stringify(' VALUE\tA '), ' VALUE\tA ');
strictEqual(stringifier.stringify(' VALUE\tA '), ' VALUE\tA ');
});
it(`wraps a field value with double quotes if the field contains "${delim}"`, () => {
assert.equal(stringifier.stringify(`VALUE${delim}A`), `"VALUE${delim}A"`);
strictEqual(stringifier.stringify(`VALUE${delim}A`), `"VALUE${delim}A"`);
});
it('wraps a field value with double quotes if the field contains newline', () => {
assert.equal(stringifier.stringify('VALUE\nA'), '"VALUE\nA"');
strictEqual(stringifier.stringify('VALUE\nA'), '"VALUE\nA"');
});
it('wraps a field value with double quotes and escape the double quotes if they are used in the field', () => {
assert.equal(stringifier.stringify('VALUE"A'), '"VALUE""A"');
strictEqual(stringifier.stringify('VALUE"A'), '"VALUE""A"');
});
it('escapes double quotes even if double quotes are only on the both edges of the field', () => {
assert.equal(stringifier.stringify('"VALUE"'), '"""VALUE"""');
strictEqual(stringifier.stringify('"VALUE"'), '"""VALUE"""');
});
it('converts a number into a string', () => {
assert.equal(stringifier.stringify(1), '1');
strictEqual(stringifier.stringify(1), '1');
});
it('converts undefined into an empty string', () => {
assert.equal(stringifier.stringify(), '');
strictEqual(stringifier.stringify(), '');
});
it('converts null into an empty string', () => {
assert.equal(stringifier.stringify(null), '');
strictEqual(stringifier.stringify(null), '');
});

@@ -58,3 +78,3 @@

};
assert.equal(stringifier.stringify(obj), 'Name: OBJECT_NAME');
strictEqual(stringifier.stringify(obj), 'Name: OBJECT_NAME');
});

@@ -67,3 +87,3 @@

};
assert.equal(stringifier.stringify(obj), `"Name: OBJECT${delim}NAME"`);
strictEqual(stringifier.stringify(obj), `"Name: OBJECT${delim}NAME"`);
});

@@ -76,3 +96,3 @@

};
assert.equal(stringifier.stringify(obj), '"Name: OBJECT_NAME"""');
strictEqual(stringifier.stringify(obj), '"Name: OBJECT_NAME"""');
});

@@ -79,0 +99,0 @@ };

@@ -1,2 +0,2 @@

import * as assert from 'assert';
import {ok, strictEqual} from 'assert';

@@ -9,7 +9,7 @@ const fs = require('fs');

const actualContents = fs.readFileSync(path, encoding || 'utf8');
assert.equal(actualContents, expectedContents);
strictEqual(actualContents, expectedContents);
};
export const assertContain = (expectedSubstring: string, actualString: string) => {
assert.ok(
ok(
expectedSubstring.includes(actualString),

@@ -16,0 +16,0 @@ `${actualString} does not contain ${expectedSubstring}`

import {promisify} from '../../lib/lang/promise';
import * as assert from 'assert';
import {strictEqual} from 'assert';

@@ -14,3 +14,3 @@ describe('Promise', () => {

const promisifiedFn = promisify(greetAsync);
assert.equal(await promisifiedFn('foo'), 'Hello, foo!');
strictEqual(await promisifiedFn('foo'), 'Hello, foo!');
});

@@ -22,5 +22,5 @@

() => new Error('Should not have been called'),
(e: Error) => { assert.equal(e.message, "We don't know bar"); }
(e: Error) => { strictEqual(e.message, "We don't know bar"); }
);
});
});

@@ -119,2 +119,16 @@ import {assertFile, testFilePath} from './helper';

});
describe('When `alwaysQuote` flag is set', () => {
const filePath = makeFilePath('always-quote');
const writer = createArrayCsvWriter({
path: filePath,
header: ['NAME', 'LANGUAGE'],
alwaysQuote: true
});
it('quotes all fields', async () => {
await writer.writeRecords(records);
assertFile(filePath, '"NAME","LANGUAGE"\n"Bob","French"\n"Mary","English"\n');
});
});
});

@@ -139,2 +139,16 @@ import {assertFile, testFilePath} from './helper';

});
describe('When `alwaysQuote` flag is set', () => {
const filePath = makeFilePath('always-quote');
const writer = createObjectCsvWriter({
path: filePath,
header: [{id: 'name', title: 'NAME'}, {id: 'lang', title: 'LANGUAGE'}],
alwaysQuote: true
});
it('quotes all fields', async () => {
await writer.writeRecords(records);
assertFile(filePath, '"NAME","LANGUAGE"\n"Bob","French"\n"Mary","English"\n');
});
});
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc