My FeedDiscussionsHeadless CMS
New
Sign in
Log inSign up
Learn more about Hashnode Headless CMSHashnode Headless CMS
Collaborate seamlessly with Hashnode Headless CMS for Enterprise.
Upgrade ✨Learn more

Nodejs terminal app

Aman Kumar Singh's photo
Aman Kumar Singh
·Sep 23, 2020·

11 min read

By the end of this post, you will learn to create your own commands for Linux to make your life simpler.

Lets Begin

First of all, you need node and npm installed in your system to install node and npm you can follow install node & npm download and install the latest stable version of node and npm.

Creating the project

$ mkdir node-cli
$ cd node-cli
$ npm init -y

hurray we created a node application 😃

to make this easy lets divide this in steps

Step 1

you can open the project in any code editor of choice mine is vs code.

there will be a file called package.json that is used by NPM (Node Package Manager) uses this package.json file information about Node JS Application information or Node JS Package details. It will look like this

{
  "name": "node-cli",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Now let's test this

 $ echo "console.log(\"Hello world\") " > index.js 
 $ node index.js
 Hello world

By this we successfully executed our first node terminal program Yes, it is working, great 😃, let's now focus on the real thing.

Step 2 (We will do everything in index.js)

Add this line at the top of your index.js file

#!/usr/bin/env node;
console.log("Hello, world!");

#!/usr/bin/env node this line should be the first line of your file basically when you execute this file it will tell that the system what interpreter to pass that file to for execution, via the command line following the magic #! prefix (called shebang).

let's make this index.js file executable, in the terminal run the following command.

$ chmod +x index.js

it will make the file executable ./index.js to run your application.

let me tell you the capability of our command: It is capable of doing creating a react app and pushing to your Github account, to keep you synced. creating a new project and pushing it to Github is redundant, it's needed to be automated.

Step 3 (Knowing about the modules we will use)

$ yarn add minimist axios path

yarn add will add these packages to your projects

the use of minimist : the guts of optimist's argument parser without all the fanciful decoration.

the use of axios : it is used for passing the HTTP request.

the use of path : The path module provides utilities for working with file and directory paths.

we will also use child_process it comes prebuild with node.

use of minimist

suppose you want to run our index.js file you do ./index.js but if you want to pass arguments to the program like ./index.js --file ./ --n first minimist will give you an object like this

{
     file : './',
     n : 'first'
}

we can use minimist in this way

var args = require("minimist")(process.argv.slice(2), {
  boolean: ["help", "check"],
  string: ["n", "path", "setup"],
});

the type of help and check will be boolean and n, path, and setup will be of type string.

use of Axios

Axios is used to make HTTP request, you can use Axios like this.

const { default: Axios } = require("axios");
const payload = {
          name: `${args.n}`,
          description: "this is text",
          homepage: "https://github.com",
          private: false,
        };
        Axios.post("https://api.github.com/user/repos", payload, {
          headers: {
            "Content-Type": "application/json",
            Authorization: `token ${Key}`,
          },
        })
.then(res => console.log(res.data))
.catch(e => console.err(e));

Axios returns a promise that we check if the promise is fulfilled .then() will we called and if it fails .catch() will be called

use of path

The path module provides utilities for working with file and directory paths.

use of child_process

The child_process module provides the ability to spawn child processes in a manner that is similar, but not identical, to popen(3). This capability is primarily provided by the child_process.spawn() function, but here we will mainly use exec() method

const exec = require("child_process").exec;
exec(` {your linux terminal commands or anything goes here }`,
     function (err, stdout, stderr) {
                if (err) {
                  console.error(`error: ${err.message}`);
                  return;
                }

                if (stderr) {
                  console.error(`stderr: ${stderr}`);
                }
                console.log("");
                if (stdout) {
                  console.error(`stdout: ${stdout}`);
                }
              }
            );

Now we know all about the packages we will be using.

Step 4

Whenever you make any command line tools it is important to give the proper documentation of the function. Inside the Index.js file first write the help function

function printHelp() {
  console.log("github usage:");
  console.log("");
  console.log(
    "This package can be used while creating a react app and at the same time get synced with github"
  );
  console.log("");
  console.log("--help                             Gives you help window");
  console.log(
    "--n ={fineName} --path ={path}                    File name of the project"
  );

After This lets consider on the main logic of the function, The index.js file will look like this,

#!/usr/bin/env node
var path = require("path");
const exec = require("child_process").exec;
const fetch = require("node-fetch");
const { default: Axios } = require("axios");
var args = require("minimist")(process.argv.slice(2), {
  boolean: ["help", "check"],
  string: ["n", "path", "setup"],
});

const key = <Your_key />;

const BASEPATH = path.resolve(process.env.BASEPATH || __dirname);
if (args.help) {
  printHelp();
} else if (args.n) {
  if (args.path) {
    var pathto = path.join(BASEPATH, args.path);
    console.log("\x1b[32m", "work is in progress, please wait!");
    exec(
      `cd ${pathto} && mkdir ${args.n} && cd ${args.n} && create-react-app ./`,
      (err, stdout, stderr) => {
        if (err) {
          console.error(`error: ${err.message}`);
          return;
        }

        if (stderr) {
          console.error(`stderr: ${stderr}`);
          //return;
        }

        console.log("\x1b[32m", "Creating github repo!");

        const payload = {
          name: `${args.n}`,
          description: "this is text",
          homepage: "https://github.com",
          private: false,
        };
        Axios.post("https://api.github.com/user/repos", payload, {
          headers: {
            "Content-Type": "application/json",
            Authorization: `token ${key}`,
          },
        })
          .then((res) => {
            console.log(res.data);
            exec(
              `cd ${pathto}/${args.n} && 
                 git init && 
                git remote add origin ${res.data.ssh_url} && 
                git add . && git branch -M master &&
                git push -u origin master `,
              function (err, stdout, stderr) {
                if (err) {
                  console.error(`error: ${err.message}`);
                  return;
                }

                if (stderr) {
                  console.error(`stderr: ${stderr}`);
                }
                console.log("");
                console.log(`cd ${pathto}/${args.n}`);
                console.log("yarn start");
                console.log("Happy hacking");
              }
            );
          })
          .catch((e) => console.log("NetWork Error", e));
      }
    );
  } else {
    printHelp();
  }
} else {
  printHelp();
}
//************************************************
function printHelp() {
  console.log("github usage:");
  console.log("");
  console.log(
    "This package can be used while creating a react app and at the same time get synced with github"
  );
  console.log("");
  console.log("--help                             Gives you help window");
  console.log(
    "--n ={fineName} --path ={path}                    File name of the project"
  );
}

you can get your key here create personal access token, you can put your key at line 12, in index.js

step 5

Creating an command to execute this file

$ npm link
npm WARN react-app@1.0.0 No description
npm WARN react-app@1.0.0 No repository field.

audited 35 packages in 0.769s

3 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

/usr/local/bin/react-app -> /usr/local/lib/node_modules/react-app/index.js
/usr/local/lib/node_modules/react-app -> /home/aman/Github

To run hit node-cli with the arguments in command line if you want to change the name of function you can change name of in package.json.

Link to the repo Github

Thanks for bearing 😃.