2020-06-19 09:24:51 +03:00
|
|
|
const Promise = require('bluebird');
|
2020-07-08 10:39:37 +03:00
|
|
|
const papaparse = require('papaparse');
|
2020-06-19 09:24:51 +03:00
|
|
|
const _ = require('lodash');
|
|
|
|
const fs = require('fs-extra');
|
|
|
|
|
2020-06-30 16:27:11 +03:00
|
|
|
const mapRowsWithRegexes = (rows, columnsToExtract) => {
|
2020-06-19 09:24:51 +03:00
|
|
|
let results = [];
|
2020-06-30 16:27:11 +03:00
|
|
|
const columnMap = {};
|
|
|
|
// If CSV is single column - return all values including header
|
|
|
|
const headers = _.keys(rows[0]);
|
|
|
|
|
|
|
|
if (columnsToExtract.length === 1 && headers.length === 1) {
|
|
|
|
results = _.map(rows, function (value) {
|
|
|
|
let result = {};
|
|
|
|
result[columnsToExtract[0].name] = value[headers[0]];
|
|
|
|
return result;
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
// If there are multiple columns in csv file
|
|
|
|
// try to match headers using lookup value
|
|
|
|
_.map(columnsToExtract, function findMatches(column) {
|
|
|
|
_.each(headers, function checkheader(header) {
|
|
|
|
if (column.lookup.test(header)) {
|
|
|
|
columnMap[column.name] = header;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
results = _.map(rows, function evaluateRow(row) {
|
|
|
|
const result = {};
|
|
|
|
_.each(columnMap, function returnMatches(value, key) {
|
|
|
|
result[key] = row[value];
|
|
|
|
});
|
|
|
|
return result;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return results;
|
|
|
|
};
|
|
|
|
|
|
|
|
const mapRowsWithMappings = (rows, mapping) => {
|
|
|
|
const results = rows.map((row) => {
|
|
|
|
for (const key in mapping) {
|
|
|
|
row[key] = row[mapping[key]];
|
|
|
|
|
|
|
|
if (key !== mapping[key]) {
|
|
|
|
delete row[mapping[key]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return row;
|
|
|
|
});
|
|
|
|
|
|
|
|
return results;
|
|
|
|
};
|
|
|
|
|
|
|
|
const readCSV = ({path, columnsToExtract, mapping}) => {
|
2020-06-19 09:24:51 +03:00
|
|
|
const rows = [];
|
|
|
|
|
|
|
|
return new Promise(function (resolve, reject) {
|
2020-06-30 16:27:11 +03:00
|
|
|
const readFile = fs.createReadStream(path);
|
2020-06-19 09:24:51 +03:00
|
|
|
|
|
|
|
readFile.on('err', function (err) {
|
|
|
|
reject(err);
|
|
|
|
})
|
2020-07-08 10:39:37 +03:00
|
|
|
.pipe(papaparse.parse(papaparse.NODE_STREAM_INPUT, {
|
|
|
|
header: true
|
|
|
|
}))
|
2020-06-19 09:24:51 +03:00
|
|
|
.on('data', function (row) {
|
|
|
|
rows.push(row);
|
|
|
|
})
|
|
|
|
.on('end', function () {
|
2020-06-30 16:27:11 +03:00
|
|
|
let results = [];
|
|
|
|
|
|
|
|
if (columnsToExtract) {
|
|
|
|
results = mapRowsWithRegexes(rows, columnsToExtract);
|
2020-06-19 09:24:51 +03:00
|
|
|
} else {
|
2020-06-30 16:27:11 +03:00
|
|
|
results = mapRowsWithMappings(rows, mapping);
|
2020-06-19 09:24:51 +03:00
|
|
|
}
|
2020-06-30 16:27:11 +03:00
|
|
|
|
2020-06-19 09:24:51 +03:00
|
|
|
resolve(results);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
2020-06-19 08:58:33 +03:00
|
|
|
|
2020-06-30 16:27:11 +03:00
|
|
|
const parse = async (filePath, mapping) => {
|
2020-06-19 08:58:33 +03:00
|
|
|
const columnsToExtract = [{
|
|
|
|
name: 'email',
|
|
|
|
lookup: /^email/i
|
|
|
|
}, {
|
|
|
|
name: 'name',
|
|
|
|
lookup: /name/i
|
|
|
|
}, {
|
|
|
|
name: 'note',
|
|
|
|
lookup: /note/i
|
|
|
|
}, {
|
|
|
|
name: 'subscribed_to_emails',
|
|
|
|
lookup: /subscribed_to_emails/i
|
|
|
|
}, {
|
|
|
|
name: 'stripe_customer_id',
|
|
|
|
lookup: /stripe_customer_id/i
|
|
|
|
}, {
|
|
|
|
name: 'complimentary_plan',
|
|
|
|
lookup: /complimentary_plan/i
|
|
|
|
}, {
|
|
|
|
name: 'labels',
|
|
|
|
lookup: /labels/i
|
|
|
|
}, {
|
|
|
|
name: 'created_at',
|
|
|
|
lookup: /created_at/i
|
|
|
|
}];
|
|
|
|
|
2020-06-30 16:27:11 +03:00
|
|
|
const options = {
|
|
|
|
path: filePath
|
|
|
|
};
|
|
|
|
|
|
|
|
if (mapping) {
|
|
|
|
options.mapping = mapping;
|
|
|
|
} else {
|
|
|
|
options.columnsToExtract = columnsToExtract;
|
|
|
|
}
|
|
|
|
|
|
|
|
return await readCSV(options);
|
2020-06-19 08:58:33 +03:00
|
|
|
};
|
|
|
|
|
2020-06-19 10:23:26 +03:00
|
|
|
module.exports = parse;
|
2020-06-19 09:24:51 +03:00
|
|
|
module.exports.readCSV = readCSV;
|