-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.js
93 lines (71 loc) · 3.03 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
const {Transform} = require('stream');
class CsvFilter extends Transform {
constructor(options) {
super({objectMode: options.objectMode || false});
this._objectMode = options.objectMode || false;
this._delimiter = options.delimiter || ',';
this._newLine = options.newLine || '\n';
this._targetDelimiter = options.targetDelimiter || this._delimiter;
this._targetNewLine = options.targetNewLine || this._newLine;
this._filter = options.filter || (fields => fields);
this._skipFirstLine = options.skipFirstLine || false;
}
_transform(chunk, encoding, callback) {
const newLine = Buffer.from(this._targetNewLine);
const delimiter = Buffer.from(this._targetDelimiter);
let index = 0;
const lines = [];
while (index > -1 && index < chunk.length - 1) {
const parts = [];
const prevIndex = index;
index = chunk.indexOf(this._newLine, index);
const line = chunk.slice(prevIndex, index > -1 ? index++ : chunk.length);
if (this._skipFirstLine) {
this._skipFirstLine = false;
continue;
}
let col = 0;
while (col > -1) {
const colIndex = col;
col = line.indexOf(this._delimiter, col);
parts.push(line.slice(colIndex, col > -1 ? col++ : line.length));
}
// skip line if it doesn't have csv column
if (parts.length === 0) {
continue;
}
let targetLine = this._filter(parts, chunk);
// skip line if callback return undefined
if (!targetLine) {
continue;
}
switch (typeof targetLine) {
case 'object':
if (targetLine instanceof Array) {
const cols = [];
// seperate columns with column seperator character
targetLine.forEach((part, index) => {
if (this._objectMode) {
cols.push(part.toString());
} else {
index > 0 && cols.push(delimiter);
cols.push(part);
}
});
targetLine = this._objectMode ? cols : Buffer.concat(cols);
} else if (!Buffer.isBuffer(targetLine)) {
continue;
}
break;
case 'string': targetLine = this._objectMode ? [targetLine] : Buffer.from(targetLine); break;
default: continue;
}
// combine new columns
lines.push(targetLine);
!this._objectMode && lines.push(newLine);
}
// combine new rows and give back to transform
callback(null, this._objectMode ? lines : Buffer.concat(lines));
}
}
module.exports = CsvFilter;