Socket
Socket
Sign inDemoInstall

csv-writer

Package Overview
Dependencies
0
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.5.0 to 1.6.0

dist/lib/lang/object.js

4

CHANGELOG.md

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

## [1.6.0] - 2020-01-18
### Added
- Support for specifying values in nested objects. [#34](https://github.com/ryu1kn/csv-writer/pull/34)
## [1.5.0] - 2019-07-13

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

2

dist/lib/csv-stringifier-factory.js

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

var fieldStringifier = field_stringifier_1.createFieldStringifier(params.fieldDelimiter, params.alwaysQuote);
return new object_1.ObjectCsvStringifier(fieldStringifier, params.header, params.recordDelimiter);
return new object_1.ObjectCsvStringifier(fieldStringifier, params.header, params.recordDelimiter, params.headerIdDelimiter);
};

@@ -18,0 +18,0 @@ return CsvStringifierFactory;

@@ -7,10 +7,10 @@ "use strict";

function CsvStringifier(fieldStringifier, recordDelimiter) {
if (recordDelimiter === void 0) { recordDelimiter = DEFAULT_RECORD_DELIMITER; }
this.fieldStringifier = fieldStringifier;
this.fieldDelimiter = fieldStringifier.fieldDelimiter;
this.recordDelimiter = recordDelimiter || DEFAULT_RECORD_DELIMITER;
_validateRecordDelimiter(this.recordDelimiter);
this.recordDelimiter = recordDelimiter;
_validateRecordDelimiter(recordDelimiter);
}
CsvStringifier.prototype.getHeaderString = function () {
var headerRecord = this.getHeaderRecord();
return headerRecord ? this.stringifyRecords([headerRecord]) : null;
return headerRecord ? this.joinRecords([this.getCsvLine(headerRecord)]) : null;
};

@@ -20,3 +20,3 @@ CsvStringifier.prototype.stringifyRecords = function (records) {

var csvLines = Array.from(records, function (record) { return _this.getCsvLine(_this.getRecordAsArray(record)); });
return csvLines.join(this.recordDelimiter) + this.recordDelimiter;
return this.joinRecords(csvLines);
};

@@ -27,4 +27,7 @@ CsvStringifier.prototype.getCsvLine = function (record) {

.map(function (fieldValue) { return _this.fieldStringifier.stringify(fieldValue); })
.join(this.fieldDelimiter);
.join(this.fieldStringifier.fieldDelimiter);
};
CsvStringifier.prototype.joinRecords = function (records) {
return records.join(this.recordDelimiter) + this.recordDelimiter;
};
return CsvStringifier;

@@ -31,0 +34,0 @@ }());

@@ -17,7 +17,9 @@ "use strict";

var abstract_1 = require("./abstract");
var object_1 = require("../lang/object");
var ObjectCsvStringifier = /** @class */ (function (_super) {
__extends(ObjectCsvStringifier, _super);
function ObjectCsvStringifier(fieldStringifier, header, recordDelimiter) {
function ObjectCsvStringifier(fieldStringifier, header, recordDelimiter, headerIdDelimiter) {
var _this = _super.call(this, fieldStringifier, recordDelimiter) || this;
_this.header = header;
_this.headerIdDelimiter = headerIdDelimiter;
return _this;

@@ -28,10 +30,13 @@ }

return null;
return this.header.reduce(function (memo, field) {
var _a;
return Object.assign({}, memo, (_a = {}, _a[field.id] = field.title, _a));
}, {});
return this.header.map(function (field) { return field.title; });
};
ObjectCsvStringifier.prototype.getRecordAsArray = function (record) {
return this.fieldIds.map(function (field) { return record[field]; });
var _this = this;
return this.fieldIds.map(function (fieldId) { return _this.getNestedValue(record, fieldId); });
};
ObjectCsvStringifier.prototype.getNestedValue = function (obj, key) {
if (!this.headerIdDelimiter)
return obj[key];
return key.split(this.headerIdDelimiter).reduce(function (subObj, keyPart) { return (subObj || {})[keyPart]; }, obj);
};
Object.defineProperty(ObjectCsvStringifier.prototype, "fieldIds", {

@@ -46,3 +51,3 @@ get: function () {

get: function () {
return isObject(this.header && this.header[0]);
return object_1.isObject(this.header && this.header[0]);
},

@@ -55,5 +60,2 @@ enumerable: true,

exports.ObjectCsvStringifier = ObjectCsvStringifier;
function isObject(value) {
return Object.prototype.toString.call(value) === '[object Object]';
}
//# sourceMappingURL=object.js.map

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

recordDelimiter: params.recordDelimiter,
headerIdDelimiter: params.headerIdDelimiter,
alwaysQuote: params.alwaysQuote

@@ -24,0 +25,0 @@ });

"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());

@@ -42,5 +43,6 @@ });

function CsvWriter(csvStringifier, path, encoding, append) {
this.append = append || DEFAULT_INITIAL_APPEND_FLAG;
if (append === void 0) { append = DEFAULT_INITIAL_APPEND_FLAG; }
this.csvStringifier = csvStringifier;
this.append = append;
this.fileWriter = new file_writer_1.FileWriter(path, this.append, encoding);
this.csvStringifier = csvStringifier;
}

@@ -47,0 +49,0 @@ CsvWriter.prototype.writeRecords = function (records) {

@@ -20,11 +20,4 @@ "use strict";

function FieldStringifier(fieldDelimiter) {
this._fieldDelimiter = fieldDelimiter;
this.fieldDelimiter = fieldDelimiter;
}
Object.defineProperty(FieldStringifier.prototype, "fieldDelimiter", {
get: function () {
return this._fieldDelimiter;
},
enumerable: true,
configurable: true
});
FieldStringifier.prototype.isEmpty = function (value) {

@@ -31,0 +24,0 @@ return typeof value === 'undefined' || value === null || value === '';

"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());

@@ -44,5 +45,6 @@ });

function FileWriter(path, append, encoding) {
if (encoding === void 0) { encoding = DEFAULT_ENCODING; }
this.path = path;
this.append = append;
this.encoding = encoding || DEFAULT_ENCODING;
this.encoding = encoding;
}

@@ -49,0 +51,0 @@ FileWriter.prototype.write = function (string) {

"use strict";
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
Object.defineProperty(exports, "__esModule", { value: true });

@@ -16,3 +23,3 @@ function promisify(fn) {

};
fn.apply(null, args.concat([nodeCallback]));
fn.apply(null, __spreadArrays(args, [nodeCallback]));
});

