Socket
Socket
Sign inDemoInstall

csv42

Package Overview
Dependencies
0
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.0.0 to 2.0.0

12

lib/cjs/csv2json.js

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

(_fields$index = fields[index]) === null || _fields$index === void 0 ? void 0 : _fields$index.setValue(object, value);
});
}, parse);
json.push(object);

@@ -36,3 +36,3 @@ };

names.push(withHeader ? String(fieldName) : "Field ".concat(index));
});
}, _value.unescapeValue);
if (!withHeader) {

@@ -44,6 +44,6 @@ i = 0; // reset the pointer again: the first line contains data, not a header

}
function parseRecord(onField) {
function parseRecord(onField, parse) {
var index = 0;
while (i < csv.length && !(0, _validate.isEol)(csv, i)) {
onField(parseField(), index);
onField(parseField(parse), index);
index++;

@@ -56,3 +56,3 @@ if (csv.charCodeAt(i) === delimiter) {

}
function parseField() {
function parseField(parse) {
var start = i;

@@ -63,3 +63,3 @@ if (csv.charCodeAt(i) === quote) {

i++;
if (csv.charCodeAt(i) === quote && csv.charCodeAt(i + 1) === quote) {
while (csv.charCodeAt(i) === quote && csv.charCodeAt(i + 1) === quote) {
// skip over escaped quote (two quotes)

@@ -66,0 +66,0 @@ i += 2;

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

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
function collectFields(records, flatten) {
return collectNestedPaths(records, flatten).map(function (path) {
function collectFields(records, flatten, flattenArray) {
return collectNestedPaths(records, flatten, flattenArray).map(function (path) {
return {

@@ -27,6 +27,9 @@ name: (0, _path.stringifyPath)(path),

var path = (0, _path.parsePath)(name);
var first = path[0];
return {
name: name,
setValue: path.length === 1 || !nested ? function (record, value) {
setValue: path.length === 0 || !nested ? function (record, value) {
return record[name] = value;
} : path.length === 1 ? function (record, value) {
return record[first] = value;
} : function (record, value) {

@@ -73,36 +76,56 @@ return (0, _object.setIn)(record, path, value);

}
function collectNestedPaths(records, flatten) {
var leaf = Symbol();
function collectNestedPaths(array, flatten, flattenArray) {
var recurse = flatten ? flattenArray ? _object.isObjectOrArray : _object.isObject : function () {
return false;
};
var merged = {};
function mergeRecord(object, merged) {
for (var key in object) {
var value = object[key];
if (flatten(value)) {
if (merged[key] === undefined) {
merged[key] = Array.isArray(object[key]) ? [] : {};
}
mergeRecord(value, merged[key]);
} else {
if (merged[key] === undefined) {
merged[key] = true;
}
}
array.forEach(function (item) {
if ((0, _object.isObjectOrArray)(item)) {
_mergeObject(item, merged, recurse);
} else {
_mergeValue(item, merged);
}
}
records.forEach(function (record) {
return mergeRecord(record, merged);
});
var paths = [];
function collectPaths(object, parentPath) {
_collectPaths(merged, [], paths);
return paths;
}
// internal function for collectNestedPaths
// mutates the argument `merged`
function _mergeObject(object, merged, recurse) {
for (var key in object) {
var _value = object[key];
var valueMerged = merged[key] || (merged[key] = Array.isArray(_value) ? [] : {});
if (recurse(_value)) {
_mergeObject(_value, valueMerged, recurse);
} else {
_mergeValue(_value, valueMerged);
}
}
}
// internal function for collectNestedPaths
// mutates the argument `merged`
function _mergeValue(value, merged) {
if (merged[leaf] === undefined) {
merged[leaf] = value === null || value === undefined ? null : true;
}
}
// internal function for collectNestedPaths
// mutates the argument `paths`
function _collectPaths(object, parentPath, paths) {
if (object[leaf] === true || object[leaf] === null && isEmpty(object)) {
paths.push(parentPath);
} else if (Array.isArray(object)) {
object.forEach(function (item, index) {
return _collectPaths(item, parentPath.concat(index), paths);
});
} else if ((0, _object.isObjectOrArray)(object)) {
for (var key in object) {
var path = parentPath.concat(Array.isArray(object) ? parseInt(key) : key);
var value = object[key];
if (flatten(value)) {
collectPaths(value, path);
} else {
paths.push(path);
}
_collectPaths(object[key], parentPath.concat(key), paths);
}
}
collectPaths(merged, []);
return paths;
}

@@ -125,2 +148,5 @@ function createGetValue(path) {

}
function isEmpty(object) {
return Object.keys(object).length === 0;
}
//# sourceMappingURL=fields.js.map

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

parseValue: true,
unescapeValue: true,
collectNestedPaths: true,

@@ -72,2 +73,8 @@ parsePath: true,

});
Object.defineProperty(exports, "unescapeValue", {
enumerable: true,
get: function get() {
return _value.unescapeValue;
}
});
var _json2csv = require("./json2csv.js");

@@ -74,0 +81,0 @@ var _csv2json = require("./csv2json.js");

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

var _validate = require("./validate.js");
var _object = require("./object.js");
function json2csv(json, options) {

@@ -16,6 +15,3 @@ var header = (options === null || options === void 0 ? void 0 : options.header) !== false; // true when not specified

var eol = (0, _validate.validateEOL)((options === null || options === void 0 ? void 0 : options.eol) || '\r\n');
var flatten = typeof (options === null || options === void 0 ? void 0 : options.flatten) === 'function' ? options === null || options === void 0 ? void 0 : options.flatten : (options === null || options === void 0 ? void 0 : options.flatten) === false ? function () {
return false;
} : _object.isObjectOrArray; // options?.flatten is true or undefined
var fields = options !== null && options !== void 0 && options.fields ? Array.isArray(options === null || options === void 0 ? void 0 : options.fields) ? options === null || options === void 0 ? void 0 : options.fields : options === null || options === void 0 ? void 0 : options.fields(json) : (0, _fields.collectFields)(json, flatten);
var fields = options !== null && options !== void 0 && options.fields ? Array.isArray(options === null || options === void 0 ? void 0 : options.fields) ? options === null || options === void 0 ? void 0 : options.fields : options === null || options === void 0 ? void 0 : options.fields(json) : (0, _fields.collectFields)(json, (options === null || options === void 0 ? void 0 : options.flatten) !== false, (options === null || options === void 0 ? void 0 : options.flattenArray) === true);
var formatValue = (options === null || options === void 0 ? void 0 : options.formatValue) || (0, _value.createFormatValue)(delimiter);

@@ -22,0 +18,0 @@ var output = '';

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

exports.getIn = getIn;
exports.isObject = isObject;
exports.isObjectOrArray = isObjectOrArray;

@@ -15,3 +16,4 @@ exports.setIn = setIn;

while (i < path.length && value !== undefined) {
value = value[path[i]];
var _value;
value = (_value = value) === null || _value === void 0 ? void 0 : _value[path[i]];
i++;

@@ -41,4 +43,7 @@ }

function isObjectOrArray(value) {
return value !== null && _typeof(value) === 'object';
return _typeof(value) === 'object' && value !== null;
}
function isObject(value) {
return _typeof(value) === 'object' && value !== null && value.constructor === Object; // do not match on classes or Array
}
//# sourceMappingURL=object.js.map

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

return path.map(function (p, index) {
return typeof p === 'number' ? '[' + p + ']' : /[.\[\]]/.test(p) // match any character . or [ or ]
return typeof p === 'number' ? '[' + p + ']' : /[.\[\]]/.test(p) || p === '' // match any character . or [ or ] and handle an empty string
? '["' + p + '"]' : (index > 0 ? '.' : '') + p;

@@ -17,0 +17,0 @@ }).join('');

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

exports.parseValue = parseValue;
exports.unescapeValue = unescapeValue;
function createFormatValue(delimiter) {

@@ -33,8 +34,10 @@ // match at least one occurrence of a control character in a string:

function parseValue(value) {
if (value[0] === '"') {
var unescapedValue = value.substring(1, value.length - 1).replaceAll('""', '"');
return unescapedValue === '' ? unescapedValue : parseUnescapedValue(unescapedValue);
if (value === '') {
return null;
}
return parseUnescapedValue(value);
return parseUnescapedValue(unescapeValue(value));
}
function unescapeValue(value) {
return value[0] === '"' ? value.substring(1, value.length - 1).replaceAll('""', '"') : value;
}
function parseUnescapedValue(value) {

@@ -51,3 +54,3 @@ var number = Number(value);

}
if (value === 'null' || value === '') {
if (value === 'null') {
return null;

@@ -54,0 +57,0 @@ }

@@ -1,3 +0,3 @@

import { parseValue } from './value.js';
import { toFields, mapFields } from './fields.js';
import { parseValue, unescapeValue } from './value.js';
import { mapFields, toFields } from './fields.js';
import { isCRLF, isEol, isLF, validateDelimiter } from './validate.js';

@@ -17,3 +17,3 @@ export function csv2json(csv, options) {

fields[index]?.setValue(object, value);
});
}, parse);
json.push(object);

@@ -26,3 +26,3 @@ }

names.push(withHeader ? String(fieldName) : `Field ${index}`);
});
}, unescapeValue);
if (!withHeader) {

@@ -34,6 +34,6 @@ i = 0; // reset the pointer again: the first line contains data, not a header

}
function parseRecord(onField) {
function parseRecord(onField, parse) {
let index = 0;
while (i < csv.length && !isEol(csv, i)) {
onField(parseField(), index);
onField(parseField(parse), index);
index++;

@@ -46,3 +46,3 @@ if (csv.charCodeAt(i) === delimiter) {

}
function parseField() {
function parseField(parse) {
const start = i;

@@ -53,3 +53,3 @@ if (csv.charCodeAt(i) === quote) {

i++;
if (csv.charCodeAt(i) === quote && csv.charCodeAt(i + 1) === quote) {
while (csv.charCodeAt(i) === quote && csv.charCodeAt(i + 1) === quote) {
// skip over escaped quote (two quotes)

@@ -56,0 +56,0 @@ i += 2;

@@ -1,5 +0,5 @@

import { getIn, setIn } from './object.js';
import { getIn, isObject, isObjectOrArray, setIn } from './object.js';
import { parsePath, stringifyPath } from './path.js';
export function collectFields(records, flatten) {
return collectNestedPaths(records, flatten).map(path => ({
export function collectFields(records, flatten, flattenArray) {
return collectNestedPaths(records, flatten, flattenArray).map(path => ({
name: stringifyPath(path),

@@ -12,5 +12,6 @@ getValue: createGetValue(path)

const path = parsePath(name);
const first = path[0];
return {
name,
setValue: path.length === 1 || !nested ? (record, value) => record[name] = value : (record, value) => setIn(record, path, value)
setValue: path.length === 0 || !nested ? (record, value) => record[name] = value : path.length === 1 ? (record, value) => record[first] = value : (record, value) => setIn(record, path, value)
};

@@ -45,34 +46,52 @@ });

}
export function collectNestedPaths(records, flatten) {
const leaf = Symbol();
export function collectNestedPaths(array, flatten, flattenArray) {
const recurse = flatten ? flattenArray ? isObjectOrArray : isObject : () => false;
const merged = {};
function mergeRecord(object, merged) {
for (const key in object) {
const value = object[key];
if (flatten(value)) {
if (merged[key] === undefined) {
merged[key] = Array.isArray(object[key]) ? [] : {};
}
mergeRecord(value, merged[key]);
} else {
if (merged[key] === undefined) {
merged[key] = true;
}
}
array.forEach(item => {
if (isObjectOrArray(item)) {
_mergeObject(item, merged, recurse);
} else {
_mergeValue(item, merged);
}
});
const paths = [];
_collectPaths(merged, [], paths);
return paths;
}
// internal function for collectNestedPaths
// mutates the argument `merged`
function _mergeObject(object, merged, recurse) {
for (const key in object) {
const value = object[key];
const valueMerged = merged[key] || (merged[key] = Array.isArray(value) ? [] : {});
if (recurse(value)) {
_mergeObject(value, valueMerged, recurse);
} else {
_mergeValue(value, valueMerged);
}
}
records.forEach(record => mergeRecord(record, merged));
const paths = [];
function collectPaths(object, parentPath) {
}
// internal function for collectNestedPaths
// mutates the argument `merged`
function _mergeValue(value, merged) {
if (merged[leaf] === undefined) {
merged[leaf] = value === null || value === undefined ? null : true;
}
}
// internal function for collectNestedPaths
// mutates the argument `paths`
function _collectPaths(object, parentPath, paths) {
if (object[leaf] === true || object[leaf] === null && isEmpty(object)) {
paths.push(parentPath);
} else if (Array.isArray(object)) {
object.forEach((item, index) => _collectPaths(item, parentPath.concat(index), paths));
} else if (isObjectOrArray(object)) {
for (const key in object) {
const path = parentPath.concat(Array.isArray(object) ? parseInt(key) : key);
const value = object[key];
if (flatten(value)) {
collectPaths(value, path);
} else {
paths.push(path);
}
_collectPaths(object[key], parentPath.concat(key), paths);
}
}
collectPaths(merged, []);
return paths;
}

@@ -91,2 +110,5 @@ function createGetValue(path) {

}
function isEmpty(object) {
return Object.keys(object).length === 0;
}
//# sourceMappingURL=fields.js.map
export { json2csv } from './json2csv.js';
export { csv2json } from './csv2json.js';
export { createFormatValue, parseValue } from './value.js';
export { createFormatValue, parseValue, unescapeValue } from './value.js';
export { collectNestedPaths } from './fields.js';

@@ -5,0 +5,0 @@ export { parsePath, stringifyPath } from './path.js';

import { collectFields } from './fields.js';
import { createFormatValue } from './value.js';
import { validateDelimiter, validateEOL } from './validate.js';
import { isObjectOrArray } from './object.js';
export function json2csv(json, options) {

@@ -9,4 +8,3 @@ const header = options?.header !== false; // true when not specified

const eol = validateEOL(options?.eol || '\r\n');
const flatten = typeof options?.flatten === 'function' ? options?.flatten : options?.flatten === false ? () => false : isObjectOrArray; // options?.flatten is true or undefined
const fields = options?.fields ? Array.isArray(options?.fields) ? options?.fields : options?.fields(json) : collectFields(json, flatten);
const fields = options?.fields ? Array.isArray(options?.fields) ? options?.fields : options?.fields(json) : collectFields(json, options?.flatten !== false, options?.flattenArray === true);
const formatValue = options?.formatValue || createFormatValue(delimiter);

@@ -13,0 +11,0 @@ let output = '';

@@ -5,3 +5,3 @@ export function getIn(object, path) {

while (i < path.length && value !== undefined) {
value = value[path[i]];
value = value?.[path[i]];
i++;

@@ -31,4 +31,7 @@ }

export function isObjectOrArray(value) {
return value !== null && typeof value === 'object';
return typeof value === 'object' && value !== null;
}
export function isObject(value) {
return typeof value === 'object' && value !== null && value.constructor === Object; // do not match on classes or Array
}
//# sourceMappingURL=object.js.map

@@ -7,3 +7,3 @@ /**

return path.map((p, index) => {
return typeof p === 'number' ? '[' + p + ']' : /[.\[\]]/.test(p) // match any character . or [ or ]
return typeof p === 'number' ? '[' + p + ']' : /[.\[\]]/.test(p) || p === '' // match any character . or [ or ] and handle an empty string
? '["' + p + '"]' : (index > 0 ? '.' : '') + p;

@@ -10,0 +10,0 @@ }).join('');

@@ -25,8 +25,10 @@ export function createFormatValue(delimiter) {

export function parseValue(value) {
if (value[0] === '"') {
const unescapedValue = value.substring(1, value.length - 1).replaceAll('""', '"');
return unescapedValue === '' ? unescapedValue : parseUnescapedValue(unescapedValue);
if (value === '') {
return null;
}
return parseUnescapedValue(value);
return parseUnescapedValue(unescapeValue(value));
}
export function unescapeValue(value) {
return value[0] === '"' ? value.substring(1, value.length - 1).replaceAll('""', '"') : value;
}
function parseUnescapedValue(value) {

@@ -43,3 +45,3 @@ const number = Number(value);

}
if (value === 'null' || value === '') {
if (value === 'null') {
return null;

@@ -46,0 +48,0 @@ }

@@ -1,3 +0,3 @@

import { CsvField, FlattenValue, JsonField, NestedObject, Path } from './types.js';
export declare function collectFields(records: NestedObject[], flatten: FlattenValue): CsvField[];
import { CsvField, JsonField, NestedObject, Path } from './types.js';
export declare function collectFields(records: NestedObject[], flatten: boolean, flattenArray: boolean): CsvField[];
export declare function toFields(names: string[], nested: boolean): JsonField[];

@@ -12,3 +12,3 @@ /**

export declare function mapFields(fieldNames: string[], fields: JsonField[]): (JsonField | undefined)[];
export declare function collectNestedPaths(records: NestedObject[], flatten: FlattenValue): Path[];
export declare function collectNestedPaths(array: NestedObject[], flatten: boolean, flattenArray: boolean): Path[];
//# sourceMappingURL=fields.d.ts.map
export { json2csv } from './json2csv.js';
export { csv2json } from './csv2json.js';
export { createFormatValue, parseValue } from './value.js';
export { createFormatValue, parseValue, unescapeValue } from './value.js';
export { collectNestedPaths } from './fields.js';

@@ -5,0 +5,0 @@ export { parsePath, stringifyPath } from './path.js';

import { NestedObject, Path } from './types';
export declare function getIn(object: NestedObject, path: Path): unknown;
export declare function setIn(object: NestedObject, path: Path, value: unknown): NestedObject;
export declare function isObjectOrArray(value: unknown): value is NestedObject;
export declare function isObjectOrArray(value: unknown): boolean;
export declare function isObject(value: unknown): boolean;
//# sourceMappingURL=object.d.ts.map
export type Path = (string | number)[];
export type NestedObject = {
[key: string]: NestedObject | unknown;
};
export type NestedObject = Record<string, NestedObject>;
export type ValueGetter = (object: NestedObject) => unknown;

@@ -9,3 +7,2 @@ export type ValueSetter = (object: NestedObject, value: unknown) => void;

export type ValueParser = (value: string) => unknown;
export type FlattenValue = (value: unknown) => boolean;
export interface CsvField {

@@ -30,3 +27,4 @@ name: string;

eol?: '\r\n' | '\n';
flatten?: boolean | FlattenValue;
flatten?: boolean;
flattenArray?: boolean;
fields?: CsvField[] | CsvFieldsParser;

@@ -33,0 +31,0 @@ formatValue?: ValueFormatter;

import { ValueFormatter } from './types';
export declare function createFormatValue(delimiter: string): ValueFormatter;
export declare function parseValue(value: string): unknown;
export declare function unescapeValue(value: string): string;
//# sourceMappingURL=value.d.ts.map

@@ -11,3 +11,3 @@ (function (global, factory) {

while (i < path.length && value !== undefined) {
value = value[path[i]];
value = value?.[path[i]];
i++;

@@ -37,4 +37,7 @@ }

function isObjectOrArray(value) {
return value !== null && typeof value === 'object';
return typeof value === 'object' && value !== null;
}
function isObject(value) {
return typeof value === 'object' && value !== null && value.constructor === Object; // do not match on classes or Array
}

@@ -47,3 +50,3 @@ /**

return path.map((p, index) => {
return typeof p === 'number' ? '[' + p + ']' : /[.\[\]]/.test(p) // match any character . or [ or ]
return typeof p === 'number' ? '[' + p + ']' : /[.\[\]]/.test(p) || p === '' // match any character . or [ or ] and handle an empty string
? '["' + p + '"]' : (index > 0 ? '.' : '') + p;

@@ -95,4 +98,4 @@ }).join('');

function collectFields(records, flatten) {
return collectNestedPaths(records, flatten).map(path => ({
function collectFields(records, flatten, flattenArray) {
return collectNestedPaths(records, flatten, flattenArray).map(path => ({
name: stringifyPath(path),

@@ -105,5 +108,6 @@ getValue: createGetValue(path)

const path = parsePath(name);
const first = path[0];
return {
name,
setValue: path.length === 1 || !nested ? (record, value) => record[name] = value : (record, value) => setIn(record, path, value)
setValue: path.length === 0 || !nested ? (record, value) => record[name] = value : path.length === 1 ? (record, value) => record[first] = value : (record, value) => setIn(record, path, value)
};

@@ -138,34 +142,52 @@ });

}
function collectNestedPaths(records, flatten) {
const leaf = Symbol();
function collectNestedPaths(array, flatten, flattenArray) {
const recurse = flatten ? flattenArray ? isObjectOrArray : isObject : () => false;
const merged = {};
function mergeRecord(object, merged) {
for (const key in object) {
const value = object[key];
if (flatten(value)) {
if (merged[key] === undefined) {
merged[key] = Array.isArray(object[key]) ? [] : {};
}
mergeRecord(value, merged[key]);
} else {
if (merged[key] === undefined) {
merged[key] = true;
}
}
array.forEach(item => {
if (isObjectOrArray(item)) {
_mergeObject(item, merged, recurse);
} else {
_mergeValue(item, merged);
}
});
const paths = [];
_collectPaths(merged, [], paths);
return paths;
}
// internal function for collectNestedPaths
// mutates the argument `merged`
function _mergeObject(object, merged, recurse) {
for (const key in object) {
const value = object[key];
const valueMerged = merged[key] || (merged[key] = Array.isArray(value) ? [] : {});
if (recurse(value)) {
_mergeObject(value, valueMerged, recurse);
} else {
_mergeValue(value, valueMerged);
}
}
records.forEach(record => mergeRecord(record, merged));
const paths = [];
function collectPaths(object, parentPath) {
}
// internal function for collectNestedPaths
// mutates the argument `merged`
function _mergeValue(value, merged) {
if (merged[leaf] === undefined) {
merged[leaf] = value === null || value === undefined ? null : true;
}
}
// internal function for collectNestedPaths
// mutates the argument `paths`
function _collectPaths(object, parentPath, paths) {
if (object[leaf] === true || object[leaf] === null && isEmpty(object)) {
paths.push(parentPath);
} else if (Array.isArray(object)) {
object.forEach((item, index) => _collectPaths(item, parentPath.concat(index), paths));
} else if (isObjectOrArray(object)) {
for (const key in object) {
const path = parentPath.concat(Array.isArray(object) ? parseInt(key) : key);
const value = object[key];
if (flatten(value)) {
collectPaths(value, path);
} else {
paths.push(path);
}
_collectPaths(object[key], parentPath.concat(key), paths);
}
}
collectPaths(merged, []);
return paths;
}

@@ -184,2 +206,5 @@ function createGetValue(path) {

}
function isEmpty(object) {
return Object.keys(object).length === 0;
}

@@ -210,8 +235,10 @@ function createFormatValue(delimiter) {

function parseValue(value) {
if (value[0] === '"') {
const unescapedValue = value.substring(1, value.length - 1).replaceAll('""', '"');
return unescapedValue === '' ? unescapedValue : parseUnescapedValue(unescapedValue);
if (value === '') {
return null;
}
return parseUnescapedValue(value);
return parseUnescapedValue(unescapeValue(value));
}
function unescapeValue(value) {
return value[0] === '"' ? value.substring(1, value.length - 1).replaceAll('""', '"') : value;
}
function parseUnescapedValue(value) {

@@ -228,3 +255,3 @@ const number = Number(value);

}
if (value === 'null' || value === '') {
if (value === 'null') {
return null;

@@ -266,4 +293,3 @@ }

const eol = validateEOL(options?.eol || '\r\n');
const flatten = typeof options?.flatten === 'function' ? options?.flatten : options?.flatten === false ? () => false : isObjectOrArray; // options?.flatten is true or undefined
const fields = options?.fields ? Array.isArray(options?.fields) ? options?.fields : options?.fields(json) : collectFields(json, flatten);
const fields = options?.fields ? Array.isArray(options?.fields) ? options?.fields : options?.fields(json) : collectFields(json, options?.flatten !== false, options?.flattenArray === true);
const formatValue = options?.formatValue || createFormatValue(delimiter);

@@ -299,3 +325,3 @@ let output = '';

fields[index]?.setValue(object, value);
});
}, parse);
json.push(object);

@@ -308,3 +334,3 @@ }

names.push(withHeader ? String(fieldName) : `Field ${index}`);
});
}, unescapeValue);
if (!withHeader) {

@@ -316,6 +342,6 @@ i = 0; // reset the pointer again: the first line contains data, not a header

}
function parseRecord(onField) {
function parseRecord(onField, parse) {
let index = 0;
while (i < csv.length && !isEol(csv, i)) {
onField(parseField(), index);
onField(parseField(parse), index);
index++;

@@ -328,3 +354,3 @@ if (csv.charCodeAt(i) === delimiter) {

}
function parseField() {
function parseField(parse) {
const start = i;

@@ -335,3 +361,3 @@ if (csv.charCodeAt(i) === quote) {

i++;
if (csv.charCodeAt(i) === quote && csv.charCodeAt(i + 1) === quote) {
while (csv.charCodeAt(i) === quote && csv.charCodeAt(i + 1) === quote) {
// skip over escaped quote (two quotes)

@@ -375,4 +401,5 @@ i += 2;

exports.stringifyPath = stringifyPath;
exports.unescapeValue = unescapeValue;
}));
//# sourceMappingURL=csv42.js.map

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

!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).csv42={})}(this,function(e){"use strict";function r(e,n){let t=e,r=0;for(;r<n.length&&void 0!==t;)t=t[n[r]],r++;return t}function h(e,n,t){let r=e;var o=n.length-1;let i=0;for(;i<o;){var a=n[i];void 0===r[a]&&("number"==typeof n[i+1]?r[a]=[]:r[a]={}),r=r[a],i++}return r[n[o]]=t,e}function s(e){return null!==e&&"object"==typeof e}function t(e){return e.map((e,n)=>"number"==typeof e?"["+e+"]":/[.\[\]]/.test(e)?'["'+e+'"]':(0<n?".":"")+e).join("")}function p(t){var e,n,r=[];let o=0;for(;o<t.length;)"."===t[o]&&o++,"["===t[o]?(o++,'"'===t[o]?(o++,r.push(i(e=>'"'===e)),a('"')):(e=i(e=>"]"===e),n=Number(e),r.push(isNaN(n)?e:n)),a("]")):r.push(i(e=>"."===e||"["===e));function i(e){for(var n=o;o<t.length&&!e(t[o]);)o++;return t.substring(n,o)}function a(e){if(t[o]!==e)throw new SyntaxError(`Invalid JSON path: ${e} expected at position `+o);o++}return r}function c(e,n){return o(e,n).map(e=>({name:t(e),getValue:function(n){if(1!==n.length)return e=>r(e,n);{const t=n[0];return e=>e[t]}}(e)}))}function o(e,a){const n={};e.forEach(e=>function e(n,t){for(const o in n){var r=n[o];a(r)?(void 0===t[o]&&(t[o]=Array.isArray(n[o])?[]:{}),e(r,t[o])):void 0===t[o]&&(t[o]=!0)}}(e,n));const u=[];return function e(n,t){for(const i in n){var r=t.concat(Array.isArray(n)?parseInt(i):i),o=n[i];a(o)?e(o,r):u.push(r)}}(n,[]),u}function l(e){const r=new RegExp("["+e+'"\r\n]');return function e(n){var t;return"string"==typeof n?(t=n,r.test(t)||0===t.length?'"'+t.replaceAll('"','""')+'"':t):"number"==typeof n||"boolean"==typeof n?String(n):null==n?"":e(JSON.stringify(n))}}function g(e){var n;return'"'===e[0]?""===(n=e.substring(1,e.length-1).replaceAll('""','"'))?n:i(n):i(e)}function i(e){var n=Number(e);return isNaN(n)||isNaN(parseFloat(e))?"true"===e||"false"!==e&&("null"===e||""===e?null:"{"===e[0]||"["===e[0]?JSON.parse(e):e):n}function v(e){if(1!==e.length)throw new Error(`Invalid delimiter: must be a single character but is "${e}"`);return e}function m(e,n){return y(e,n)||A(e,n)}function y(e,n){return e.charCodeAt(n)===a}function A(e,n){return e.charCodeAt(n)===u&&e.charCodeAt(n+1)===a}const a=10,u=13;e.collectNestedPaths=o,e.createFormatValue=l,e.csv2json=function(t,e){const r=!1!==e?.header,o=v(e?.delimiter||",").charCodeAt(0),i='"'.charCodeAt(0),a=e?.parseValue||g;var n=[];let u=0;var f,s=function(){const t=[];l((e,n)=>{t.push(r?String(e):"Field "+n)}),r||(u=0);return t}();const c=e?.fields?function(e,n){var t,r=[];for(t of n){var o=void 0!==t.index?t.index:e.indexOf(t.name);if(-1===o)throw new Error(`Field "${t.name}" not found in the csv data`);if(r[o])throw new Error("Duplicate field for index "+o);r[o]=t}return r}(s,Array.isArray(e?.fields)?e?.fields:e?.fields(s)):(f=!1!==e?.nested,s.map(t=>{const r=p(t);return{name:t,setValue:1!==r.length&&f?(e,n)=>h(e,r,n):(e,n)=>e[t]=n}}));for(;u<t.length;){const d={};l((e,n)=>{c[n]?.setValue(d,e)}),n.push(d)}return n;function l(e){let n=0;for(;u<t.length&&!m(t,u);)e(function(){var e=u;if(t.charCodeAt(u)===i){for(;u++,t.charCodeAt(u)===i&&t.charCodeAt(u+1)===i&&(u+=2),u<t.length&&t.charCodeAt(u)!==i;);if(t.charCodeAt(u)!==i)throw new Error('Unexpected end: end quote " missing');u++}else for(;u<t.length&&t.charCodeAt(u)!==o&&!m(t,u);)u++;return a(t.substring(e,u))}(),n),n++,t.charCodeAt(u)===o&&u++;y(t,u)?u++:A(t,u)&&(u+=2)}},e.getIn=r,e.json2csv=function(n,e){var t=!1!==e?.header;const r=v(e?.delimiter||",");var o=function(e){if(m(e,0))return e;throw new Error('Invalid EOL character: choose "\\n" or "\\r\\n"')}(e?.eol||"\r\n"),i="function"==typeof e?.flatten?e?.flatten:!1===e?.flatten?()=>!1:s;const a=e?.fields?Array.isArray(e?.fields)?e?.fields:e?.fields(n):c(n,i),u=e?.formatValue||l(r);let f="";t&&(f+=a.map(e=>u(e.name)).join(r)+o);for(let e=0;e<n.length;e++)f+=function(n){return a.map(e=>u(e.getValue(n))).join(r)}(n[e])+o;return f},e.parsePath=p,e.parseValue=g,e.setIn=h,e.stringifyPath=t});
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).csv42={})}(this,function(e){"use strict";function r(e,n){let t=e,r=0;for(;r<n.length&&void 0!==t;)t=t?.[n[r]],r++;return t}function h(e,n,t){let r=e;var o=n.length-1;let i=0;for(;i<o;){var u=n[i];void 0===r[u]&&("number"==typeof n[i+1]?r[u]=[]:r[u]={}),r=r[u],i++}return r[n[o]]=t,e}function i(e){return"object"==typeof e&&null!==e}function u(e){return"object"==typeof e&&null!==e&&e.constructor===Object}function o(e){return e.map((e,n)=>"number"==typeof e?"["+e+"]":/[.\[\]]/.test(e)||""===e?'["'+e+'"]':(0<n?".":"")+e).join("")}function p(t){var e,n,r=[];let o=0;for(;o<t.length;)"."===t[o]&&o++,"["===t[o]?(o++,'"'===t[o]?(o++,r.push(i(e=>'"'===e)),u('"')):(e=i(e=>"]"===e),n=Number(e),r.push(isNaN(n)?e:n)),u("]")):r.push(i(e=>"."===e||"["===e));function i(e){for(var n=o;o<t.length&&!e(t[o]);)o++;return t.substring(n,o)}function u(e){if(t[o]!==e)throw new SyntaxError(`Invalid JSON path: ${e} expected at position `+o);o++}return r}function f(e,n,t){return l(e,n,t).map(e=>({name:o(e),getValue:function(n){if(1!==n.length)return e=>r(e,n);{const t=n[0];return e=>e[t]}}(e)}))}const a=Symbol();function l(e,n,t){const r=n?t?i:u:()=>!1,o={};e.forEach(e=>{i(e)?function e(n,t,r){for(const o in n){const i=n[o],u=t[o]||(t[o]=Array.isArray(i)?[]:{});r(i)?e(i,u,r):c(i,u)}}(e,o,r):c(e,o)});n=[];return function t(e,r,o){if(!0===e[a]||null===e[a]&&s(e))o.push(r);else if(Array.isArray(e))e.forEach((e,n)=>t(e,r.concat(n),o));else if(i(e))for(const n in e)t(e[n],r.concat(n),o)}(o,[],n),n}function c(e,n){void 0===n[a]&&(n[a]=null!=e||null)}function s(e){return 0===Object.keys(e).length}function d(e){const r=new RegExp("["+e+'"\r\n]');return function e(n){var t;return"string"==typeof n?(t=n,r.test(t)||0===t.length?'"'+t.replaceAll('"','""')+'"':t):"number"==typeof n||"boolean"==typeof n?String(n):null==n?"":e(JSON.stringify(n))}}function g(e){return""===e?null:(e=m(e),n=Number(e),isNaN(n)||isNaN(parseFloat(e))?"true"===e||"false"!==e&&("null"!==e?"{"!==e[0]&&"["!==e[0]?e:JSON.parse(e):null):n);var n}function m(e){return'"'===e[0]?e.substring(1,e.length-1).replaceAll('""','"'):e}function y(e){if(1!==e.length)throw new Error(`Invalid delimiter: must be a single character but is "${e}"`);return e}function v(e,n){return A(e,n)||b(e,n)}function A(e,n){return e.charCodeAt(n)===t}function b(e,n){return e.charCodeAt(n)===w&&e.charCodeAt(n+1)===t}const t=10,w=13;e.collectNestedPaths=l,e.createFormatValue=d,e.csv2json=function(r,e){const o=!1!==e?.header,i=y(e?.delimiter||",").charCodeAt(0),u='"'.charCodeAt(0);var n=e?.parseValue||g,t=[];let a=0;var f,l=function(){const t=[];s((e,n)=>{t.push(o?String(e):"Field "+n)},m),o||(a=0);return t}();const c=e?.fields?function(e,n){var t,r=[];for(t of n){var o=void 0!==t.index?t.index:e.indexOf(t.name);if(-1===o)throw new Error(`Field "${t.name}" not found in the csv data`);if(r[o])throw new Error("Duplicate field for index "+o);r[o]=t}return r}(l,Array.isArray(e?.fields)?e?.fields:e?.fields(l)):(f=!1!==e?.nested,l.map(t=>{const r=p(t),o=r[0];return{name:t,setValue:0!==r.length&&f?1===r.length?(e,n)=>e[o]=n:(e,n)=>h(e,r,n):(e,n)=>e[t]=n}}));for(;a<r.length;){const d={};s((e,n)=>{c[n]?.setValue(d,e)},n),t.push(d)}return t;function s(e,n){let t=0;for(;a<r.length&&!v(r,a);)e(function(e){var n=a;if(r.charCodeAt(a)===u){do{for(a++;r.charCodeAt(a)===u&&r.charCodeAt(a+1)===u;)a+=2}while(a<r.length&&r.charCodeAt(a)!==u);if(r.charCodeAt(a)!==u)throw new Error('Unexpected end: end quote " missing');a++}else for(;a<r.length&&r.charCodeAt(a)!==i&&!v(r,a);)a++;return e(r.substring(n,a))}(n),t),t++,r.charCodeAt(a)===i&&a++;A(r,a)?a++:b(r,a)&&(a+=2)}},e.getIn=r,e.json2csv=function(n,e){var t=!1!==e?.header;const r=y(e?.delimiter||",");var o=function(e){if(v(e,0))return e;throw new Error('Invalid EOL character: choose "\\n" or "\\r\\n"')}(e?.eol||"\r\n");const i=e?.fields?Array.isArray(e?.fields)?e?.fields:e?.fields(n):f(n,!1!==e?.flatten,!0===e?.flattenArray),u=e?.formatValue||d(r);let a="";t&&(a+=i.map(e=>u(e.name)).join(r)+o);for(let e=0;e<n.length;e++)a+=function(n){return i.map(e=>u(e.getValue(n))).join(r)}(n[e])+o;return a},e.parsePath=p,e.parseValue=g,e.setIn=h,e.stringifyPath=o,e.unescapeValue=m});

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

The ISC License
ISC License (ISC)

@@ -7,2 +7,2 @@ Copyright (c) 2023 by Jos de Jong

THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
{
"name": "csv42",
"version": "1.0.0",
"description": "Small and fast CSV parser to convert nested JSON to CSV and CSV to JSON",
"version": "2.0.0",
"description": "A small and fast CSV parser with support for nested JSON",
"repository": {

@@ -6,0 +6,0 @@ "type": "git",

# csv42
Convert **CSV to JSON** and **JSON to CSV**
A small and fast CSV parser with support for nested JSON.
[![Version](https://img.shields.io/npm/v/csv42.svg)](https://www.npmjs.com/package/csv42)
[![Downloads](https://img.shields.io/npm/dm/csv42.svg)](https://www.npmjs.com/package/csv42)
[![Build Status](https://github.com/josdejong/csv42/workflows/Node.js%20CI/badge.svg)](https://github.com/josdejong/csv42/actions)
[![Maintenance](https://img.shields.io/maintenance/yes/2023.svg)](https://github.com/josdejong/csv42/graphs/commit-activity)
[![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](https://github.com/josdejong/csv42/blob/main/LICENSE.md)
[![Codecov](https://codecov.io/gh/josdejong/csv42/branch/main/graph/badge.svg)](https://codecov.io/gh/josdejong/csv42)
[![Github Sponsor](https://camo.githubusercontent.com/7d9333b097b2f54a8957d126ab82937811489c9b75c3850f609985cf94cd29fe/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f2532302d53706f6e736f722532306d652532306f6e2532304769744875622d6f72616e6765)](https://github.com/sponsors/josdejong)
## Features
- **2 way**: convert from and to CSV
- **Simple**: straightforward and flexible API
- **Lightweight**: <2KB gzipped with everything included, <1KB gzipped when only using `json2csv`
- **2 way**: convert JSON to CSV and the other way around.
- **Simple**: straightforward and flexible API.
- **Lightweight**: 2KB gzipped with everything included, 1KB gzipped when only using `json2csv`.
- **Fast**: faster than the popular CSV libraries out there. See [benchmark](/benchmark).
- **Modular**: only load what you use, thanks to ES5 modules and a plugin architecture
- **Modular**: only load what you use, thanks to ES5 modules and a plugin architecture.
- **Powerful**:
- Configurable properties: `header`, `delimiter`, `eol`
- Configurable `fields`, with custom value getters and setters and the ability to ignore fields
- Configurable serialization and deserialization of values via `formatValue` and `parseValue`
- Support for nested JSON objects: either flatten nested contents, or stringify as a JSON object
- **Standards compliant**: adheres to the CSV standard [RFC 4180](https://datatracker.ietf.org/doc/html/rfc4180)
- **Universal**: Created for the browser, but can be used in any JavaScript environment like node.js.
- Configurable properties: `header`, `delimiter`, `eol`.
- Configurable `fields`, with custom value getters and setters and the ability to ignore fields.
- Configurable serialization and deserialization of values via `formatValue` and `parseValue`.
- Support for nested JSON objects: either flatten nested contents, or stringify as a JSON object.
- **Standards compliant**: adheres to the CSV standard [RFC 4180](https://datatracker.ietf.org/doc/html/rfc4180).
- **Universal**: Created for the browser, but can be used in any JavaScript environment like node.js. TypeScript types included.

@@ -26,3 +34,3 @@ Note that the parser has no streaming support.

The `csv42` library was developed specifically for https://jsoneditoronline.org. The library was developed for the browser. Besides being small and fast, one important feature is supporting nested JSON objects. So, why the name `csv42`? Just because [42](<https://simple.wikipedia.org/wiki/42_(answer)>) is a beautiful number and reminds us that there is a whole universe of beautiful CSV libraries out there.
The `csv42` library was developed specifically for https://jsoneditoronline.org, for use in the browser. Besides being small and fast, one important feature is supporting nested JSON objects. So, why the name `csv42`? Just because [42](<https://simple.wikipedia.org/wiki/42_(answer)>) is a beautiful number and to remind us that there is a whole universe of beautiful CSV libraries out there.

@@ -121,10 +129,11 @@ ## Install

| Option | Type | Description |
| ------------- | ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `header` | `boolean` | If true, a header will be created as first line of the CSV. |
| `delimiter` | `string` | Default delimiter is `,`. A delimiter must be a single character. |
| `eol` | `\r\n` or `\n` | End of line, can be `\r\n` (default) or `\n`. |
| `flatten` | `boolean` or `(value: unknown) => boolean` | If `true` (default), nested objects and arrays will be flattened in multiple CSV columns. When `false`, nested objects and arrays will be serialized as JSON in a single CSV field. This behavior can be customized by providing your own callback function for `flatten`. For example, to flatten objects but not arrays, you can do `json2csv(json, { flatten: (value) => value ? value.constructor === Object : false })`. The option `flatten` is not applicable when `fields` is defined. |
| `fields` | `CsvField[]` or `CsvFieldsParser` | A list with fields to be put into the CSV file. This allows specifying the order of the fields and which fields to include/excluded. |
| `formatValue` | `ValueFormatter` | Function used to change any type of value into a serialized string for the CSV. The build in formatter will only enclose values in quotes when necessary, and will stringify nested JSON objects. |
| Option | Type | Description |
| -------------- | --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `header` | `boolean` | If true, a header will be created as first line of the CSV. |
| `delimiter` | `string` | Default delimiter is `,`. A delimiter must be a single character. |
| `eol` | `\r\n` or `\n` | End of line, can be `\r\n` (default) or `\n`. |
| `flatten` | `boolean` | If `true` (default), nested objects will be flattened in multiple CSV columns. When `false`, nested objects will be serialized as JSON in a single CSV field. See also option `flattenArray`. The option `flatten` is not applicable when `fields` is defined. |
| `flattenArray` | `boolean` | If `true`, each item in a nested array will be expanded in a separate column. When `false` (default), arrays will be serialized into a single column. Only applicable when `flatten` is `true`. |
| `fields` | `CsvField[]` or `CsvFieldsParser` | A list with fields to be put into the CSV file. This allows specifying the order of the fields and which fields to include/excluded. |
| `formatValue` | `ValueFormatter` | Function used to change any type of value into a serialized string for the CSV. The build in formatter will only enclose values in quotes when necessary, and will stringify nested JSON objects. |

@@ -167,5 +176,6 @@ A simple example of a `ValueFormatter` is the following. This formatter will enclose every value in quotes:

| `parseValue(value: string): unknown` | Parse a string into a value, parse numbers into a number, etc. This is the function used by default for the option `parseValue`. |
| `unescapeValue(value: string) : string` | Unescape an escaped value like `"hello ""Joe"""` into the string `hello "Joe"`. |
| `collectNestedPaths(records: NestedObject[], recurse: boolean): Path[]` | Loop over the data and collect all nested paths. This can be used to generate a list with fields. |
| `parsePath(pathStr: string): Path` | Parse a path like `'items[3].name'` |
| `function stringifyPath(path: Path): string` | Stringify a path into a string like `'items[3].name'` |
| `stringifyPath(path: Path): string` | Stringify a path into a string like `'items[3].name'` |
| `getIn(object: NestedObject, path: Path): unknown` | Get a nested property from an object |

@@ -172,0 +182,0 @@ | `setIn(object: NestedObject, path: Path, value: unknown): NestedObject` | Set a nested property in an object |

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

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