-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathread-csv.js
48 lines (43 loc) · 1.44 KB
/
read-csv.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
'use strict'
const {readable: isReadable} = require('is-stream')
const {createReadStream} = require('fs')
const {pipeline} = require('stream')
const stripBomStream = require('strip-bom-stream')
const parseCsv = require('csv-parser')
const readCsv = async (path) => {
const isPathStream = isReadable(path)
if (typeof path !== 'string' && !isPathStream) {
throw new Error('path must be a string or a Readable stream')
}
const src = isPathStream ? path : createReadStream(path)
if (!isPathStream) {
// When consuming an fs.createReadStream readable stream of a non-
// existent file via `for await`, it only emits the `ENOENT` error at
// the first iteration. We want to fail right away though, so we listen
// for `readable` & `error` here.
// This sets the stream to flowing/resumed mode, but since we pipe it
// into another stream right after, that's fine.
// see also https://nodejs.org/docs/latest-v14.x/api/stream.html#stream_two_reading_modes
await new Promise((resolve, reject) => {
const onError = (err) => {
reject(err)
src.removeListener('error', onError)
src.removeListener('readable', onReadable)
}
const onReadable = () => {
resolve()
src.removeListener('error', onError)
src.removeListener('readable', onReadable)
}
src.on('error', onError)
src.on('readable', onReadable)
})
}
return pipeline(
src,
stripBomStream(),
parseCsv(),
() => {}, // no-op cb
)
}
module.exports = readCsv