-
Notifications
You must be signed in to change notification settings - Fork 37
/
Copy pathindex.js
99 lines (75 loc) · 2.46 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
var stream = require('stream')
var util = require('util')
var gen = require('generate-object-property')
var CsvWriteStream = function(opts) {
if (!opts) opts = {}
stream.Transform.call(this, {objectMode:true, highWaterMark:16})
this.sendHeaders = opts.sendHeaders !== false
this.headers = opts.headers || null
this.separator = opts.separator || opts.seperator || ','
this.newline = opts.newline || '\n'
this._objRow = null
this._arrRow = null
this._first = true
this._destroyed = false
}
util.inherits(CsvWriteStream, stream.Transform)
CsvWriteStream.prototype._compile = function(headers) {
var newline = this.newline
var sep = this.separator
var str = 'function toRow(obj) {\n'
if (!headers.length) str += '""'
headers = headers.map(function(prop, i) {
str += 'var a'+i+' = '+prop+' == null ? "" : '+prop+'\n'
return 'a'+i
})
for (var i = 0; i < headers.length; i += 500) { // do not overflowi the callstack on lots of cols
var part = headers.length < 500 ? headers : headers.slice(i, i + 500)
str += i ? 'result += "'+sep+'" + ' : 'var result = '
part.forEach(function(prop, j) {
str += (j ? '+"'+sep+'"+' : '') + '(/['+sep+'\\r\\n"]/.test('+prop+') ? esc('+prop+'+"") : '+prop+')'
})
str += '\n'
}
str += 'return result +'+JSON.stringify(newline)+'\n}'
return new Function('esc', 'return '+str)(esc)
}
CsvWriteStream.prototype._transform = function(row, enc, cb) {
var isArray = Array.isArray(row)
if (!isArray && !this.headers) this.headers = Object.keys(row)
if (this._first && this.headers) {
this._first = false
var objProps = []
var arrProps = []
var heads = []
for (var i = 0; i < this.headers.length; i++) {
arrProps.push('obj['+i+']')
objProps.push(gen('obj', this.headers[i]))
}
this._objRow = this._compile(objProps)
this._arrRow = this._compile(arrProps)
if (this.sendHeaders) this.push(this._arrRow(this.headers))
}
if (isArray) {
if (!this.headers) return cb(new Error('no headers specified'))
this.push(this._arrRow(row))
} else {
this.push(this._objRow(row))
}
cb()
}
CsvWriteStream.prototype.destroy = function (err) {
if (this._destroyed) return
this._destroyed = true
var self = this
process.nextTick(function () {
if (err) self.emit('error', err)
self.emit('close')
})
}
module.exports = function(opts) {
return new CsvWriteStream(opts)
}
function esc(cell) {
return '"'+cell.replace(/"/g, '""')+'"'
}