@@ -19,0 +26,0 @@ };

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

{ FIELD_A: 'VALUE_A1', FIELD_B: 'VALUE_B1' },
{ FIELD_A: 'VALUE_A2', FIELD_B: 'VALUE_B2' }
{ FIELD_A: 'VALUE_A2', FIELD_B: 'VALUE_B2', OTHERS: { FIELD_C: 'VALUE_C2' } }
];

@@ -97,2 +97,17 @@ describe('When field delimiter is comma', generateTestCases());

});
describe('When `headerIdDelimiter` is set', function () {
var stringifier = index_1.createObjectCsvStringifier({
header: [
{ id: 'FIELD_A', title: 'TITLE_A' },
{ id: 'OTHERS/FIELD_C', title: 'TITLE_C' }
],
headerIdDelimiter: '/'
});
it('uses the title as is', function () {
assert_1.strictEqual(stringifier.getHeaderString(), 'TITLE_A,TITLE_C\n');
});
it('picks up a value in nested objects', function () {
assert_1.strictEqual(stringifier.stringifyRecords(records), 'VALUE_A1,\nVALUE_A2,VALUE_C2\n');
});
});
function generateTestCases(fieldDelimiter) {

@@ -99,0 +114,0 @@ var delim = delimiter_1.resolveDelimiterChar(fieldDelimiter);

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var assert_1 = require("assert");
var fs = require('fs');
var fs_1 = require("fs");
exports.testFilePath = function (id) { return "./test-tmp/" + id + ".csv"; };
exports.assertFile = function (path, expectedContents, encoding) {
var actualContents = fs.readFileSync(path, encoding || 'utf8');
var actualContents = fs_1.readFileSync(path, encoding || 'utf8');
assert_1.strictEqual(actualContents, expectedContents);
};
exports.assertContain = function (expectedSubstring, actualString) {
assert_1.ok(expectedSubstring.includes(actualString), actualString + " does not contain " + expectedSubstring);
exports.assertRejected = function (p, message) {
return p.then(function () { return new Error('Should not have been called'); }, function (e) { assert_1.strictEqual(e.message, message); });
};
function mockType(params) {
return Object.assign({}, params);
}
exports.mockType = mockType;
//# sourceMappingURL=helper.js.map
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());

@@ -37,6 +38,6 @@ });

};
var _this = this;
Object.defineProperty(exports, "__esModule", { value: true });
var promise_1 = require("../../lib/lang/promise");
var assert_1 = require("assert");
var helper_1 = require("../helper");
describe('Promise', function () {

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

};
it('promisify node style callback', function () { return __awaiter(_this, void 0, void 0, function () {
var promisifiedFn, _a;
var promisifiedFn = promise_1.promisify(greetAsync);
it('promisify node style callback', function () { return __awaiter(void 0, void 0, void 0, function () {
var _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
promisifiedFn = promise_1.promisify(greetAsync);
_a = assert_1.strictEqual;

@@ -66,7 +67,13 @@ return [4 /*yield*/, promisifiedFn('foo')];

}); });
it('raise an error for error', function () {
var promisifiedFn = promise_1.promisify(greetAsync);
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"); });
});
it('raise an error for error', function () { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, helper_1.assertRejected(promisifiedFn('bar'), "We don't know bar")];
case 1:
_a.sent();
return [2 /*return*/];
}
});
}); });
});
//# sourceMappingURL=promise.test.js.map
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());

