1 | 'use strict'
|
2 |
|
3 | const { writeFile } = require('fs/promises')
|
4 |
|
5 | const append = (fileName, line) => writeFile(fileName, line + '\n', { flag: 'a+' })
|
6 | const escape = value => {
|
7 | const stringValue = value.toString()
|
8 | if (stringValue.match(/\r|\n|\t|"/)) {
|
9 | return JSON.stringify(stringValue)
|
10 | }
|
11 | return stringValue
|
12 | }
|
13 |
|
14 | class CsvWriter {
|
15 | #fileName
|
16 | #ready
|
17 | #fields
|
18 |
|
19 | constructor (fileName) {
|
20 | this.#fileName = fileName
|
21 | this.#ready = Promise.resolve()
|
22 | this.#fields = []
|
23 | }
|
24 |
|
25 | get ready () {
|
26 | return this.#ready
|
27 | }
|
28 |
|
29 | append (records) {
|
30 | if (!Array.isArray(records)) {
|
31 | records = [records]
|
32 | }
|
33 | if (this.#fields.length === 0) {
|
34 | this.#fields = Object.keys(records[0]).filter(name => name !== 'timestamp')
|
35 | this.#ready = this.#ready.then(() => append(this.#fileName, `timestamp\t${this.#fields.join('\t')}`))
|
36 | }
|
37 | const lines = records.map(record => {
|
38 | const { timestamp = Date.now() } = record
|
39 | return [
|
40 | timestamp,
|
41 | ...this.#fields.map(name => escape(record[name]))
|
42 | ].join('\t')
|
43 | }).join('\n')
|
44 | this.#ready = this.#ready.then(() => append(this.#fileName, lines))
|
45 | }
|
46 | }
|
47 |
|
48 | module.exports = {
|
49 | buildCsvWriter (fileName) {
|
50 | return new CsvWriter(fileName)
|
51 | }
|
52 | }
|