-
Notifications
You must be signed in to change notification settings - Fork 266
/
index.js
121 lines (115 loc) · 3.42 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/*
CSV Parse
Please look at the [project documentation](https://csv.js.org/parse/) for
additional information.
*/
import { Transform } from 'stream';
import {is_object} from './utils/is_object.js';
import {transform} from './api/index.js';
import {CsvError} from './api/CsvError.js';
class Parser extends Transform {
constructor(opts = {}){
super({...{readableObjectMode: true}, ...opts, encoding: null});
this.api = transform(opts);
this.api.options.on_skip = (err, chunk) => {
this.emit('skip', err, chunk);
};
// Backward compatibility
this.state = this.api.state;
this.options = this.api.options;
this.info = this.api.info;
}
// Implementation of `Transform._transform`
_transform(buf, _, callback){
if(this.state.stop === true){
return;
}
const err = this.api.parse(buf, false, (record) => {
this.push(record);
}, () => {
this.push(null);
this.end();
// Fix #333 and break #410
// ko: api.stream.iterator.coffee
// ko with v21.4.0, ok with node v20.5.1: api.stream.finished # aborted (with generate())
// ko: api.stream.finished # aborted (with Readable)
// this.destroy()
// Fix #410 and partially break #333
// ok: api.stream.iterator.coffee
// ok: api.stream.finished # aborted (with generate())
// broken: api.stream.finished # aborted (with Readable)
this.on('end', this.destroy);
});
if(err !== undefined){
this.state.stop = true;
}
callback(err);
}
// Implementation of `Transform._flush`
_flush(callback){
if(this.state.stop === true){
return;
}
const err = this.api.parse(undefined, true, (record) => {
this.push(record);
}, () => {
this.push(null);
this.on('end', this.destroy);
});
callback(err);
}
}
const parse = function(){
let data, options, callback;
for(const i in arguments){
const argument = arguments[i];
const type = typeof argument;
if(data === undefined && (typeof argument === 'string' || Buffer.isBuffer(argument))){
data = argument;
}else if(options === undefined && is_object(argument)){
options = argument;
}else if(callback === undefined && type === 'function'){
callback = argument;
}else{
throw new CsvError('CSV_INVALID_ARGUMENT', [
'Invalid argument:',
`got ${JSON.stringify(argument)} at index ${i}`
], options || {});
}
}
const parser = new Parser(options);
if(callback){
const records = options === undefined || options.objname === undefined ? [] : {};
parser.on('readable', function(){
let record;
while((record = this.read()) !== null){
if(options === undefined || options.objname === undefined){
records.push(record);
}else{
records[record[0]] = record[1];
}
}
});
parser.on('error', function(err){
callback(err, undefined, parser.api.__infoDataSet());
});
parser.on('end', function(){
callback(undefined, records, parser.api.__infoDataSet());
});
}
if(data !== undefined){
const writer = function(){
parser.write(data);
parser.end();
};
// Support Deno, Rollup doesnt provide a shim for setImmediate
if(typeof setImmediate === 'function'){
setImmediate(writer);
}else{
setTimeout(writer, 0);
}
}
return parser;
};
// export default parse
export { parse, Parser, CsvError };