forked from iwsllc/json-csv
-
Notifications
You must be signed in to change notification settings - Fork 1
/
exporter.js
114 lines (99 loc) · 2.81 KB
/
exporter.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
var es = require('event-stream');
var _ = require("lodash")
var concat = require('concat-stream')
var exporter = function(options) {
this.options = options || {}
this.fieldSeparator = this.options.fieldSeparator || ',';
}
exporter.prototype.csvBuffered = function(data, options, done) {
if (!data) throw new Error("No data provided.")
if(typeof options == 'function')
{
done = options
options = {}
}
es.readArray(data)
.pipe(this.csv(options))
.pipe(concat(function(buffer) {
done(null, buffer)
}))
}
exporter.prototype.csv = function(options) {
var writtenHeader = false
this.options = options || {}
this.fieldSeparator = this.options.fieldSeparator || ',';
var self = this;
return es.through(function write(data) {
if (!writtenHeader && !self.options.skipHeader)
{
this.emit('data', self.getHeaderRow())
writtenHeader = true
}
this.emit('data', self.getBodyRow(data))
})
}
exporter.prototype.prepValue = function(arg, forceQuoted) {
var quoted = forceQuoted || arg.indexOf('"') >= 0 || arg.indexOf(this.fieldSeparator) >= 0 || arg.indexOf('\n') >= 0
var result = arg.replace(/\"/g,'""')
if (quoted)
result = '"' + result + '"'
return result
}
exporter.prototype.getHeaderRow = function() {
var self = this
var header = _.reduce(self.options.fields, function(line, field) {
var label = field.label || field.field
if (line !== ' ') {
line += self.fieldSeparator
}
line += self.prepValue(label)
return line
}, ' ')
if (header.trim()) {
header += '\r\n'
}
return header
}
exporter.prototype.getBodyRow = function(data) {
var self = this
var row = _.reduce(this.options.fields, function(line, field) {
if (line !== ' ') {
line += self.fieldSeparator
}
var val = self.getValue(data, field.name)
if (field.filter) {
val = field.filter(val)
}
if (typeof val !== 'undefined' && val !== null) {
var quoted = typeof field.quoted !== 'undefined' && field.quoted
line += self.prepValue(val.toString(), quoted)
}
return line
}, ' ', self)
if (row.trim()) {
row += '\r\n'
}
return row
}
exporter.prototype.getValue = function(data, arg) {
var args = arg.split('.')
if (args.length > 0)
return this.getValueIx(data, args, 0)
return ""
}
exporter.prototype.getValueIx = function(data, args, ix) {
if (!data)
return ''
//for filtered fields using the whole row as a source.
//`this` is a keyword here; hoping not to conflict with existing fields.
if (args[0] === "this")
return data
var val = data[args[ix]]
if (typeof val === 'undefined')
return ''
//walk the dot-notation recursively to get the remaining values.
if ((args.length-1) > ix)
return this.getValueIx(val, args, ix+1);
return val;
}
module.exports = exporter