@@ -37,7 +38,6 @@ });

};
var _this = this;
Object.defineProperty(exports, "__esModule", { value: true });
var helper_1 = require("./helper");
var fs = require('fs');
var createArrayCsvWriter = require('../index').createArrayCsvWriter;
var fs_1 = require("fs");
var index_1 = require("../index");
describe('Write array records into CSV', function () {

@@ -50,14 +50,19 @@ var makeFilePath = function (id) { return helper_1.testFilePath("array-" + id); };

describe('When only path is specified', function () {
'use strict';
var filePath = makeFilePath('minimum');
var writer;
beforeEach(function () {
writer = createArrayCsvWriter({ path: filePath });
writer = index_1.createArrayCsvWriter({ path: filePath });
});
it('writes records to a new file', function () {
return writer.writeRecords(records).then(function () {
helper_1.assertFile(filePath, 'Bob,French\nMary,English\n');
it('writes records to a new file', function () { return __awaiter(void 0, 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, 'Bob,French\nMary,English\n');
return [2 /*return*/];
}
});
});
it('appends records when requested to write to the same file', function () { return __awaiter(_this, void 0, void 0, function () {
}); });
it('appends records when requested to write to the same file', function () { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {

@@ -81,3 +86,3 @@ switch (_a.label) {

beforeEach(function () {
writer = createArrayCsvWriter({
writer = index_1.createArrayCsvWriter({
path: filePath,

@@ -87,8 +92,14 @@ header: ['NAME', 'LANGUAGE']

});
it('writes a header', function () {
return writer.writeRecords(records).then(function () {
helper_1.assertFile(filePath, 'NAME,LANGUAGE\nBob,French\nMary,English\n');
it('writes a header', function () { return __awaiter(void 0, 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\nBob,French\nMary,English\n');
return [2 /*return*/];
}
});
});
it('appends records without headers', function () { return __awaiter(_this, void 0, void 0, function () {
}); });
it('appends records without headers', function () { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {

@@ -110,28 +121,40 @@ switch (_a.label) {

var filePath = makeFilePath('append');
fs.writeFileSync(filePath, 'Mike,German\n', 'utf8');
var writer = createArrayCsvWriter({
fs_1.writeFileSync(filePath, 'Mike,German\n', 'utf8');
var writer = index_1.createArrayCsvWriter({
path: filePath,
append: true
});
it('do not overwrite the existing contents and appends records to them', function () {
return writer.writeRecords([records[1]]).then(function () {
helper_1.assertFile(filePath, 'Mike,German\nMary,English\n');
it('do not overwrite the existing contents and appends records to them', function () { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, writer.writeRecords([records[1]])];
case 1:
_a.sent();
helper_1.assertFile(filePath, 'Mike,German\nMary,English\n');
return [2 /*return*/];
}
});
});
}); });
});
describe('When encoding is specified', function () {
var filePath = makeFilePath('encoding');
var writer = createArrayCsvWriter({
var writer = index_1.createArrayCsvWriter({
path: filePath,
encoding: 'utf16le'
});
it('writes to a file with the specified encoding', function () {
return writer.writeRecords(records).then(function () {
helper_1.assertFile(filePath, 'Bob,French\nMary,English\n', 'utf16le');
it('writes to a file with the specified encoding', function () { return __awaiter(void 0, 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, 'Bob,French\nMary,English\n', 'utf16le');
return [2 /*return*/];
}
});
});
}); });
});
describe('When semicolon is specified as a field delimiter', function () {
var filePath = makeFilePath('field-delimiter');
var writer = createArrayCsvWriter({
var writer = index_1.createArrayCsvWriter({
path: filePath,

@@ -141,23 +164,35 @@ header: ['NAME', 'LANGUAGE'],

});
it('uses semicolon instead of comma to separate fields', function () {
return writer.writeRecords(records).then(function () {
helper_1.assertFile(filePath, 'NAME;LANGUAGE\nBob;French\nMary;English\n');
it('uses semicolon instead of comma to separate fields', function () { return __awaiter(void 0, 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\nBob;French\nMary;English\n');
return [2 /*return*/];
}
});
});
}); });
});
describe('When newline is specified', function () {
var filePath = makeFilePath('newline');
var writer = createArrayCsvWriter({
var writer = index_1.createArrayCsvWriter({
path: filePath,
recordDelimiter: '\r\n'
});
it('writes to a file with the specified newline character', function () {
return writer.writeRecords(records).then(function () {
helper_1.assertFile(filePath, 'Bob,French\r\nMary,English\r\n');
it('writes to a file with the specified newline character', function () { return __awaiter(void 0, 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, 'Bob,French\r\nMary,English\r\n');
return [2 /*return*/];
}
});
});
}); });
});
describe('When `alwaysQuote` flag is set', function () {
var filePath = makeFilePath('always-quote');
var writer = createArrayCsvWriter({
var writer = index_1.createArrayCsvWriter({
path: filePath,

@@ -167,3 +202,3 @@ header: ['NAME', 'LANGUAGE'],

});
it('quotes all fields', function () { return __awaiter(_this, void 0, void 0, function () {
it('quotes all fields', function () { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {

@@ -170,0 +205,0 @@ switch (_a.label) {

"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());

@@ -37,19 +38,17 @@ });

};
var _this = this;
Object.defineProperty(exports, "__esModule", { value: true });
var helper_1 = require("./helper");
var fs = require('fs');
var createObjectCsvWriter = require('../index').createObjectCsvWriter;
var fs_1 = require("fs");
var index_1 = require("../index");
describe('Write object records into CSV', function () {
var makeFilePath = function (id) { return helper_1.testFilePath("object-" + id); };
var records = [
{ name: 'Bob', lang: 'French' },
{ name: 'Bob', lang: 'French', address: { country: 'France' } },
{ name: 'Mary', lang: 'English' }
];
describe('When only path and header ids are given', function () {
'use strict';
var filePath = makeFilePath('minimum');
var writer;
beforeEach(function () {
writer = createObjectCsvWriter({
writer = index_1.createObjectCsvWriter({
path: filePath,

@@ -59,8 +58,14 @@ header: ['name', 'lang']

});
it('writes records to a new file', function () {
return writer.writeRecords(records).then(function () {
helper_1.assertFile(filePath, 'Bob,French\nMary,English\n');
it('writes records to a new file', function () { return __awaiter(void 0, 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, 'Bob,French\nMary,English\n');
return [2 /*return*/];
}
});
});
it('appends records when requested to write to the same file', function () { return __awaiter(_this, void 0, void 0, function () {
}); });
it('appends records when requested to write to the same file', function () { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {

@@ -82,11 +87,17 @@ switch (_a.label) {

var filePath = makeFilePath('column-order');
var writer = createObjectCsvWriter({
var writer = index_1.createObjectCsvWriter({
path: filePath,
header: ['lang', 'name']
});
it('also writes columns with reverse order', function () {
return writer.writeRecords(records).then(function () {
helper_1.assertFile(filePath, 'French,Bob\nEnglish,Mary\n');
it('also writes columns with reverse order', function () { return __awaiter(void 0, 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, 'French,Bob\nEnglish,Mary\n');
return [2 /*return*/];
}
});
});
}); });
});

@@ -97,3 +108,3 @@ describe('When field header is given with titles', function () {

beforeEach(function () {
writer = createObjectCsvWriter({
writer = index_1.createObjectCsvWriter({
path: filePath,

@@ -103,8 +114,14 @@ header: [{ id: 'name', title: 'NAME' }, { id: 'lang', title: 'LANGUAGE' }]

});
it('writes a header', function () {
return writer.writeRecords(records).then(function () {
helper_1.assertFile(filePath, 'NAME,LANGUAGE\nBob,French\nMary,English\n');
it('writes a header', function () { return __awaiter(void 0, 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\nBob,French\nMary,English\n');
return [2 /*return*/];
}
});
});
it('appends records without headers', function () { return __awaiter(_this, void 0, void 0, function () {
}); });
it('appends records without headers', function () { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {

@@ -126,4 +143,4 @@ switch (_a.label) {

var filePath = makeFilePath('append');
fs.writeFileSync(filePath, 'Mike,German\n', 'utf8');
var writer = createObjectCsvWriter({
fs_1.writeFileSync(filePath, 'Mike,German\n', 'utf8');
var writer = index_1.createObjectCsvWriter({
path: filePath,

@@ -133,11 +150,17 @@ header: ['name', 'lang'],

});
it('do not overwrite the existing contents and appends records to them', function () {
return writer.writeRecords([records[1]]).then(function () {
helper_1.assertFile(filePath, 'Mike,German\nMary,English\n');
it('do not overwrite the existing contents and appends records to them', function () { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, writer.writeRecords([records[1]])];
case 1:
_a.sent();
helper_1.assertFile(filePath, 'Mike,German\nMary,English\n');
return [2 /*return*/];
}
});
});
}); });
});
describe('When encoding is specified', function () {
var filePath = makeFilePath('encoding');
var writer = createObjectCsvWriter({
var writer = index_1.createObjectCsvWriter({
path: filePath,

@@ -147,11 +170,17 @@ header: ['name', 'lang'],

});
it('writes to a file with the specified encoding', function () {
return writer.writeRecords(records).then(function () {
helper_1.assertFile(filePath, 'Bob,French\nMary,English\n', 'utf16le');
it('writes to a file with the specified encoding', function () { return __awaiter(void 0, 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, 'Bob,French\nMary,English\n', 'utf16le');
return [2 /*return*/];
}
});
});
}); });
});
describe('When semicolon is specified as a field delimiter', function () {
var filePath = makeFilePath('field-delimiter');
var writer = createObjectCsvWriter({
var writer = index_1.createObjectCsvWriter({
path: filePath,

@@ -161,11 +190,17 @@ header: [{ id: 'name', title: 'NAME' }, { id: 'lang', title: 'LANGUAGE' }],

});
it('uses semicolon instead of comma to separate fields', function () {
return writer.writeRecords(records).then(function () {
helper_1.assertFile(filePath, 'NAME;LANGUAGE\nBob;French\nMary;English\n');
it('uses semicolon instead of comma to separate fields', function () { return __awaiter(void 0, 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\nBob;French\nMary;English\n');
return [2 /*return*/];
}
});
});
}); });
});
describe('When newline is specified', function () {
var filePath = makeFilePath('newline');
var writer = createObjectCsvWriter({
var writer = index_1.createObjectCsvWriter({
path: filePath,

@@ -175,11 +210,17 @@ header: ['name', 'lang'],

});
it('writes to a file with the specified newline character', function () {
return writer.writeRecords(records).then(function () {
helper_1.assertFile(filePath, 'Bob,French\r\nMary,English\r\n');
it('writes to a file with the specified newline character', function () { return __awaiter(void 0, 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, 'Bob,French\r\nMary,English\r\n');
return [2 /*return*/];
}
});
});
}); });
});
describe('When `alwaysQuote` flag is set', function () {
var filePath = makeFilePath('always-quote');
var writer = createObjectCsvWriter({
var writer = index_1.createObjectCsvWriter({
path: filePath,

@@ -189,3 +230,3 @@ header: [{ id: 'name', title: 'NAME' }, { id: 'lang', title: 'LANGUAGE' }],

});
it('quotes all fields', function () { return __awaiter(_this, void 0, void 0, function () {
it('quotes all fields', function () { return __awaiter(void 0, void 0, void 0, function () {
return __generator(this, function (_a) {

@@ -202,3 +243,22 @@ switch (_a.label) {

});
describe('When `headerIdDelimiter` flag is set', function () {
var filePath = makeFilePath('nested');
var writer = index_1.createObjectCsvWriter({
path: filePath,
header: [{ id: 'name', title: 'NAME' }, { id: 'address.country', title: 'COUNTRY' }],
headerIdDelimiter: '.'
});
it('breaks keys into key paths', function () { return __awaiter(void 0, 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,COUNTRY\nBob,France\nMary,\n');
return [2 /*return*/];
}
});
}); });
});
});
//# sourceMappingURL=write-object-records.test.js.map
{
"name": "csv-writer",
"version": "1.5.0",
"version": "1.6.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.6.2",
"codeclimate-test-reporter": "^0.5.0",
"coveralls": "^3.0.5",
"mocha": "^6.1.4",
"nyc": "^14.1.1",
"ts-node": "^8.3.0",
"tslint": "^5.18.0",
"typescript": "^3.5.3"
"@types/node": "^12.12.25",
"codeclimate-test-reporter": "^0.5.1",
"coveralls": "^3.0.9",
"mocha": "^7.0.0",
"nyc": "^15.0.0",
"ts-node": "^8.6.2",
"tslint": "^5.20.1",
"typescript": "^3.7.5"
}
}

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

```js
Promise.resolve()
.then(() => csvWriter.writeRecords(records1))
.then(() => csvWriter.writeRecords(records2))
...
// In an `async` function
await csvWriter.writeRecords(records1)
await csvWriter.writeRecords(records2)
...
```

@@ -146,2 +146,6 @@

* headerIdDelimiter `<string>` (optional)
Default: `undefined`. Give this value to specify a path to a value in a nested object.
* alwaysQuote `<boolean>` (optional)

@@ -238,3 +242,7 @@

Default: `\n`. Only either LF (`\n`) or CRLF (`\r\n`) is allowed.
* headerIdDelimiter `<string>` (optional)
Default: `undefined`. Give this value to specify a path to a value in a nested object.
* alwaysQuote `<boolean>` (optional)

@@ -241,0 +249,0 @@

@@ -17,2 +17,3 @@ import {ArrayCsvStringifier} from './csv-stringifiers/array';

recordDelimiter?: string;
headerIdDelimiter?: string;
alwaysQuote?: boolean;

@@ -30,5 +31,5 @@ }

const fieldStringifier = createFieldStringifier(params.fieldDelimiter, params.alwaysQuote);
return new ObjectCsvStringifier(fieldStringifier, params.header, params.recordDelimiter);
return new ObjectCsvStringifier(fieldStringifier, params.header, params.recordDelimiter, params.headerIdDelimiter);
}
}

@@ -8,11 +8,6 @@ import {FieldStringifier} from '../field-stringifier';

export abstract class CsvStringifier<T> {
private readonly fieldStringifier: FieldStringifier;
private readonly fieldDelimiter: string;
private readonly recordDelimiter: string;
constructor(fieldStringifier: FieldStringifier, recordDelimiter?: string) {
this.fieldStringifier = fieldStringifier;
this.fieldDelimiter = fieldStringifier.fieldDelimiter;
this.recordDelimiter = recordDelimiter || DEFAULT_RECORD_DELIMITER;
_validateRecordDelimiter(this.recordDelimiter);
constructor(private readonly fieldStringifier: FieldStringifier,
private readonly recordDelimiter = DEFAULT_RECORD_DELIMITER) {
_validateRecordDelimiter(recordDelimiter);
}

@@ -22,3 +17,3 @@

const headerRecord = this.getHeaderRecord();
return headerRecord ? this.stringifyRecords([headerRecord]) : null;
return headerRecord ? this.joinRecords([this.getCsvLine(headerRecord)]) : null;
}

@@ -28,3 +23,3 @@

const csvLines = Array.from(records, record => this.getCsvLine(this.getRecordAsArray(record)));
return csvLines.join(this.recordDelimiter) + this.recordDelimiter;
return this.joinRecords(csvLines);
}

@@ -34,3 +29,3 @@

protected abstract getHeaderRecord(): T | null | undefined;
protected abstract getHeaderRecord(): string[] | null | undefined;

@@ -40,4 +35,8 @@ private getCsvLine(record: Field[]): string {

.map(fieldValue => this.fieldStringifier.stringify(fieldValue))
.join(this.fieldDelimiter);
.join(this.fieldStringifier.fieldDelimiter);
}
private joinRecords(records: string[]) {
return records.join(this.recordDelimiter) + this.recordDelimiter;
}
}

@@ -44,0 +43,0 @@

@@ -6,7 +6,7 @@ import {CsvStringifier} from './abstract';

export class ArrayCsvStringifier extends CsvStringifier<Field[]> {
private readonly header?: string[];
constructor(fieldStringifier: FieldStringifier, recordDelimiter?: string, header?: string[]) {
constructor(fieldStringifier: FieldStringifier,
recordDelimiter?: string,
private readonly header?: string[]) {
super(fieldStringifier, recordDelimiter);
this.header = header;
}

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

import {CsvStringifier} from './abstract';
import {FieldStringifier} from '../field-stringifier';
import {Field, ObjectHeaderItem, ObjectStringifierHeader} from '../record';
import {ObjectMap} from '../lang';
import {isObject, ObjectMap} from '../lang/object';
export class ObjectCsvStringifier extends CsvStringifier<ObjectMap<Field>> {
private readonly header: ObjectStringifierHeader;
constructor(fieldStringifier: FieldStringifier, header: ObjectStringifierHeader, recordDelimiter?: string) {
constructor(fieldStringifier: FieldStringifier,
private readonly header: ObjectStringifierHeader,
recordDelimiter?: string,
private readonly headerIdDelimiter?: string) {
super(fieldStringifier, recordDelimiter);
this.header = header;
}
protected getHeaderRecord(): ObjectMap<Field> | null {
protected getHeaderRecord(): string[] | null {
if (!this.isObjectHeader) return null;
return (this.header as ObjectHeaderItem[]).map(field => field.title);
}
return (this.header as ObjectHeaderItem[]).reduce((memo, field) =>
Object.assign({}, memo, {[field.id]: field.title}), {});
protected getRecordAsArray(record: ObjectMap<Field>): Field[] {
return this.fieldIds.map(fieldId => this.getNestedValue(record, fieldId));
}
protected getRecordAsArray(record: ObjectMap<Field>): string[] {
return this.fieldIds.map(field => record[field]);
private getNestedValue(obj: ObjectMap<Field>, key: string) {
if (!this.headerIdDelimiter) return obj[key];
return key.split(this.headerIdDelimiter).reduce((subObj, keyPart) => (subObj || {})[keyPart], obj);
}

@@ -33,5 +37,1 @@

}
function isObject(value: any): boolean {
return Object.prototype.toString.call(value) === '[object Object]';
}

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

recordDelimiter?: string;
headerIdDelimiter?: string;
alwaysQuote?: boolean;

@@ -27,8 +28,4 @@ encoding?: string;

export class CsvWriterFactory {
private readonly csvStringifierFactory: CsvStringifierFactory;
constructor(private readonly csvStringifierFactory: CsvStringifierFactory) {}
constructor(csvStringifierFactory: CsvStringifierFactory) {
this.csvStringifierFactory = csvStringifierFactory;
}
createArrayCsvWriter(params: ArrayCsvWriterParams) {

@@ -49,2 +46,3 @@ const csvStringifier = this.csvStringifierFactory.createArrayCsvStringifier({

recordDelimiter: params.recordDelimiter,
headerIdDelimiter: params.headerIdDelimiter,
alwaysQuote: params.alwaysQuote

@@ -51,0 +49,0 @@ });

@@ -7,10 +7,9 @@ import {CsvStringifier} from './csv-stringifiers/abstract';

export class CsvWriter<T> {
private readonly csvStringifier: CsvStringifier<T>;
private readonly fileWriter: FileWriter;
private append: boolean;
constructor(csvStringifier: CsvStringifier<T>, path: string, encoding?: string, append?: boolean) {
this.append = append || DEFAULT_INITIAL_APPEND_FLAG;
constructor(private readonly csvStringifier: CsvStringifier<T>,
path: string,
encoding?: string,
private append = DEFAULT_INITIAL_APPEND_FLAG) {
this.fileWriter = new FileWriter(path, this.append, encoding);
this.csvStringifier = csvStringifier;
}

@@ -17,0 +16,0 @@

@@ -7,12 +7,4 @@ import {Field} from './record';

export abstract class FieldStringifier {
private readonly _fieldDelimiter: string;
constructor(public readonly fieldDelimiter: string) {}
constructor(fieldDelimiter: string) {
this._fieldDelimiter = fieldDelimiter;
}
get fieldDelimiter(): string {
return this._fieldDelimiter;
}
abstract stringify(value?: Field): string;

@@ -19,0 +11,0 @@

@@ -9,10 +9,6 @@ import {promisify} from './lang/promise';

export class FileWriter {
private readonly path: string;
private readonly encoding: string;
private append: boolean;
constructor(path: string, append: boolean, encoding?: string) {
this.path = path;
this.append = append;
this.encoding = encoding || DEFAULT_ENCODING;
constructor(private readonly path: string,
private append: boolean,
private readonly encoding = DEFAULT_ENCODING) {
}

@@ -19,0 +15,0 @@

@@ -8,3 +8,3 @@ import {resolveDelimiterChar} from '../helper/delimiter';

{FIELD_A: 'VALUE_A1', FIELD_B: 'VALUE_B1'},
{FIELD_A: 'VALUE_A2', FIELD_B: 'VALUE_B2'}
{FIELD_A: 'VALUE_A2', FIELD_B: 'VALUE_B2', OTHERS: {FIELD_C: 'VALUE_C2'}}
];

@@ -73,2 +73,20 @@

describe('When `headerIdDelimiter` is set', () => {
const stringifier = createObjectCsvStringifier({
header: [
{id: 'FIELD_A', title: 'TITLE_A'},
{id: 'OTHERS/FIELD_C', title: 'TITLE_C'}
],
headerIdDelimiter: '/'
});
it('uses the title as is', () => {
strictEqual(stringifier.getHeaderString(), 'TITLE_A,TITLE_C\n');
});
it('picks up a value in nested objects', () => {
strictEqual(stringifier.stringifyRecords(records), 'VALUE_A1,\nVALUE_A2,VALUE_C2\n');
});
});
function generateTestCases(fieldDelimiter?: string) {

@@ -75,0 +93,0 @@ const delim = resolveDelimiterChar(fieldDelimiter);

@@ -1,21 +0,16 @@

import {ok, strictEqual} from 'assert';
import {strictEqual} from 'assert';
import {readFileSync} from 'fs';
const fs = require('fs');
export const testFilePath = (id: string) => `./test-tmp/${id}.csv`;
export const assertFile = (path: string, expectedContents: string, encoding?: string) => {
const actualContents = fs.readFileSync(path, encoding || 'utf8');
const actualContents = readFileSync(path, encoding || 'utf8');
strictEqual(actualContents, expectedContents);
};
export const assertContain = (expectedSubstring: string, actualString: string) => {
ok(
expectedSubstring.includes(actualString),
`${actualString} does not contain ${expectedSubstring}`
export const assertRejected = (p: Promise<any>, message: string) => {
return p.then(
() => new Error('Should not have been called'),
(e: Error) => { strictEqual(e.message, message); }
);
};
export function mockType<T>(params?: any): T {
return Object.assign({} as T, params);
}
import {promisify} from '../../lib/lang/promise';
import {strictEqual} from 'assert';
import {assertRejected} from '../helper';

@@ -11,15 +12,11 @@ describe('Promise', () => {

};
const promisifiedFn = promisify(greetAsync);
it('promisify node style callback', async () => {
const promisifiedFn = promisify(greetAsync);
strictEqual(await promisifiedFn('foo'), 'Hello, foo!');
});
it('raise an error for error', () => {
const promisifiedFn = promisify(greetAsync);
return promisifiedFn('bar').then(
() => new Error('Should not have been called'),
(e: Error) => { strictEqual(e.message, "We don't know bar"); }
);
it('raise an error for error', async () => {
await assertRejected(promisifiedFn('bar'), "We don't know bar");
});
});
import {assertFile, testFilePath} from './helper';
import {CsvWriter} from '../lib/csv-writer';
import {writeFileSync} from 'fs';
import {createArrayCsvWriter} from '../index';
const fs = require('fs');
const createArrayCsvWriter = require('../index').createArrayCsvWriter;
describe('Write array records into CSV', () => {

@@ -16,4 +15,2 @@

describe('When only path is specified', () => {
'use strict';
const filePath = makeFilePath('minimum');

@@ -26,6 +23,5 @@ let writer: CsvWriter<string[]>;

it('writes records to a new file', () => {
return writer.writeRecords(records).then(() => {
assertFile(filePath, 'Bob,French\nMary,English\n');
});
it('writes records to a new file', async () => {
await writer.writeRecords(records);
assertFile(filePath, 'Bob,French\nMary,English\n');
});

@@ -51,6 +47,5 @@

it('writes a header', () => {
return writer.writeRecords(records).then(() => {
assertFile(filePath, 'NAME,LANGUAGE\nBob,French\nMary,English\n');
});
it('writes a header', async () => {
await writer.writeRecords(records);
assertFile(filePath, 'NAME,LANGUAGE\nBob,French\nMary,English\n');
});

@@ -67,3 +62,3 @@

const filePath = makeFilePath('append');
fs.writeFileSync(filePath, 'Mike,German\n', 'utf8');
writeFileSync(filePath, 'Mike,German\n', 'utf8');
const writer = createArrayCsvWriter({

@@ -74,6 +69,5 @@ path: filePath,

it('do not overwrite the existing contents and appends records to them', () => {
return writer.writeRecords([records[1]]).then(() => {
assertFile(filePath, 'Mike,German\nMary,English\n');
});
it('do not overwrite the existing contents and appends records to them', async () => {
await writer.writeRecords([records[1]]);
assertFile(filePath, 'Mike,German\nMary,English\n');
});

@@ -89,6 +83,5 @@ });

it('writes to a file with the specified encoding', () => {
return writer.writeRecords(records).then(() => {
assertFile(filePath, 'Bob,French\nMary,English\n', 'utf16le');
});
it('writes to a file with the specified encoding', async () => {
await writer.writeRecords(records);
assertFile(filePath, 'Bob,French\nMary,English\n', 'utf16le');
});

@@ -105,6 +98,5 @@ });

it('uses semicolon instead of comma to separate fields', () => {
return writer.writeRecords(records).then(() => {
assertFile(filePath, 'NAME;LANGUAGE\nBob;French\nMary;English\n');
});
it('uses semicolon instead of comma to separate fields', async () => {
await writer.writeRecords(records);
assertFile(filePath, 'NAME;LANGUAGE\nBob;French\nMary;English\n');
});

@@ -120,6 +112,5 @@ });

it('writes to a file with the specified newline character', () => {
return writer.writeRecords(records).then(() => {
assertFile(filePath, 'Bob,French\r\nMary,English\r\n');
});
it('writes to a file with the specified newline character', async () => {
await writer.writeRecords(records);
assertFile(filePath, 'Bob,French\r\nMary,English\r\n');
});

@@ -126,0 +117,0 @@ });

import {assertFile, testFilePath} from './helper';
import {CsvWriter} from '../lib/csv-writer';
import {writeFileSync} from 'fs';
import {createObjectCsvWriter} from '../index';
import {ObjectMap} from '../lib/lang/object';
const fs = require('fs');
const createObjectCsvWriter = require('../index').createObjectCsvWriter;
describe('Write object records into CSV', () => {

@@ -11,3 +11,3 @@

const records = [
{name: 'Bob', lang: 'French'},
{name: 'Bob', lang: 'French', address: {country: 'France'}},
{name: 'Mary', lang: 'English'}

@@ -17,6 +17,4 @@ ];

describe('When only path and header ids are given', () => {
'use strict';
const filePath = makeFilePath('minimum');
let writer: CsvWriter<{[k: string]: string}>;
let writer: CsvWriter<ObjectMap<any>>;

@@ -30,6 +28,5 @@ beforeEach(() => {

it('writes records to a new file', () => {
return writer.writeRecords(records).then(() => {
assertFile(filePath, 'Bob,French\nMary,English\n');
});
it('writes records to a new file', async () => {
await writer.writeRecords(records);
assertFile(filePath, 'Bob,French\nMary,English\n');
});

@@ -51,6 +48,5 @@

it('also writes columns with reverse order', () => {
return writer.writeRecords(records).then(() => {
assertFile(filePath, 'French,Bob\nEnglish,Mary\n');
});
it('also writes columns with reverse order', async () => {
await writer.writeRecords(records);
assertFile(filePath, 'French,Bob\nEnglish,Mary\n');
});

@@ -61,3 +57,3 @@ });

const filePath = makeFilePath('header');
let writer: CsvWriter<{[k: string]: string}>;
let writer: CsvWriter<ObjectMap<any>>;

@@ -71,6 +67,5 @@ beforeEach(() => {

it('writes a header', () => {
return writer.writeRecords(records).then(() => {
assertFile(filePath, 'NAME,LANGUAGE\nBob,French\nMary,English\n');
});
it('writes a header', async () => {
await writer.writeRecords(records);
assertFile(filePath, 'NAME,LANGUAGE\nBob,French\nMary,English\n');
});

@@ -87,3 +82,3 @@

const filePath = makeFilePath('append');
fs.writeFileSync(filePath, 'Mike,German\n', 'utf8');
writeFileSync(filePath, 'Mike,German\n', 'utf8');
const writer = createObjectCsvWriter({

@@ -95,6 +90,5 @@ path: filePath,

it('do not overwrite the existing contents and appends records to them', () => {
return writer.writeRecords([records[1]]).then(() => {
assertFile(filePath, 'Mike,German\nMary,English\n');
});
it('do not overwrite the existing contents and appends records to them', async () => {
await writer.writeRecords([records[1]]);
assertFile(filePath, 'Mike,German\nMary,English\n');
});

@@ -111,6 +105,5 @@ });

it('writes to a file with the specified encoding', () => {
return writer.writeRecords(records).then(() => {
assertFile(filePath, 'Bob,French\nMary,English\n', 'utf16le');
});
it('writes to a file with the specified encoding', async () => {
await writer.writeRecords(records);
assertFile(filePath, 'Bob,French\nMary,English\n', 'utf16le');
});

@@ -127,6 +120,5 @@ });

it('uses semicolon instead of comma to separate fields', () => {
return writer.writeRecords(records).then(() => {
assertFile(filePath, 'NAME;LANGUAGE\nBob;French\nMary;English\n');
});
it('uses semicolon instead of comma to separate fields', async () => {
await writer.writeRecords(records);
assertFile(filePath, 'NAME;LANGUAGE\nBob;French\nMary;English\n');
});

@@ -143,6 +135,5 @@ });

it('writes to a file with the specified newline character', () => {
return writer.writeRecords(records).then(() => {
assertFile(filePath, 'Bob,French\r\nMary,English\r\n');
});
it('writes to a file with the specified newline character', async () => {
await writer.writeRecords(records);
assertFile(filePath, 'Bob,French\r\nMary,English\r\n');
});

@@ -164,2 +155,16 @@ });

});
describe('When `headerIdDelimiter` flag is set', () => {
const filePath = makeFilePath('nested');
const writer = createObjectCsvWriter({
path: filePath,
header: [{id: 'name', title: 'NAME'}, {id: 'address.country', title: 'COUNTRY'}],
headerIdDelimiter: '.'
});
it('breaks keys into key paths', async () => {
await writer.writeRecords(records);
assertFile(filePath, 'NAME,COUNTRY\nBob,France\nMary,\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

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc