RCohen
RCohen

Reputation: 1992

Node.js TypeError: path must be a string or Buffer

I'm writting a command line program which calculates the total price of an order, using info from a CSV file.

Data inside sample.catalog.csv:

P1,5,1000.00
P2,8,250.00
P3,15,125.00
P4,10,250.00
P5,2,2500.00

And the program must run from the command line with the following arguments:

Example: $ CalculateOrder sample.catalog.csv P1 2 P2 4

(P4 6 P10 5 P12 1 are products and quantity available from csv file)

Total: 4151,25

This is what I have at the moment:

var program = require('commander');
const csv = require('csv');
const fs = require('fs');


program
    .version('1.0.0')
    .option('-l, --list [list]', 'list of order prices in sample.catalog.csv')
    .parse(process.argv)

console.log("hello world")
console.log("list of order prices", program.list);


/* 
    To read csv file and print the data to the console:
    [node orderPrice --list input/sample.catalog.csv]
*/

let parse = csv.parse;
let stream = fs.createReadStream(program.list)
    .pipe(parse({ delimiter: ',' }));

var total = 0;
const vat = 23;
const totalWithVat = total * vat;

stream
.on('data', function (data) {
    let product = data[0];
    let quantity = data[1];
    let price = data[2];
    console.log(product, quantity, price);
    calculateOrder = () => {
        if (quantity > 20) {
            stream.destroy(new Error("Quantity exceeds stored amounts"));
        }
        total += price * quantity;
    }
})

.on("finish", function () {
    console.log("Total price:", totalWithVat);
})

.on("error", function (error) {
    console.error("The following error occured:", error);
})

I am having the following error:

λ node orderPrice calculateOrder sample.catalog.csv P1 2 P2 4
hello world
list of order prices undefined
fs.js:636
binding.open(pathModule._makeLong(path),
      ^

TypeError: path must be a string or Buffer
    at Object.fs.open (fs.js:636:11)
    at ReadStream.open (fs.js:1982:6)
    at new ReadStream (fs.js:1969:10)
    at Object.fs.createReadStream (fs.js:1923:10)
    at Object.<anonymous> (E:\order-price\orderPrice.js:31:17)
    at Module._compile (module.js:643:30)
    at Object.Module._extensions..js (module.js:654:10)
    at Module.load (module.js:556:32)
    at tryModuleLoad (module.js:499:12)
    at Function.Module._load (module.js:491:3)

I'm a Node.js newbie and any help is appreciated. Thank you.

Upvotes: 6

Views: 11849

Answers (3)

Shubham
Shubham

Reputation: 1288

Change line

let stream = fs.createReadStream(program.list)

to

let stream = fs.createReadStream(program.argv[some number])

where some number is position at which you mention filename

e.g. run program with following command

node test.js somevar filename

then somenumber = 3

0th param > node
1st param > test.js (file to run)
2nd > somevar
3rd > filename

Another error:

Final code will look like

const csv = require('fast-csv');
const fs = require('fs');

console.log("hello world")
console.log("list of order prices", process.argv[2]);
let required_products=[]
for(var i=3;i<process.argv.length;){
   let temp=[]
   temp.name=process.argv[i++]
   temp.quantity=process.argv[i++]
   required_products.push(temp)
}
/*
    To read csv file and print the data to the console:
    [node orderPrice --list input/sample.catalog.csv]
*/

let stream = fs.createReadStream(process.argv[2]);

var total = 0;
var csvStream = csv()
    .on("data", function(data){
         let product_name = data[0];
         let quantity = data[1];
         let price = data[2];

         required_products.forEach(function(product){

             if(product['name']==product_name){
               if(parseInt(product['quantity'])>parseInt(quantity)){
                 console.log('Quantity required for product '+product['name']+' '+product['quantity']+' is greater than available '+quantity);
                 process.exit(1)
               }else{
                 total += parseInt(price) * parseInt(product['quantity']);
               }
             }
         })
    })
    .on("end", function(){
         console.log("done");
         let totalWithVat = total * (1+ 0.23);
         console.log("Total price:", totalWithVat);
    }).on("error", function (error) {
        console.error("The following error occured:", error);
    })
 stream.pipe(csvStream);

Upvotes: 2

eskawl
eskawl

Reputation: 637

With the following directory structure:

- .. - orderPrices.js - sample.catalog.csv

You can execute node orderPrices.js --list sample.catalog.csv to make it work.

If your CSV file is located else where. You can you path module's path.resolve function to get the CSV file through its relative position in the following manner.

fs.createReadStream(path.resolve(__dirname, program.list)

Upvotes: 0

Micromuncher
Micromuncher

Reputation: 903

It may sound glib, but program.list is undefined, which is why you can't read from it. It is undefined because you haven't set up commander to know how it maps from the command line. If you review examples in the commander documentation it might provide more light (and look at the help for "variadic arguments"). You can follow this example on how to use command and action methods.

I recommend if you are just starting, don't use packages like commander if you don't need to. Your question really is about using commander. This question provides some great hints as to how to get at command line arguments.

Upvotes: 1

Related Questions