UNPKG

@geocodeearth/ge

Version:

Geocode Earth command-line tools

138 lines (123 loc) 3.78 kB
const _ = require('lodash') const fs = require('fs') const Metrics = require('../../../stream/Metrics') const stream = { csv: require('../../../stream/csv'), batch: require('../../../stream/batch'), stats: require('../../../stream/stats') } module.exports = { command: 'csv <file>', describe: 'append geocoded columns to a CSV file', builder: (yargs) => { // mandatory params yargs.positional('file', { type: 'string', describe: 'location of the input CSV file.' }) // optional params yargs.option('param', { alias: 'p', type: 'string', describe: 'Define a parameter.' }) yargs.option('template', { alias: 't', type: 'string', describe: 'Define a template.' }) yargs.option('column', { alias: 'c', type: 'string', describe: 'Define a new column.' }) yargs.option('selector', { alias: 's', type: 'string', describe: 'Define _.get() selector path.' }) yargs.option('endpoint', { type: 'string', default: '/v1/search', describe: 'API endpoint to query.' }) yargs.option('concurrency', { type: 'number', default: 5, describe: 'Maximum queries per-second.' }) yargs.option('discovery', { type: 'boolean', default: true, describe: 'Maximum concurrency will be applied based on your plan limits.' }) yargs.option('force', { alias: 'f', type: 'boolean', default: false, describe: 'Force previously geocoded rows to be refreshed.' }) yargs.option('summary', { type: 'boolean', default: true, describe: 'Print summary statistics.' }) yargs.option('tick', { type: 'boolean', default: false, describe: 'Update summary statistics once per second.' }) }, handler: (argv) => { // record summary statistics const metrics = new Metrics() // trap ctrl+C process.on('SIGINT', () => { if (argv.summary) { metrics.print('error') } process.exit(1) }) fs.createReadStream(argv.file) .pipe(stream.csv.parser()) .pipe(stream.batch.geocoder({ templates: generateTemplates(argv), fields: generateFields(argv), ...argv, metrics })) .pipe(stream.stats(metrics, (argv.summary && argv.tick) ? 1000 : 0)) .pipe(stream.csv.stringifier()) .pipe(process.stdout) } } function generateTemplates (argv) { // report error if user failed to specify any valid pairs if (_.isEmpty(argv.param) || _.isEmpty(argv.template)) { throw new Error('error: you must specify at least one pair of -p (param) and -t (template) flags.') } // cast scalar (single flag specified) values to arrays const p = _.castArray(argv.param) const t = _.castArray(argv.template) // report error if pairs are unbalanced if (_.size(p) !== _.size(t)) { throw new Error('error: you pair every -p (param) flag with a -t (template) flag.') } const mappings = _.zipObject(p, t) if (argv.verbose) { console.error('param templates', mappings) } const templates = _.map(mappings, (template, param) => { // compile template const render = _.template(template) // return req param template function return (req, row) => { req.params[param] = render({ row }) } }) return templates } function generateFields (argv) { // cast scalar (single flag specified) values to arrays const c = _.filter(_.castArray(argv.column), _.size) const s = _.filter(_.castArray(argv.selector), _.size) // report error if pairs are unbalanced if (_.size(c) !== _.size(s)) { throw new Error('error: you pair every -c (column) flag with a -s (selector) flag.') } return _.zipObject(c, s) }