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

Become the Very Best, Like No One Ever Was: Create Your Own Pokemon API with TypeScript & Deno was initially published on Saturday January 14 2023 on the Tech Dev Blog. For the latest up-to-date content, fresh out of the oven, visit https://techdevblog.io and subscribe to our newsletter!

Welcome to our guide on how to create a JSON REST Pokemon API using Deno, TypeScript, and the PokeAPI! 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 and return it in JSON format. We'll be using Deno as our runtime environment, TypeScript for type-checking, and the PokeAPI as our data source.

Prerequisites

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

  • Deno - a secure JavaScript/TypeScript runtime built with V8 and Rust
  • TypeScript - a strongly type superset of JavaScript
  • Denon - a development tool that restarts your server when you make changes to your code

    Installing Deno

    Deno 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 on your machine. You can verify the installation by running the following command:

deno -v

Installing TypeScript

TypeScript 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 on your machine. You can verify the installation by running the following command:

tsc -v

Installing Denon

A neat trick with Deno 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. If you nonetheless wish to install 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

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 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, 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, 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. 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, 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, 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, TypeScript, and the PokeAPI. 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. Happy coding!

Become the Very Best, Like No One Ever Was: Create Your Own Pokemon API with TypeScript & Deno was initially published on Saturday January 14 2023 on the Tech Dev Blog. For the latest up-to-date content, fresh out of the oven, visit https://techdevblog.io and subscribe to our newsletter!

Did you find this article valuable?

Support Tech Dev Blog by becoming a sponsor. Any amount is appreciated!