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
115
116
117
118
119
120
121
122
123
124
125
126
127 |
1×
1×
1×
1620×
1×
1440×
1440×
1×
229×
229×
180×
180×
180×
180×
180×
180×
180×
180×
180×
229×
229×
229×
225×
1×
147×
42×
42×
42×
147×
147×
2×
145×
82×
25×
25×
25×
82×
82×
2×
80×
1×
1×
1× | 'use strict';
var json2Csv = require('./json-2-csv'), // Require our json-2-csv code
csv2Json = require('./csv-2-json'), // Require our csv-2-json code
constants = require('./constants.json'), // Require in constants
docPath = require('doc-path'),
promise = require('bluebird'),
_ = require('underscore');
/**
* Default options
*/
var defaultOptions = constants.DefaultOptions;
var isDefined = function (val) {
return !_.isUndefined(val);
};
var copyOption = function (options, lowercasePath, uppercasePath) {
var lowerCaseValue = docPath.evaluatePath(options, lowercasePath);
Iif (isDefined(lowerCaseValue)) {
docPath.setPath(options, uppercasePath, lowerCaseValue);
}
};
/**
* Build the options to be passed to the appropriate function
* If a user does not provide custom options, then we use our default
* If options are provided, then we set each valid key that was passed
*/
var buildOptions = function (opts, cb) {
// PREVIOUS VERSION SUPPORT (so that future versions are backwards compatible)
// Issue #26: opts.EOL should be opts.DELIMITER.EOL -- this will move the option & provide backwards compatibility
if (docPath.evaluatePath(opts, 'EOL')) { docPath.setPath(opts, 'DELIMITER.EOL', opts.EOL); }
// #62: Allow for lower case option names
if (opts) {
copyOption(opts, 'prependHeader', 'PREPEND_HEADER');
copyOption(opts, 'trimHeaderFields', 'TRIM_HEADER_FIELDS');
copyOption(opts, 'trimFieldValues', 'TRIM_FIELD_VALUES');
copyOption(opts, 'sortHeader', 'SORT_HEADER');
copyOption(opts, 'parseCsvNumbers', 'PARSE_CSV_NUMBERS');
copyOption(opts, 'keys', 'KEYS');
copyOption(opts, 'checkSchemaDifferences', 'CHECK_SCHEMA_DIFFERENCES');
copyOption(opts, 'emptyFieldValue', 'EMPTY_FIELD_VALUE');
Iif (isDefined(opts.delimiter)) {
copyOption(opts, 'delimiter.field', 'DELIMITER.FIELD');
copyOption(opts, 'delimiter.array', 'DELIMITER.ARRAY');
copyOption(opts, 'delimiter.wrap', 'DELIMITER.WRAP');
copyOption(opts, 'delimiter.eol', 'DELIMITER.EOL');
}
}
opts = _.defaults(opts || {}, defaultOptions);
// Note: _.defaults does a shallow default, we need to deep copy the DELIMITER object
opts.DELIMITER = _.defaults(opts.DELIMITER || {}, defaultOptions.DELIMITER);
// If the delimiter fields are the same, report an error to the caller
if (opts.DELIMITER.FIELD === opts.DELIMITER.ARRAY) { return cb(new Error(constants.Errors.delimitersMustDiffer)); }
// Otherwise, send the options back
return cb(null, opts);
};
// Export the following functions that will be client accessible
var exports = {
/**
* Client accessible json2csv function
* Takes an array of JSON documents to be converted, a callback that will be called with (err, csv)
* after processing is complete, and optional options
* @param array Object[] data to be converted
* @param callback Function callback
* @param opts Object options object
*/
json2csv: function (array, callback, opts) {
// If this was promisified (callback and opts are swapped) then fix the argument order.
if (_.isObject(callback) && !_.isFunction(callback)) {
var func = opts;
opts = callback;
callback = func;
}
buildOptions(opts, function (err, options) { // Build the options
if (err) {
return callback(err);
} else {
json2Csv.json2csv(options, array, callback); // Call our internal json2csv function
}
});
},
/**
* Client accessible csv2json function
* Takes a string of CSV to be converted to a JSON document array, a callback that will be called
* with (err, json) after processing is complete, and optional options
* @param csv
* @param callback
* @param opts
*/
csv2json: function (csv, callback, opts) {
// If this was promisified (callback and opts are swapped) then fix the argument order.
if (_.isObject(callback) && !_.isFunction(callback)) {
var func = opts;
opts = callback;
callback = func;
}
buildOptions(opts, function (err, options) { // Build the options
if (err) {
return callback(err);
} else {
csv2Json.csv2json(options, csv, callback); // Call our internal csv2json function
}
});
}
};
// Promisified json2csv:
exports.json2csvPromisified = promise.promisify(exports.json2csv);
// Promisified csv2json:
exports.csv2jsonPromisified = promise.promisify(exports.csv2json);
module.exports = exports; |