A node CLI to start new projects I was annoyed to manually start new projects each time so I made a Node CLI that automate the process. I'm really not comfortable yet with node, so I wanted some advice. It works but I don't know if I did it the node way or not.

Basically the code under here is my whole application. The file structure is like so:

- app.js
- seed 


It's not really complicated. What I do in the app is copy the seed and change the project name in package.json. The seed is a template project, with nothing in it beside a starter-repo. I could have upload it to git but this is more fun.

#!/usr/bin/env node

const spawn = require('child_process').spawn;
const fs = require("fs");
const path = require('path');
const through2 = require('through2');
const copydir = require('copy-dir');

const name = process.argv[2] || "unnamed project";
const projPath = path.join(process.cwd(), name);
// path to my seed project
const seed = path.join(__dirname, "seed");


if (!fs.existsSync(name)) {
    fs.mkdirSync(name);
} else {
    throw new Error(`directory ${name} already exist`);
}

copydir(seed, path.join(process.cwd(), name), function(err) {
    if (err) {
        console.log(err);
        process.exit(1);
    }
    const package = path.join(projPath, "package.json");
    // in my seed project package.json, I have name: "-your-app-name-here-"
    replaceInFile(package, "-your-app-name-here-", name, onCopyDone);
});

function onCopyDone(err) {
    if (!err)
        install(projPath)
    else
        console.log(err)
}

function replaceInFile(someFile, rep, by, cb) {
    fs.readFile(someFile, 'utf8', function(err, data) {
        if (err) {
            return console.log(err);
        }
        let result = data.replace(rep, by);

        fs.writeFile(someFile, result, 'utf8', cb);
    });
}

function install(where) {
    console.log('installing dependencies...')
    const i = spawn('npm', ['install', '--prefix', where]);

    i.stdout.on('data', (data) =&gt; {
        console.log(`stdout: ${data}`);
    });
}


Primarily what I'd like to know is how I can do it more the Node way, if that makes sense.
Avoiding else

If you can avoid else then it can simplify indentation. For example: 


if (!fs.existsSync(name)) {
    fs.mkdirSync(name);
} else {
    throw new Error(`directory ${name} already exist`);
}



The error can be thrown the error if the name exists, but if not just go ahead with the call to fs.mkdirSync():

if (fs.existsSync(name)) {
    throw new Error(`directory ${name} already exist`);
} 
fs.mkdirSync(name);


In some cases you may have to manually return or exit if the statement inside the first conditional doesn't return early or terminate the process - e.g. inside onCopyDone().

Use const instead of let when appropriate

It is wise to get in the habit of using const for any value that doesn't get re-assigned. Then if you need to have a variable that changes, switch to using let. This affects variables like result in the callback inside replaceInFile().

Arrow functions

The parentheses are not necessary on arrow functions with only one argument. Also, a single line doesn't need to have brackets - while this would lead to the return value of the statement getting returned, it shouldn't matter in most cases - so this:


i.stdout.on('data', (data) =&gt; {
    console.log(`stdout: ${data}`);
});



can be simplified to:

i.stdout.on('data', data =&gt; console.log(`stdout: ${data}`));