godkimchi-read-line
Version:
kimchi style's read line module
68 lines (55 loc) • 1.89 kB
JavaScript
const util = require('util')
const csv = require('csv')
const iconv = require('iconv-lite')
const ReadLines = require('n-readlines')
const DEFAULT_OPTION = { skipHeader: false, encoding: 'utf8', type: 'text', quote: '', delimiter: ',', escape: '"' }
function setupOption (option = {}, yourOption = {}) {
Object.keys(yourOption).forEach(key => {
if (option.hasOwnProperty(key)) {
option[key] = yourOption[key]
}
})
}
module.exports = async function (filePath = String, yourOption = DEFAULT_OPTION, cb = undefined) {
if (typeof arguments[1] === 'function') {
yourOption = DEFAULT_OPTION
cb = arguments[1]
}
const option = Object.assign({}, DEFAULT_OPTION)
setupOption(option, yourOption)
const { quote, delimiter, escape } = option
const lineReader = new ReadLines(filePath)
let skipCallback = false, error, data, line, lineCount = 0
while ((line = lineReader.next()) !== false) {
skipCallback = false
error = data = undefined
try {
if (++lineCount === 1 && option.skipHeader === true) {
skipCallback = true
continue
} else {
line = iconv.decode(line, option.encoding)
data = { line, lineCount }
}
if (option.type === 'csv') {
const [fields] = await util.promisify(csv.parse)(line, { quote, delimiter, escape })
data.fields = fields
}
} catch (e) {
error = e
} finally {
let continueOrNot
if (skipCallback === true || typeof cb !== 'function') {
continueOrNot = true
} else if (cb instanceof (async () => {}).constructor) {
continueOrNot = await cb(error, data)
} else {
continueOrNot = cb(error, data)
}
if (continueOrNot === false) {
break
}
}
}
return { filePath, option, lineCount }
}