2020-10-27 13:44:06 +03:00
|
|
|
const pump = require('pump');
|
2020-07-08 10:39:37 +03:00
|
|
|
const papaparse = require('papaparse');
|
2020-06-19 09:24:51 +03:00
|
|
|
const fs = require('fs-extra');
|
|
|
|
|
2022-10-13 07:16:35 +03:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @param {string} path - The path to the CSV to prepare
|
2022-10-13 07:39:57 +03:00
|
|
|
* @param {Object.<string, string>} headerMapping - An object whose keys are headers in the input CSV and values are the header to replace it with
|
2022-10-13 07:16:35 +03:00
|
|
|
* @param {Array<string>} [defaultLabels] - A list of labels to apply to every parsed member row
|
|
|
|
* @returns
|
|
|
|
*/
|
2022-10-18 08:05:31 +03:00
|
|
|
module.exports = (path, headerMapping, defaultLabels = []) => {
|
2020-10-27 13:44:06 +03:00
|
|
|
return new Promise(function (resolve, reject) {
|
|
|
|
const csvFileStream = fs.createReadStream(path);
|
|
|
|
const csvParserStream = papaparse.parse(papaparse.NODE_STREAM_INPUT, {
|
|
|
|
header: true,
|
|
|
|
transformHeader(_header) {
|
2023-06-23 09:31:16 +03:00
|
|
|
const cleanHeader = _header.replace(papaparse.BYTE_ORDER_MARK, ''); //Removing BOM characters for Unicode-based encodings
|
|
|
|
if (!headerMapping || !Reflect.has(headerMapping, cleanHeader)) {
|
2022-10-18 08:05:31 +03:00
|
|
|
return undefined;
|
2020-10-27 13:44:06 +03:00
|
|
|
}
|
2023-06-23 09:31:16 +03:00
|
|
|
return headerMapping[cleanHeader];
|
2020-10-27 13:44:06 +03:00
|
|
|
},
|
|
|
|
transform(value, header) {
|
|
|
|
if (header === 'labels') {
|
|
|
|
if (value && typeof value === 'string') {
|
|
|
|
return value.split(',').map(name => ({name}));
|
|
|
|
}
|
2020-06-30 16:27:11 +03:00
|
|
|
}
|
2020-06-19 09:24:51 +03:00
|
|
|
|
2020-12-04 15:39:58 +03:00
|
|
|
if (header === 'subscribed') {
|
2020-10-27 13:44:06 +03:00
|
|
|
return value.toLowerCase() !== 'false';
|
|
|
|
}
|
2020-06-19 09:24:51 +03:00
|
|
|
|
2020-10-27 13:44:06 +03:00
|
|
|
if (header === 'complimentary_plan') {
|
|
|
|
return value.toLowerCase() === 'true';
|
|
|
|
}
|
2020-08-17 08:57:49 +03:00
|
|
|
|
2020-10-27 13:44:06 +03:00
|
|
|
if (value === '') {
|
|
|
|
return null;
|
2020-08-17 08:57:49 +03:00
|
|
|
}
|
2020-06-30 16:27:11 +03:00
|
|
|
|
2020-10-27 13:44:06 +03:00
|
|
|
if (value === 'undefined') {
|
|
|
|
return null;
|
2020-06-19 09:24:51 +03:00
|
|
|
}
|
2020-06-30 16:27:11 +03:00
|
|
|
|
2020-10-27 13:44:06 +03:00
|
|
|
if (value.toLowerCase() === 'false') {
|
|
|
|
return false;
|
|
|
|
}
|
2020-06-19 08:58:33 +03:00
|
|
|
|
2020-10-27 13:44:06 +03:00
|
|
|
if (value.toLowerCase() === 'true') {
|
|
|
|
return true;
|
|
|
|
}
|
2020-06-19 08:58:33 +03:00
|
|
|
|
2020-10-27 13:44:06 +03:00
|
|
|
return value;
|
|
|
|
}
|
|
|
|
});
|
2020-06-30 16:27:11 +03:00
|
|
|
|
2020-10-27 13:44:06 +03:00
|
|
|
const rows = [];
|
|
|
|
const parsedCSVStream = pump(csvFileStream, csvParserStream, (err) => {
|
|
|
|
if (err) {
|
|
|
|
return reject(err);
|
|
|
|
}
|
|
|
|
resolve(rows);
|
|
|
|
});
|
2020-06-30 16:27:11 +03:00
|
|
|
|
2020-10-27 13:44:06 +03:00
|
|
|
parsedCSVStream.on('data', (row) => {
|
2022-10-18 08:05:31 +03:00
|
|
|
// unmapped columns end up being assigned to 'undefined' property
|
|
|
|
// in the transformHeader stage, those should be removed completely
|
|
|
|
if (Reflect.has(row, 'undefined')) {
|
|
|
|
delete row.undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
// skip a rows with no data
|
|
|
|
if (!Object.keys(row).length){
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-10-27 13:44:06 +03:00
|
|
|
if (row.labels) {
|
|
|
|
row.labels = row.labels.concat(defaultLabels);
|
|
|
|
} else {
|
|
|
|
row.labels = defaultLabels;
|
|
|
|
}
|
2022-10-18 08:05:31 +03:00
|
|
|
|
2020-10-27 13:44:06 +03:00
|
|
|
rows.push(row);
|
|
|
|
});
|
|
|
|
});
|
2020-06-19 08:58:33 +03:00
|
|
|
};
|
|
|
|
|