Task
I need to make an app that reads a CSV file, transforms its data and then outputs it as another CSV file.
The input has the following format:
13:25:37 up 19 days, 21:35, 4 users, load average: 0.02, 0.02, 0.00
13:25:38 up 19 days, 21:35, 4 users, load average: 0.02, 0.02, 0.00
... so on
For those of you who are UNIX fans, you will recognise this as the output from the console command uptime
.
The output format I want is the following:
RowNum, Avg Load
1,0.02
2,0.02
Where the first column is the row number in the CSV and the second is the number part of load average: 0.02.
All other columns are to be ignored.
Problem
Trying to do this as functionally as I can, I decided to use ramda.
This has been ... a challenge, to say the least. Right now, my code has several structural issues, but I want to focus on the main
function, which is not working. Every time I execute my code I get the error:
index.js:54
.then( () => console.log("Done!") )
^
TypeError: main(...).then is not a function
Which is confusing because in both functions I pass to R.ifElse
I return a Promise.
Code
const fs = require("fs");
const csvReader = require("csvreader");
const R = require("ramda");
const isString = require("lodash.isstring");
const { promisify } = require("util");
const argv = require("minimist")(process.argv.slice(2));
const appedFileAsync = promisify( fs.appendFile );
const createProcessData = () => {
const stringifyArray = array => `${array.toString()}\n`;
const write = str => fs.appendFileSync( argv.outputFile, str );
const getAvg = R.pipe(
R.replace("load average:", ""),
R.trim
);
let elapsedTime = 1;
const transform = list => [ elapsedTime++, getAvg ( R.nth( 3, list ) ) ];
return R.pipe(
transform,
stringifyArray,
write
);
};
const printHelp = () => {
console.log(`
=== MAN HELP ===
Usage: npm start -- --inputFile input.csv --outputFile output.csv
--inputFile: location of an input file in CSV format
--outputFile: location of an output file to append the new information to.
If this file does not exist, it will be created.
`);
return Promise.resolve();
};
const execute = () => appedFileAsync( argv.outputFile, "Time, Avg Load\n" )
.then( ( ) => csvReader.read( argv.inputFile, createProcessData() ) );
const main = () => {
const isInvalidFileName = R.anyPass( [ R.isNil, R.isEmpty, R.pipe ( isString, R.not ) ] );
const hasInvalidArgs = R.either( isInvalidFileName( argv.inputFile ), isInvalidFileName( argv.outputFile ) );
return R.ifElse(
hasInvalidArgs,
printHelp,
execute
);
};
main()
.then( () => console.log("Done!") )
.catch( console.error );
Question
- What is wrong with my code ?