From 4300f14d79ab8b81100995caa160a7ec901c58e0 Mon Sep 17 00:00:00 2001 From: Naz Date: Thu, 13 Oct 2022 12:39:57 +0800 Subject: [PATCH] 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 --- ghost/members-csv/lib/parse.js | 12 ++++-------- ghost/members-csv/test/parse.test.js | 22 ++++++++++++++++++++-- ghost/members-importer/lib/importer.js | 5 ++++- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/ghost/members-csv/lib/parse.js b/ghost/members-csv/lib/parse.js index 8aeb3bbd57..3ef8d75977 100644 --- a/ghost/members-csv/lib/parse.js +++ b/ghost/members-csv/lib/parse.js @@ -6,23 +6,19 @@ const fs = require('fs-extra'); /** * * @param {string} path - The path to the CSV to prepare - * @param {Object.} mapping - An object whose keys are headers in the input CSV and values are the header to replace it with + * @param {Object.} headerMapping - An object whose keys are headers in the input CSV and values are the header to replace it with * @param {Array} [defaultLabels] - A list of labels to apply to every parsed member row * @returns */ -module.exports = (path, mapping, defaultLabels = []) => { - const inputMapping = Object.assign({}, mapping, { - subscribed_to_emails: 'subscribed' - }); - +module.exports = (path, headerMapping = {}, defaultLabels = []) => { return new Promise(function (resolve, reject) { const csvFileStream = fs.createReadStream(path); const csvParserStream = papaparse.parse(papaparse.NODE_STREAM_INPUT, { header: true, transformHeader(_header) { let header = _header; - if (inputMapping && Reflect.has(inputMapping, _header)) { - header = inputMapping[_header]; + if (headerMapping && Reflect.has(headerMapping, _header)) { + header = headerMapping[_header]; } return header; diff --git a/ghost/members-csv/test/parse.test.js b/ghost/members-csv/test/parse.test.js index a6464e0cf9..392063747e 100644 --- a/ghost/members-csv/test/parse.test.js +++ b/ghost/members-csv/test/parse.test.js @@ -124,9 +124,13 @@ describe('parse', function () { 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({ - filePath: csvPath + 'subscribed-to-emails-header.csv' + filePath: csvPath + 'subscribed-to-emails-header.csv', + mapping }); assert.ok(result); @@ -137,4 +141,18 @@ describe('parse', function () { assert.equal(result[1].email, 'test@example.com'); 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); + }); }); diff --git a/ghost/members-importer/lib/importer.js b/ghost/members-importer/lib/importer.js index 60b6b1dc17..18c596554d 100644 --- a/ghost/members-importer/lib/importer.js +++ b/ghost/members-importer/lib/importer.js @@ -88,7 +88,10 @@ module.exports = class MembersCSVImporter { 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 numberOfBatches = Math.ceil(rows.length / batchSize); const mappedCSV = membersCSV.unparse(rows, columns);