Removed hidden row mapping in csv parser

refs https://github.com/TryGhost/Toolbox/issues/430
refs https://github.com/TryGhost/Ghost/issues/14882

- Having an explicit mappings passed into the members CSV parser makes it easier to control and understand the transforms for package clients
- Eventually the parser will receive a strict map with the fields it should parse - skipping all unknown & unmapped fields
This commit is contained in:
Naz 2022-10-13 12:39:57 +08:00
parent 971a562b46
commit 4300f14d79
No known key found for this signature in database
3 changed files with 28 additions and 11 deletions

View File

@ -6,23 +6,19 @@ const fs = require('fs-extra');
/** /**
* *
* @param {string} path - The path to the CSV to prepare * @param {string} path - The path to the CSV to prepare
* @param {Object.<string, string>} mapping - An object whose keys are headers in the input CSV and values are the header to replace it with * @param {Object.<string, string>} headerMapping - An object whose keys are headers in the input CSV and values are the header to replace it with
* @param {Array<string>} [defaultLabels] - A list of labels to apply to every parsed member row * @param {Array<string>} [defaultLabels] - A list of labels to apply to every parsed member row
* @returns * @returns
*/ */
module.exports = (path, mapping, defaultLabels = []) => { module.exports = (path, headerMapping = {}, defaultLabels = []) => {
const inputMapping = Object.assign({}, mapping, {
subscribed_to_emails: 'subscribed'
});
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
const csvFileStream = fs.createReadStream(path); const csvFileStream = fs.createReadStream(path);
const csvParserStream = papaparse.parse(papaparse.NODE_STREAM_INPUT, { const csvParserStream = papaparse.parse(papaparse.NODE_STREAM_INPUT, {
header: true, header: true,
transformHeader(_header) { transformHeader(_header) {
let header = _header; let header = _header;
if (inputMapping && Reflect.has(inputMapping, _header)) { if (headerMapping && Reflect.has(headerMapping, _header)) {
header = inputMapping[_header]; header = headerMapping[_header];
} }
return header; return header;

View File

@ -124,9 +124,13 @@ describe('parse', function () {
should.equal(result[1].name, null); should.equal(result[1].name, null);
}); });
it('read csv: transforms "subscribed_to_emails" column to "subscribed" property', async function () { it('read csv: transforms "subscribed_to_emails" column to "subscribed" property when the mapping is passed in', async function () {
const mapping = {
subscribed_to_emails: 'subscribed'
};
const result = await readCSV({ const result = await readCSV({
filePath: csvPath + 'subscribed-to-emails-header.csv' filePath: csvPath + 'subscribed-to-emails-header.csv',
mapping
}); });
assert.ok(result); assert.ok(result);
@ -137,4 +141,18 @@ describe('parse', function () {
assert.equal(result[1].email, 'test@example.com'); assert.equal(result[1].email, 'test@example.com');
assert.equal(result[1].subscribed, false); assert.equal(result[1].subscribed, false);
}); });
it('read csv: DOES NOT transforms "subscribed_to_emails" column to "subscribed" property when the WITHOUT mapping', async function () {
const result = await readCSV({
filePath: csvPath + 'subscribed-to-emails-header.csv'
});
assert.ok(result);
assert.equal(result.length, 2);
assert.equal(result[0].email, 'jbloggs@example.com');
assert.ok(result[0].subscribed_to_emails);
assert.equal(result[1].email, 'test@example.com');
assert.equal(result[1].subscribed_to_emails, false);
});
}); });

View File

@ -88,7 +88,10 @@ module.exports = class MembersCSVImporter {
throw new errors.DataImportError({message: tpl(messages.filenameCollision)}); throw new errors.DataImportError({message: tpl(messages.filenameCollision)});
} }
const rows = await membersCSV.parse(inputFilePath, headerMapping, defaultLabels); const inputMapping = Object.assign({}, headerMapping, {
subscribed_to_emails: 'subscribed'
});
const rows = await membersCSV.parse(inputFilePath, inputMapping, defaultLabels);
const columns = Object.keys(rows[0]); const columns = Object.keys(rows[0]);
const numberOfBatches = Math.ceil(rows.length / batchSize); const numberOfBatches = Math.ceil(rows.length / batchSize);
const mappedCSV = membersCSV.unparse(rows, columns); const mappedCSV = membersCSV.unparse(rows, columns);