How make Commead line app using Node.js
Tags: webdev, node, cli, javascript
Published: 2023-07-31 15:43:39

Creating a command-line interface app using Node.js is a great way to build utility that users can run from their terminal.

below,I'll guide you through the steps to create a simple cli tool using Node.js

1. set up the project:
First, create a new directory for your cli tool and initialize a new node.js project using npm

```
mkdir my-cli-tool
cd my-cli-tool
npm init -y
```
2.Install necessary dependencies:
In this example, we'll use the 'yargs' package to handle command line input and 'chalk' package to add color to the output .install these dependencies:
`npm install yargs chalk`

2. setup yargs pakage:
import yargs and notes file we'll create. below,
add all command to handle input and use notes script to 
handel every command.
```
const yargs = require("yargs");
const notes = require("./notes.js");

//creat add command
yargs.command({
  command: "add",
  describe: "Add a new note",
  builder: {
    title: {
      describe: "note title ",
      demandOption: true,
      type: "string",
    },
    body: {
      describe: "note body",
      demandOption: true,
      type: "string",
    },
  },
  handler(argv) {
    notes.addNote(argv.title, argv.body);
  },
});
// remove command
yargs.command({
  command: "remove",
  describe: "remove a  note",
  builder: {
    title: {
      describe: "note title",
      demandOption: true,
      type: "string",
    },
  },
  handler(argv) {
    notes.removeNote(argv.title);
  },
});
//creat a read command
yargs.command({
  command: "read",
  describe: "read a note",
  builder: {
    title: {
      command: "title",
      describe: "note title",
      demandOption: true,
      type: "string",
    },
  },
  handler(argv) {
    notes.readNote(argv.title);
  },
});

//creat a list command
yargs.command({
  command: "list",
  describe: "list your notes",
  handler() {
    notes.listNotes();
  },
});
// for yargs work
yargs.parse();
```
4.notes file to handle all command:
work with file system to storing notes and chalk
to style output 
```
const fs = require("fs");
const chalk = require("chalk");

const saveNotes = (notes) => {
  let notesJSON = JSON.stringify(notes);
  fs.writeFileSync("notes.json", notesJSON);
};

const loadNotes = () => {
  try {
    return JSON.parse(fs.readFileSync("notes.json").toString());
  } catch (e) {
    return [];
  }
};

let notes = loadNotes();

const addNote = (title, body) => {
  let note = {
    title: title,
    body: body,
  };
  const duplicateNote = notes.find((note) => note.title === title);
  if (!duplicateNote) {
    notes.push(note);
    saveNotes(notes);
    console.log(chalk.green.inverse("New note added!"));
  } else {
    console.log(chalk.red.inverse("note title taken!"));
  }
};

const removeNote = (title) => {
  let newNotes = notes.filter((note) => note.title !== title);
  if (notes.length > newNotes.length) {
    console.log(chalk.green.inverse("Note removed!"));
    saveNotes(newNotes);
  } else {
    console.log(chalk.red.inverse("No note found! or it removed"));
  }
};

const listNotes = () => {
  if (notes.length == 0) {
    console.log(chalk.inverse("no note found add one"));
    return;
  }
  console.log(chalk.inverse("Your notes"));
  notes.forEach((note) => {
    console.log(chalk.blue(note.title));
  });
};

const readNote = (title) => {
  const note = notes.find((note) => note.title === title);
  if (note) {
    console.log("title: " + chalk.blue.inverse(note.title));
    console.log("body: " + chalk.blue(note.body));
  } else {
    console.log(chalk.red.inverse("note not found!"));
  }
};

module.exports = {
  addNote,
  removeNote,
  listNotes,
  readNote,
};

```
5.test app :
add command
```
node .\app.js add  --title="test app" --body="test"
```

remove command
```
node .\app.js remove  --title="test app"
```
read note command
```
node .\app.js read  --title="test app"
```

list command

```
node .\app.js list
```
 That's it! You have now created a basic CLI tool using Node.js that can be shared and used by others. You can expand it with more commands and functionalities based on your specific use case.