2020-10-02 17:16:06 +02:00
|
|
|
const csv = require("csvtojson")
|
2021-05-18 23:14:27 +02:00
|
|
|
const { FieldTypes } = require("../constants")
|
2020-10-02 17:16:06 +02:00
|
|
|
|
|
|
|
const VALIDATORS = {
|
2021-05-18 23:14:27 +02:00
|
|
|
[FieldTypes.STRING]: () => true,
|
|
|
|
[FieldTypes.OPTIONS]: () => true,
|
|
|
|
[FieldTypes.NUMBER]: attribute => !isNaN(Number(attribute)),
|
|
|
|
[FieldTypes.DATETIME]: attribute => !isNaN(new Date(attribute).getTime()),
|
2020-10-02 17:16:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const PARSERS = {
|
2021-05-18 23:14:27 +02:00
|
|
|
[FieldTypes.NUMBER]: attribute => Number(attribute),
|
|
|
|
[FieldTypes.DATETIME]: attribute => new Date(attribute).toISOString(),
|
2020-10-02 17:16:06 +02:00
|
|
|
}
|
|
|
|
|
2020-10-19 20:24:05 +02:00
|
|
|
function parse(csvString, parsers) {
|
|
|
|
const result = csv().fromString(csvString)
|
2020-10-02 17:16:06 +02:00
|
|
|
|
|
|
|
const schema = {}
|
|
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
2021-05-04 12:32:22 +02:00
|
|
|
result.on("header", headers => {
|
2020-10-02 17:16:06 +02:00
|
|
|
for (let header of headers) {
|
|
|
|
schema[header] = {
|
|
|
|
type: parsers[header] ? parsers[header].type : "string",
|
|
|
|
success: true,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
2021-05-04 12:32:22 +02:00
|
|
|
result.subscribe(row => {
|
2020-10-05 20:21:51 +02:00
|
|
|
// For each CSV row parse all the columns that need parsed
|
2020-10-02 17:16:06 +02:00
|
|
|
for (let key in parsers) {
|
2020-10-05 20:21:51 +02:00
|
|
|
if (!schema[key] || schema[key].success) {
|
|
|
|
// get the validator for the column type
|
|
|
|
const validator = VALIDATORS[parsers[key].type]
|
2020-10-02 17:16:06 +02:00
|
|
|
|
2020-10-05 20:21:51 +02:00
|
|
|
try {
|
|
|
|
// allow null/undefined values
|
|
|
|
schema[key].success = !row[key] || validator(row[key])
|
|
|
|
} catch (err) {
|
|
|
|
schema[key].success = false
|
|
|
|
}
|
2020-10-02 17:16:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
2021-05-04 12:32:22 +02:00
|
|
|
result.on("done", error => {
|
2020-10-02 17:16:06 +02:00
|
|
|
if (error) {
|
|
|
|
console.error(error)
|
|
|
|
reject(error)
|
|
|
|
}
|
|
|
|
|
|
|
|
resolve(schema)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-10-19 20:24:05 +02:00
|
|
|
async function transform({ schema, csvString }) {
|
2020-10-02 17:16:06 +02:00
|
|
|
const colParser = {}
|
|
|
|
|
|
|
|
for (let key in schema) {
|
2020-10-05 11:51:58 +02:00
|
|
|
colParser[key] = PARSERS[schema[key].type] || schema[key].type
|
2020-10-02 17:16:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2020-10-19 20:24:05 +02:00
|
|
|
const json = await csv({ colParser }).fromString(csvString)
|
2020-10-02 17:16:06 +02:00
|
|
|
return json
|
|
|
|
} catch (err) {
|
|
|
|
console.error(`Error transforming CSV to JSON for data import`, err)
|
2020-10-05 12:48:13 +02:00
|
|
|
throw err
|
2020-10-02 17:16:06 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = {
|
|
|
|
parse,
|
|
|
|
transform,
|
|
|
|
}
|