@lowdep/csv2json 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +117 -0
- package/bin/csv2json.js +252 -0
- package/package.json +47 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Rushabh Shah
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# csv2json
|
|
2
|
+
|
|
3
|
+
   
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
Convert between CSV and JSON in **both directions**, with automatic type inference and a proper RFC 4180 parser (quoted fields, escaped quotes, embedded newlines). Zero dependencies.
|
|
7
|
+
|
|
8
|
+
The companion to [`csv-peek`](https://github.com/Rushabh5000/csv-peek) (which previews CSVs). Unlike `csvkit` (Python) or paste-it-here websites, this runs locally and never uploads your data.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install -g csv2json
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Or without installing:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npx csv2json data.csv
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
csv2json users.csv # CSV → JSON on stdout
|
|
30
|
+
csv2json users.csv -o users.json # CSV → JSON file
|
|
31
|
+
csv2json users.json -o users.csv # JSON → CSV
|
|
32
|
+
csv2json data.tsv -d tab # Tab-separated input
|
|
33
|
+
cat export.csv | csv2json - --compact # From stdin, single-line JSON
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Direction is inferred from the file extension (or the `-o` target), and falls back to sniffing the content. Force it with `--from csv|json`.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Example
|
|
41
|
+
|
|
42
|
+
`users.csv`:
|
|
43
|
+
```csv
|
|
44
|
+
id,name,active,score
|
|
45
|
+
1,Alice,true,9.5
|
|
46
|
+
2,Bob,false,7
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
`csv2json users.csv`:
|
|
50
|
+
```json
|
|
51
|
+
[
|
|
52
|
+
{ "id": 1, "name": "Alice", "active": true, "score": 9.5 },
|
|
53
|
+
{ "id": 2, "name": "Bob", "active": false, "score": 7 }
|
|
54
|
+
]
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Note that `1`→number, `true`→boolean, `9.5`→float automatically. Disable with `--no-type`.
|
|
58
|
+
|
|
59
|
+
Reverse it — `csv2json users.json -o users.csv` — and you get the CSV back.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## Type Inference
|
|
64
|
+
|
|
65
|
+
| CSV value | JSON value |
|
|
66
|
+
|---|---|
|
|
67
|
+
| `42` | `42` (number) |
|
|
68
|
+
| `3.14` | `3.14` (number) |
|
|
69
|
+
| `true` / `false` | boolean |
|
|
70
|
+
| `null` | `null` |
|
|
71
|
+
| empty cell | `""` (or `null` with `--empty-as-null`) |
|
|
72
|
+
| anything else | string |
|
|
73
|
+
|
|
74
|
+
Turn it off with `--no-type` to keep every value a string.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Options
|
|
79
|
+
|
|
80
|
+
| Flag | Description |
|
|
81
|
+
|---|---|
|
|
82
|
+
| `--from <csv\|json>` | Force input format (for stdin / odd extensions) |
|
|
83
|
+
| `-o, --out <file>` | Write to a file (format from its extension) |
|
|
84
|
+
| `-d, --delimiter <d>` | `,` `;` `\|` or `tab` (default: auto-detect) |
|
|
85
|
+
| `--no-header` | CSV has no header → arrays of values |
|
|
86
|
+
| `--no-type` | Keep all values as strings |
|
|
87
|
+
| `--empty-as-null` | Empty CSV cells become `null` |
|
|
88
|
+
| `--skip-empty` | Omit empty cells from JSON objects |
|
|
89
|
+
| `--pretty` / `--compact` | JSON formatting (pretty is default) |
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## Nested Values
|
|
94
|
+
|
|
95
|
+
When converting **JSON → CSV**, nested objects/arrays in a cell are serialized as JSON strings (and properly quoted). The header row is the union of all keys across every record, in first-seen order.
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## License
|
|
100
|
+
|
|
101
|
+
MIT
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Keywords
|
|
106
|
+
|
|
107
|
+
`csv to json` · `json to csv` · `convert csv` · `csv json converter` · `csvkit alternative` · `rfc 4180` · `parse csv` · `tsv to json` · `zero dependencies` · `cli`
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
<div align="center">
|
|
112
|
+
|
|
113
|
+
**Built to solve, shared to help — Rushabh Shah 🛠️✨**
|
|
114
|
+
|
|
115
|
+
<sub>One of 40+ zero-dependency developer CLI tools — no <code>node_modules</code>, ever.</sub>
|
|
116
|
+
|
|
117
|
+
</div>
|
package/bin/csv2json.js
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
|
|
7
|
+
const VERSION = '1.0.0';
|
|
8
|
+
|
|
9
|
+
// ─── ANSI ─────────────────────────────────────────────────────────────────────
|
|
10
|
+
const isTTY = process.stderr.isTTY;
|
|
11
|
+
const c = (code, t) => isTTY ? `\x1b[${code}m${t}\x1b[0m` : t;
|
|
12
|
+
const bold = t => c('1', t);
|
|
13
|
+
const dim = t => c('2', t);
|
|
14
|
+
const red = t => c('31', t);
|
|
15
|
+
const green = t => c('32', t);
|
|
16
|
+
const yellow = t => c('33', t);
|
|
17
|
+
const cyan = t => c('36', t);
|
|
18
|
+
|
|
19
|
+
// ─── CSV parser (RFC 4180, quoted fields, escaped quotes, CRLF) ───────────────
|
|
20
|
+
function parseCSV(content, delimiter) {
|
|
21
|
+
const rows = [];
|
|
22
|
+
let row = [], field = '', inQuotes = false;
|
|
23
|
+
|
|
24
|
+
for (let i = 0; i < content.length; i++) {
|
|
25
|
+
const ch = content[i], next = content[i + 1];
|
|
26
|
+
if (inQuotes) {
|
|
27
|
+
if (ch === '"' && next === '"') { field += '"'; i++; }
|
|
28
|
+
else if (ch === '"') { inQuotes = false; }
|
|
29
|
+
else { field += ch; }
|
|
30
|
+
} else {
|
|
31
|
+
if (ch === '"') { inQuotes = true; }
|
|
32
|
+
else if (ch === delimiter) { row.push(field); field = ''; }
|
|
33
|
+
else if (ch === '\n' || (ch === '\r' && next === '\n')) {
|
|
34
|
+
if (ch === '\r') i++;
|
|
35
|
+
row.push(field); field = '';
|
|
36
|
+
rows.push(row); row = [];
|
|
37
|
+
} else field += ch;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (field !== '' || row.length) { row.push(field); rows.push(row); }
|
|
41
|
+
// Drop a trailing empty row produced by a final newline
|
|
42
|
+
if (rows.length && rows[rows.length - 1].length === 1 && rows[rows.length - 1][0] === '') rows.pop();
|
|
43
|
+
return rows;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function detectDelimiter(firstLine) {
|
|
47
|
+
const counts = {
|
|
48
|
+
',': (firstLine.match(/,/g) || []).length,
|
|
49
|
+
'\t': (firstLine.match(/\t/g) || []).length,
|
|
50
|
+
';': (firstLine.match(/;/g) || []).length,
|
|
51
|
+
'|': (firstLine.match(/\|/g) || []).length,
|
|
52
|
+
};
|
|
53
|
+
return Object.entries(counts).sort(([, a], [, b]) => b - a)[0][0] || ',';
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ─── Value coercion ───────────────────────────────────────────────────────────
|
|
57
|
+
function coerce(val, opts) {
|
|
58
|
+
if (opts.noType) return val;
|
|
59
|
+
if (val === '') return opts.emptyAsNull ? null : '';
|
|
60
|
+
const t = val.trim();
|
|
61
|
+
if (t === '') return val;
|
|
62
|
+
if (/^-?\d+$/.test(t)) return parseInt(t, 10);
|
|
63
|
+
if (/^-?\d*\.\d+([eE][+-]?\d+)?$/.test(t)) return parseFloat(t);
|
|
64
|
+
if (/^-?\d+\.\d+$/.test(t)) return parseFloat(t);
|
|
65
|
+
const low = t.toLowerCase();
|
|
66
|
+
if (low === 'true') return true;
|
|
67
|
+
if (low === 'false') return false;
|
|
68
|
+
if (low === 'null') return null;
|
|
69
|
+
return val;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ─── CSV → JSON ───────────────────────────────────────────────────────────────
|
|
73
|
+
function csvToJson(content, opts) {
|
|
74
|
+
const delimiter = opts.delimiter || detectDelimiter(content.split('\n')[0]);
|
|
75
|
+
const rows = parseCSV(content, delimiter);
|
|
76
|
+
if (!rows.length) return [];
|
|
77
|
+
|
|
78
|
+
if (opts.noHeader) {
|
|
79
|
+
return rows.map(r => r.map(v => coerce(v, opts)));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const headers = rows[0].map(h => h.trim());
|
|
83
|
+
const out = [];
|
|
84
|
+
for (let i = 1; i < rows.length; i++) {
|
|
85
|
+
const r = rows[i];
|
|
86
|
+
const obj = {};
|
|
87
|
+
headers.forEach((h, j) => {
|
|
88
|
+
if (opts.skipEmpty && (r[j] === undefined || r[j] === '')) return;
|
|
89
|
+
obj[h] = coerce(r[j] !== undefined ? r[j] : '', opts);
|
|
90
|
+
});
|
|
91
|
+
out.push(obj);
|
|
92
|
+
}
|
|
93
|
+
return out;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ─── JSON → CSV ───────────────────────────────────────────────────────────────
|
|
97
|
+
function jsonToCsv(data, opts) {
|
|
98
|
+
const delimiter = opts.delimiter || ',';
|
|
99
|
+
let rows;
|
|
100
|
+
|
|
101
|
+
if (Array.isArray(data)) rows = data;
|
|
102
|
+
else if (data && typeof data === 'object') rows = [data];
|
|
103
|
+
else throw new Error('JSON must be an array of objects (or a single object)');
|
|
104
|
+
|
|
105
|
+
if (!rows.length) return '';
|
|
106
|
+
|
|
107
|
+
// Collect the union of all keys, preserving first-seen order
|
|
108
|
+
const allArrays = rows.every(r => Array.isArray(r));
|
|
109
|
+
if (allArrays) {
|
|
110
|
+
return rows.map(r => r.map(v => csvCell(v, delimiter)).join(delimiter)).join('\n') + '\n';
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const headers = [];
|
|
114
|
+
const seen = new Set();
|
|
115
|
+
for (const r of rows) {
|
|
116
|
+
if (r && typeof r === 'object' && !Array.isArray(r)) {
|
|
117
|
+
for (const k of Object.keys(r)) if (!seen.has(k)) { seen.add(k); headers.push(k); }
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const lines = [];
|
|
122
|
+
if (!opts.noHeader) lines.push(headers.map(h => csvCell(h, delimiter)).join(delimiter));
|
|
123
|
+
for (const r of rows) {
|
|
124
|
+
lines.push(headers.map(h => csvCell(r ? r[h] : undefined, delimiter)).join(delimiter));
|
|
125
|
+
}
|
|
126
|
+
return lines.join('\n') + '\n';
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function csvCell(v, delimiter) {
|
|
130
|
+
if (v === undefined || v === null) return '';
|
|
131
|
+
let s;
|
|
132
|
+
if (typeof v === 'object') s = JSON.stringify(v);
|
|
133
|
+
else s = String(v);
|
|
134
|
+
// Quote if it contains delimiter, quote, or newline
|
|
135
|
+
if (s.includes(delimiter) || s.includes('"') || s.includes('\n') || s.includes('\r')) {
|
|
136
|
+
s = '"' + s.replace(/"/g, '""') + '"';
|
|
137
|
+
}
|
|
138
|
+
return s;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// ─── CLI ──────────────────────────────────────────────────────────────────────
|
|
142
|
+
const args = process.argv.slice(2);
|
|
143
|
+
const VALUE_FLAGS = new Set(['-d', '--delimiter', '-o', '--out']);
|
|
144
|
+
|
|
145
|
+
function getFlag(...names) {
|
|
146
|
+
for (const f of names) { const i = args.indexOf(f); if (i !== -1) return args[i + 1]; }
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
function hasFlag(...names) { return names.some(f => args.includes(f)); }
|
|
150
|
+
|
|
151
|
+
const positional = [];
|
|
152
|
+
for (let i = 0; i < args.length; i++) {
|
|
153
|
+
if (args[i].startsWith('-') && args[i] !== '-') { if (VALUE_FLAGS.has(args[i])) i++; }
|
|
154
|
+
else positional.push(args[i]);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (hasFlag('--version', '-v')) {
|
|
158
|
+
console.log(`csv2json v${VERSION}`); process.exit(0);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (hasFlag('--help', '-h') || !positional.length) {
|
|
162
|
+
console.log(`
|
|
163
|
+
${bold('csv2json')} — Convert between CSV and JSON, both directions, zero deps
|
|
164
|
+
|
|
165
|
+
${bold('USAGE')}
|
|
166
|
+
csv2json <file.csv> Convert CSV → JSON (auto-detected by extension)
|
|
167
|
+
csv2json <file.json> Convert JSON → CSV
|
|
168
|
+
cat data.csv | csv2json - Read from stdin (assumes CSV unless --from)
|
|
169
|
+
|
|
170
|
+
${bold('OPTIONS')}
|
|
171
|
+
--from <csv|json> Force input format (needed for stdin / odd extensions)
|
|
172
|
+
-o, --out <file> Write to a file (format inferred from its extension)
|
|
173
|
+
-d, --delimiter <d> CSV delimiter: , ; | or "tab" (default: auto-detect)
|
|
174
|
+
--no-header CSV has no header row → arrays of values
|
|
175
|
+
--no-type Don't coerce numbers/booleans/null (keep strings)
|
|
176
|
+
--empty-as-null Convert empty CSV cells to null instead of ""
|
|
177
|
+
--skip-empty Omit empty cells from JSON objects entirely
|
|
178
|
+
--pretty Pretty-print JSON output (default for TTY)
|
|
179
|
+
--compact Compact single-line JSON
|
|
180
|
+
--version Show version
|
|
181
|
+
|
|
182
|
+
${bold('EXAMPLES')}
|
|
183
|
+
csv2json users.csv # → JSON on stdout
|
|
184
|
+
csv2json users.csv -o users.json # → JSON file
|
|
185
|
+
csv2json users.json -o users.csv # JSON → CSV
|
|
186
|
+
csv2json data.tsv -d tab # Tab-separated input
|
|
187
|
+
cat export.csv | csv2json - --compact # From stdin, one-line JSON
|
|
188
|
+
`);
|
|
189
|
+
process.exit(positional.length ? 0 : 1);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
let delimiter = getFlag('-d', '--delimiter');
|
|
193
|
+
if (delimiter === 'tab') delimiter = '\t';
|
|
194
|
+
const outFile = getFlag('-o', '--out');
|
|
195
|
+
const forceFrom = getFlag('--from');
|
|
196
|
+
const noHeader = hasFlag('--no-header');
|
|
197
|
+
const noType = hasFlag('--no-type');
|
|
198
|
+
const emptyAsNull = hasFlag('--empty-as-null');
|
|
199
|
+
const skipEmpty = hasFlag('--skip-empty');
|
|
200
|
+
const compact = hasFlag('--compact');
|
|
201
|
+
const pretty = hasFlag('--pretty') || (!compact && (isTTY || outFile));
|
|
202
|
+
|
|
203
|
+
// Read input
|
|
204
|
+
const inPath = positional[0];
|
|
205
|
+
let content, sourceName;
|
|
206
|
+
if (inPath === '-') {
|
|
207
|
+
content = fs.readFileSync(0, 'utf8'); // stdin
|
|
208
|
+
sourceName = '(stdin)';
|
|
209
|
+
} else {
|
|
210
|
+
const full = path.resolve(inPath);
|
|
211
|
+
if (!fs.existsSync(full)) { console.error(red(`File not found: ${full}`)); process.exit(1); }
|
|
212
|
+
content = fs.readFileSync(full, 'utf8');
|
|
213
|
+
sourceName = path.basename(inPath);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Determine direction
|
|
217
|
+
let direction = forceFrom
|
|
218
|
+
? (forceFrom === 'json' ? 'json2csv' : 'csv2json')
|
|
219
|
+
: null;
|
|
220
|
+
if (!direction) {
|
|
221
|
+
if (outFile && /\.csv$/i.test(outFile)) direction = 'json2csv';
|
|
222
|
+
else if (outFile && /\.json$/i.test(outFile)) direction = 'csv2json';
|
|
223
|
+
else if (/\.json$/i.test(inPath || '')) direction = 'json2csv';
|
|
224
|
+
else if (/\.(csv|tsv|txt)$/i.test(inPath || '')) direction = 'csv2json';
|
|
225
|
+
else {
|
|
226
|
+
// Sniff: starts with { or [ → JSON
|
|
227
|
+
direction = /^\s*[[{]/.test(content) ? 'json2csv' : 'csv2json';
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const opts = { delimiter, noHeader, noType, emptyAsNull, skipEmpty };
|
|
232
|
+
|
|
233
|
+
let output;
|
|
234
|
+
try {
|
|
235
|
+
if (direction === 'csv2json') {
|
|
236
|
+
const json = csvToJson(content, opts);
|
|
237
|
+
output = JSON.stringify(json, null, pretty ? 2 : 0);
|
|
238
|
+
} else {
|
|
239
|
+
const data = JSON.parse(content);
|
|
240
|
+
output = jsonToCsv(data, opts);
|
|
241
|
+
}
|
|
242
|
+
} catch (e) {
|
|
243
|
+
console.error(red(`\nConversion failed: ${e.message}\n`)); process.exit(1);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (outFile) {
|
|
247
|
+
fs.writeFileSync(path.resolve(outFile), output.endsWith('\n') ? output : output + '\n');
|
|
248
|
+
const arrow = direction === 'csv2json' ? 'CSV → JSON' : 'JSON → CSV';
|
|
249
|
+
process.stderr.write(`${green('✓')} ${arrow} ${dim(sourceName)} → ${cyan(outFile)}\n`);
|
|
250
|
+
} else {
|
|
251
|
+
process.stdout.write(output.endsWith('\n') ? output : output + '\n');
|
|
252
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lowdep/csv2json",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Convert between CSV and JSON in both directions with type inference — RFC 4180 parser, zero dependencies",
|
|
5
|
+
"bin": {
|
|
6
|
+
"csv2json": "bin/csv2json.js"
|
|
7
|
+
},
|
|
8
|
+
"keywords": [
|
|
9
|
+
"csv",
|
|
10
|
+
"json",
|
|
11
|
+
"convert",
|
|
12
|
+
"csv2json",
|
|
13
|
+
"json2csv",
|
|
14
|
+
"tsv",
|
|
15
|
+
"cli",
|
|
16
|
+
"data",
|
|
17
|
+
"zero-dependencies",
|
|
18
|
+
"csv to json",
|
|
19
|
+
"json to csv",
|
|
20
|
+
"convert csv",
|
|
21
|
+
"csv json converter",
|
|
22
|
+
"csvkit alternative",
|
|
23
|
+
"rfc 4180",
|
|
24
|
+
"parse csv",
|
|
25
|
+
"tsv to json",
|
|
26
|
+
"zero dependencies"
|
|
27
|
+
],
|
|
28
|
+
"author": "Rushabh Shah",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=14"
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"bin/"
|
|
35
|
+
],
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "git+https://github.com/Rushabh5000/csv2json.git"
|
|
39
|
+
},
|
|
40
|
+
"bugs": {
|
|
41
|
+
"url": "https://github.com/Rushabh5000/csv2json/issues"
|
|
42
|
+
},
|
|
43
|
+
"homepage": "https://github.com/Rushabh5000/csv2json#readme",
|
|
44
|
+
"publishConfig": {
|
|
45
|
+
"access": "public"
|
|
46
|
+
}
|
|
47
|
+
}
|