Build A Simple CLI Tool With Deno
Tags: typescript, javascript, node, deno
Published: 2020-04-20 17:20:58

![cover image](https://pbs.twimg.com/media/EJ-3hAxU8AAaYcQ.jpg)

#### What is Deno?
Deno is a secure runtime for JavaScript and TypeScript created by Ryan Dahl who also happens to be the creator of Nodejs. If you've never heard of deno, I suggest you watch these talks by Ryan: He talks about his mistakes with Nodejs [here](https://www.youtube.com/watch?v=M3BM9TB-8yA&vl=en) and a more in-depth look into deno [here](https://www.youtube.com/watch?v=z6JRlx5NC9E)
Deno is basically what Nodejs would have been if it was written today. Now, deno is still a relatively new project and it's not reached v1.0 yet and although it's not intended to replace Nodejs, it certainly has prospects to be the future of server-side JavaScript. Some of the core values that makes it different from Nodejs include:
* security out of the box - explicit access is required for file, network and environment access.
* a different module management system - deno does not use npm and there's no node_modules. Rather, it has a module management system similar to Go where modules are imported via URL.
* in-built support for typescript - you can run typescript files directly without compiling to javascript.
* it is built with Rust!

I'm personally very excited about this project especially because of its support for typescript. However, it's nowhere near reaching Nodejs in terms of popularity and adoption.

#### Let's build something!
In this article, we're going to build a simple cli tool to demonstrate some of the features of [deno](deno.land). Our cli will be interacting with a cryptocurrency API to fetch live data.
> _Requirement_: make sure you have deno installed. If you don't, refer to this [link](https://github.com/denoland/deno_install). It's pretty straightforward.

Deno projects typically have an entry file called `mod.ts` so we're going to start here. If you're coding along, create your project folder alongside your entry file. Here's what the project directory looks like:

![code sample one](https://res.cloudinary.com/devmayor/image/upload/v1587346494/crypto-cli-1.png)

__Overview:__
* `mod.ts` is our entry file.
* `Makefile` contains useful commands that would typically be in package.json for a Node.js project.
* `deps.ts` contains all our dependencies.
* `types.d.ts` contains our type definitions.
* `import_map.json` contains our import maps. We use this to enable clarity and readability.

Our cli is basically going to provide two commands. One to fetch and list all coin prices within a limit and one to fetch a particular coin using an id. First off, we need to parse the flags provided with each command and deno provides us just what we need from the std library. So we're going to import the `parse` method from the `flags` module. This is how we import modules in deno:

![code sample two](https://res.cloudinary.com/devmayor/image/upload/v1587346508/crypto-cli-2.png)

In deno, modules are imported using a URL and they're cached the first time you run your app so even if you don't have an internet connection at subsequent times, your app will still run. The `@v0.38.0` in our import means I'm importing from the release version I currently have installed. You can omit that and just import from the latest version if you just installed deno. In the code above, we're destructuring the `args` variable from the `Deno` namespace which simply returns the arguments passed to a script then we pass it to the `parse` method which returns an object containing all arguments passed in key-value pairs. For example, if we run our program as `$ crypto-cli --coins --limit 10`, the object returned will be: `{_: [], coins: true, limit: 10}`. The first property in the object is always an array containing all arguments that did not have an option associated with them(i.e it doesn't match `-f` or `--flag`). If you do not pass a corresponding value to a flag, it defaults to `true`.

Let's write out the function for our first command:

![code sample three](https://res.cloudinary.com/devmayor/image/upload/v1587346495/crypto-cli-3.png)

Here, we have an async function that returns the data from our API call. We're making a fetch request (yes, deno has browser functionality in-built) to the API endpoint to get all coins within the `limit` provided. The if statement checks if a `limit` was not provided and defaults to 10.

The function for the second command looks very similar, only that an `id` is provided this time.

![code sample four](https://res.cloudinary.com/devmayor/image/upload/v1587346506/crypto-cli-4.png)

The response data from the API contains a bunch of information so we're going to filter what we need out and format the data we want to display.

In the code above, the `formatData` function accepts the raw data object and returns a string of the coin name and current price in `USD`.

Now let's define the main function which executes our program commands.

![code sample five](https://res.cloudinary.com/devmayor/image/upload/v1587346557/crypto-cli-5.png)

The function above is an __IIFE__ which runs immediately the file is executed. We have a `switch` statement to check the first flag that was passed and calls the appropriate function. The default case simply displays the welcome message. We also have `if` conditions to check for optional flags like the `limit`.

To test our program, we're going to run `$ deno run --allow-net mod.ts --coins --limit 10`. We should get the following result:

![code sample six](https://res.cloudinary.com/devmayor/image/upload/v1587346536/crypto-cli-6.png)

You must have noticed the `--allow-net` flag passed to the command. This is an example of deno being security first. Deno can't access your network, files, or environment without giving it explicit access. So for example, if your code needs to access the file system you'd need to run it with the `--allow-read` flag.

That's all there is for our cli tool. If you'd like to see the full code, the repository is linked [here](https://github.com/Mayowa-Ojo/crypto-cli). In conclusion, Deno is a very exciting project especially because you get all the benefits of typescript out of the box without the need to compile your files to `js`. You can build a lot with it, ranging from cli Programs to HTTP servers. Do have a look at the [collection of 3rd party libraries](https://deno.land/x/) and see what people are building.