Become the Very Best, Like No One Ever Was: Create Your Own Pokemon API with TypeScript & Deno
Tags: deno, typescript, api, tutorial
Published: 2023-01-17 01:33:41

---
title: Become the Very Best, Like No One Ever Was: Create Your Own Pokemon API with TypeScript & Deno
published: true
date: 2023-01-14 11:25:40 UTC
tags: Deno,TypeScript,API,Tutorial
canonical_url: https://techdevblog.io/become-the-very-best-like-no-one-ever-was-create-your-own-pokemon-api-with-typescript-deno/
---

 ![Become the Very Best, Like No One Ever Was: Create Your Own Pokemon API with TypeScript & Deno](https://techdevblog.io/content/images/2023/01/image_0-16.jpg)

Welcome to our guide on how to create a JSON REST Pokemon API using [Deno](https://deno.land/), [TypeScript](https://www.typescriptlang.org), and the [PokeAPI](https://pokeapi.co)! In this guide, we'll be walking through the process of setting up a simple API that can retrieve information about Pokemon from the [PokeAPI](https://pokeapi.co) and return it in JSON format. We'll be using [Deno](https://deno.land/) as our runtime environment, [TypeScript](https://www.typescriptlang.org) for type-checking, and the [PokeAPI](https://pokeapi.co) as our data source.

## Prerequisites

Before we begin, you'll need to make sure you have the following installed on your machine:

- [Deno](https://deno.land/) - a secure JavaScript/TypeScript runtime built with V8 and Rust
- [TypeScript](https://www.typescriptlang.org) - a strongly type superset of JavaScript
- [Denon](https://deno.land/x/denon) - a development tool that restarts your server when you make changes to your code

### Installing [Deno](https://deno.land/)

[Deno](https://deno.land/) can be installed on your machine by running the following command in your terminal:

```
curl -fsSL https://deno.land/x/install/install.sh | sh

```

This will download and install the latest version of [Deno](https://deno.land/) on your machine.  
You can verify the installation by running the following command:

```
deno -v

```

### Installing [TypeScript](https://www.typescriptlang.org)

[TypeScript](https://www.typescriptlang.org) can be installed on your machine using npm...

```
npm install -g typescript

```

... or yarn

```
yarn global add typescript

```

This will download and install the latest version of [TypeScript](https://www.typescriptlang.org) on your machine.  
You can verify the installation by running the following command:

```
tsc -v

```

### Installing [Denon](https://deno.land/x/denon)

A neat trick with [Deno](https://deno.land/) is that can run remote modules without needing them to be installed first. So it is up to you wether or not you should install [Denon](https://deno.land/x/denon). If you nonetheless wish to install [Denon](https://deno.land/x/denon) as a global module, it can be done by running the following command in your terminal:

```
deno install --unstable --allow-read --allow-write --allow-run https://deno.land/x/denon/denon.ts

```

## Set up

### Setting up the project

First, let's create a new directory for our project and navigate into it:

```
mkdir pokemon-api
cd pokemon-api

```

### Setting up [Denon](https://deno.land/x/denon)

[Denon](https://deno.land/x/denon) uses a `denon.json` for it's settings and scripts. In order to avoid having to deal with Deno permissions at runtime when using Denon, we will create a `denon.json` file containing the following settings:

```
{
	"scripts": {
			"start": "deno run --allow-env --allow-net server.ts"
	}
}

```

Next, we'll create a new file called `server.ts` and open it in your text editor of choice. This will be the entry point for our API.

## Importing dependencies

In the first few lines of `server.ts`, we import the dependencies we need for our project:

```
import { Application, Router } from "https://deno.land/x/oak/mod.ts";

```

This line imports the `Application` and `Router` classes from the [Oak](https://deno.land/x/oak) library, which we will use them to set up our server and routing.

## Creating the server

Next, let's create a new instance of the `Application` class and set up our server:

```
const app = new Application();
const PORT = 3000;

app.use(async (ctx, next) => {
    await next();
    const rt = ctx.response.headers.get("X-Response-Time");
    console.log(`${ctx.request.method} ${ctx.request.url} - ${rt}`);
});

app.use(async (ctx, next) => {
    const start = Date.now();
    await next();
    const ms = Date.now() - start;
    ctx.response.headers.set("X-Response-Time", `${ms}ms`); });

app.use(async (ctx) => { ctx.response.body = "Hello World!"; });

console.log(`Server running on port ${PORT}`);
await app.listen({ port: PORT });

```

This sets up an instance of the `Application` class in a variable named `app`, and sets the listening port to 3000. Additionally, we have added two middleware functions. One to log the response time, another that sets the response time in headers. This sets up a basic "Hello World" route for our server, which returns the string "Hello World!" when you visit the root URL of the server.

If you have chosen not to install [Denon](https://deno.land/x/denon), you can run this file using this command:

```
deno run --allow-read --allow-write --allow-run https://deno.land/x/denon/denon.ts start

```

If you have installed [Denon](https://deno.land/x/denon), you can simply use that command:

```
denon start

```

Now, if you visit `http://localhost:3000/` in your web browser, you should see the "Hello World!" message.

## Retrieving a list of Pokemons

Let's add a route for retrieving a list of Pokemons from the [PokeAPI](https://pokeapi.co). In the `server.ts` file, add the following code:

```
router.get("/pokemons", async (ctx) => {
    const res = await fetch(`https://pokeapi.co/api/v2/pokemon?limit=151`);
    const data = await res.json();
    ctx.response.body = data;
});

```

This creates a new route for the URL pattern `/pokemons`. When this route is accessed, the code inside the callback function is executed.

The callback function makes a `GET` request to the [PokeAPI](https://pokeapi.co), retrieving the first generation's 151 original Pokemons. After that, the response JSON is parsed and returned to the user as the response body.

## Retrieving Pokemon data

Now that we have our basic server set up, we can add a route for retrieving Pokemon data by name. In the `server.ts` file, add the following code:

```
router.get("/pokemon/:name", async (ctx) => {
    const pokemonName = ctx.params.name;
    const res = await fetch(`https://pokeapi.co/api/v2/pokemon/${pokemonName}`);
    const data = await res.json();
    ctx.response.body = data;
});

```

This creates a new route for the URL pattern `/pokemon/:name`. When this route is accessed, the code inside the callback function is executed.

The callback function uses the `name` parameter from the URL to make a `GET` request to the [PokeAPI](https://pokeapi.co), retrieving the pokemon data for the `name` specified by the user in the url. After that, the response JSON is parsed and returned to the user as the response body.

Then we tell our app to use the routes and allowed methods defined by our router.

Now, if you visit `http://localhost:3000/pokemon/pikachu` in your web browser, you should see information about Pikachu in JSON format.

## Result

```
import { Application, Router } from "https://deno.land/x/oak/mod.ts";

const app = new Application();
const PORT = 3000;
const router = new Router();

app.use(async (ctx, next) => {
    await next();
    const rt = ctx.response.headers.get("X-Response-Time");
    console.log(`${ctx.request.method} ${ctx.request.url} - ${rt}`);
});

app.use(async (ctx, next) => {
    const start = Date.now();
    await next();
    const ms = Date.now() - start;
    ctx.response.headers.set("X-Response-Time", `${ms}ms`);
});

router.get("/", async (ctx) => {
	ctx.response.body = "Hello World!";
})

router.get("/pokemons", async (ctx) => {
    const res = await fetch(`https://pokeapi.co/api/v2/pokemon?limit=151`);
    const data = await res.json();
    ctx.response.body = data;
});

router.get("/pokemon/:name", async (ctx) => {
	const pokemonName = ctx.params.name;
	const res = await fetch(`https://pokeapi.co/api/v2/pokemon/${pokemonName}`);
	const data = await res.json();
	ctx.response.body = data;
});

app.use(router.routes());
app.use(router.allowedMethods());

console.log(`Server running on port ${PORT}`);
await app.listen({ port: PORT });

```

## Conclusion

That's it! You now have a basic JSON REST Pokemon API up and running using [Deno](https://deno.land/), [TypeScript](https://www.typescriptlang.org), and the [PokeAPI](https://pokeapi.co). This API can be further enhanced with more routes and functionalities to fit your use-case. To go further, you could also add more error handling, caching, and rate limiting for better performance and security.

I hope this guide has been helpful in getting you started with creating your own API using [Deno](https://deno.land/). Happy coding!

<!--kg-card-end: markdown-->