What is Deno?
Tags: deno, javascript, node, webassembly
Published: 2021-04-20 20:26:26

In this new -- ongoing series -- I want to talk about Deeno. Or Dehno. Or Déno.
Eh, *_Dunno_, Take your pick.

This article is a transcript of a [Youtube video I made](https://youtu.be/8MTxtW-NsXI).

Deno is a JavaScript runtime, just like Node. Actually, the creator of Node, Ryan Dahl, initialized the Deno project. Maybe you
noticed that Deno is an anagram for Node. Clever.

For the past ten years or so, ECMA International -- the people responsible for standardizing JavaScript -- and browser
manufacturers have been hard at work improving the JavaScript ecosystem.

In retrospect, the design decisions made by the Node creators are feeling more and more foreign. 
[That's what Ryan said during a presentation in 2018](https://www.youtube.com/watch?v=M3BM9TB-8yA).

So TL;DR Deno is a secure JavaScript runtime that feels more in-line with the modern JavaScript ecosystem. The project bundles more of
the techs that the community loves; things like TypeScript, a linter, testing tools and WASM.

Okay, so let's go over what makes Deno different than Node.

## ES Modules

So, the first thing -- which might be shocking if you're coming from Node -- is ECMAScript modules. That is "importing" files instead of "requiring" files. 

I know you're going to say "Node has ES modules too," which is stable since version 15 -- But -- Node doesn't accept full URL as the target; every script must be downloaded locally, usually via NPM. 

I think it's good that Deno implemented module fetching like the browsers do. It makes for a more consistent code base and, it's the first step toward portable code. 

With this feature you can decentralize module registries; You can either import from local files, host them yourself or use a third-party registry like `deno/x` or `nest.land`.

```js
import { serve } from "https://deno.land/std@0.88.0/http/server.ts";
```

## Web Platform API

Next up is the "Web Platform API" -- when it makes sense, the Deno team implements APIs using the Whataburger (WHATWG) specs.

That means that things like `fetch,` WebSocket and Workers are available out-of-the-box.

These kinds of efforts help bridge the gap between "browser code" and "server code," -- making it possible to write code that works everywhere.

```js
fetch("https://randomuser.me/api")
  .then(response => response.json());
```

## TypeScript

Next on the list is "A TypeScript compiler" [confettis]. You heard that right. Deno is a polyglot. 

In the same project, you can have JavaScript and TypeScript files without any extra step. 
No Babel, no Webpack, no nothing else.

Considering the ceiling shattering rise of TypeScript in recent years, having TypeScript as a first-citizen format is a game-changer that surely will make a lot of developers life easier.

## Permissions

Have you ever worried that a Node module might be spying on you, uploading your browser history or stealing your bitcoins for the 4th time? Enter the Permission API. 

Straight from the CLI, you can specify if a program can read or write to local files or make network requests. 

The rules can be pretty granular, which should give you peace of mind when running code you found on the Internet. But also, it lets your users know that they can trust your module.

```bash
deno run --allow-net=randomuser.me
```

## WebAssembly

Remember when I told you that Deno was a polyglot? 

Well Deno can also execute WebAssembly modules - which means that, through WASM, Deno can execute code from any language that can be compiled down to the binary byte code format. 

Support for this is fairly common in other languages like C, C++ and Rust.

That feature makes it possible to port existing libraries with close to native performance.
 
## Community

Last but not least, is the community. The Deno community is very active and very helpful. 

Most of the action happens on the official Discord server. 

If you're curious to know more about Deno and haven't yet, I highly recommend that you join the server.

Alright, so with all of this covered, I think it would be great to show you Deno in action!

---

First we can define a function to experiment with. Notice that we can use TypeScript without any extra-step. Our `getUser` function will fetch a random user and return a `Promise`.

```ts
// users.ts 
export const targetURL = "https://randomuser.me/api/";

interface Users {
  name: string;
  email: string;
  login: {
    uuid: string;
  };
}

export function getUser (): Promise<Users> {

  return fetch(`${targetURL}?inc=name,email,login,id`)
    .then(response => response.json())
    .then(({ results: [ user ] }) => user);
}
```

Next we could create a new file to run some tests on our function. The Deno namespace comes with a `test` function. 

```ts
// users_test.ts
import { assert } from "https://deno.land/std@0.90.0/testing/asserts.ts";
import { getUser } from "./users.ts";


Deno.test("getUser", async () => {
  const user = await getUser();

  assert(typeof user === "object", "The user is not an object.");
  assert(user.name, "The user does not have a name.");
  assert(user.email, "The user does not have an email.");
});
```

To run our test, we can use the `deno test` sub-command, with the appropriate permissions.

```bash
deno test --allow-net=randomuser.me users_test.ts
```

The Deno test runner will detect any resource leak and throw an error. This is a great way to find bugs early.

```ts
// users_test.ts

...

Deno.test("getUser: leaking", async () => {
  getUser();
});
```

```bash
deno test --allow-net=randomuser.me users_test.ts

[error]
```

Finally, we can create a new file to be used as CLI that will write a JSON file to the File System using our previous `getUser` function. Notice that most I/O functions are available under the Deno namespace.

```ts
// cli.ts
import { getUser } from "./users.ts";

export async function writeUserFile () {
  const user = await getUser();

  return Deno.writeFile(`./${user.login.uuid}.json`, new TextEncoder().encode(JSON.stringify(user, null, 2)));
}

if (import.meta.meta) {
  console.log("%cGenerating a new user...", "color: blue");
  await writeUserFile();
  console.log("%cDone!", "color: green");
}
```

We can run our new tool with the appropriate permissions.

```bash
deno run --allow-write=$(pwd) --allow-net=randomuser.me cli.ts
```

Cherry on top, we can use the `deno install` sub-command to create a system named command. This is a great way to share utility CLI to colleague and friends.

```bash
deno install --allow-read=$(pwd) --allow-write=$(pwd) --allow-net=randomuser.me -n generate-users https://raw.githubusercontent.com/sebastienfilion/i-y/main/01/cli.ts
```

Now, everything you need a random user, you can just run this nifty little command.

```bash
generate-users
```

That's all folks.

---

In this article, we talked about Deno, what makes it unique, and we went through an example of Deno in action. 

I hope this made you curious to learn more about this fantastic project. 

In the next article, we will cover the tools that come out of the box with Deno and how the community deals with modules -- no more package.json.