Deno Pokemon API
permalinkToday I wanted to dive deeper into Deno and see how a very basic file API would look like. This is a great exercise to get a better feel for Deno.
We are going to build a Pokémon API; We'll be able to do the following actions:
- Retrieve a list of all our Pokémon
- Catch a new Pokémon
- Level up a Pokémon
- Release a Pokémon back to the wild
Please note this uses local storage and is not connected to a Database!
Deno API permalink
We will be using the oak
module (see the Pokémon reference?) and import the Application and Router object:
import {Application, Router} from 'https://deno.land/x/oak/mod.ts';
Next up we start by defining our variables:
const env = Deno.env.toObject();
const PORT = env.PORT || 3000;
const HOST = env.HOST || '127.0.0.1';
Now we have to start our Oak application and run it.
// Define our router
const router = new Router();
// Define all our routes
router
.get('/pokemon', getPokemons)
.get('/pokemon/:name', getPokemon)
.post('/pokemon', catchPokemon)
.put('/pokemon/:name', levelUpPokemon)
.delete('/pokemon/:name', releasePokemon);
// Define our application
const app = new Application();
// Tell the application to use our defined routes
app.use(router.routes());
// We do have to allow all methods since Deno is a secure environment
app.use(router.allowedMethods());
// And we'll start our app on the defined port and address
await app.listen(`${HOST}:${PORT}`);
That's our setup, but we now have to go and define all methods!
Deno Declaring our Interface permalink
Before defining our methods, we must declare our Pokémon interface and our basic Pokémons.
interface Pokemon {
name: string;
level: number;
}
let pokemons: Array<Pokemon> = [
{
name: 'Pikachu',
level: 10,
},
{
name: 'Eevee',
level: 50,
},
{
name: 'Snorlax',
level: 20,
},
];
Excellent, now we can start and build our methods. Let's start by creating our get function:
Deno Getting All Pokémon permalink
GET: /pokemon
export const getPokemons = ({response}: {response: any}) => {
response.body = pokemons;
};
Easy as that, on the request, we return the response of our Pokemon, and it will look like this:
Deno Get Specific Pokémon permalink
Ok, but what if we want to get one specific Pokémon based on their name?
GET: /pokemon/Pikachu
export const getPokemon = ({
params,
response,
}: {
params: {
name: string,
},
response: any,
}) => {
const pokemon = pokemons.filter((pokemon) => pokemon.name === params.name);
if (pokemon.length) {
response.status = 200;
response.body = pokemon[0];
return;
}
response.status = 400;
response.body = {msg: `Cannot find pokemon ${params.name}`};
};
Here we are listing to the params name and filtering our Pokémons array. If none is, found, we will return that we can't find the Pokémon.
Deno Catch a Pokémon permalink
But we are proper Pokémasters, and we want to catch a Charizard!
POST: /pokemon
export const catchPokemon = async ({
request,
response,
}: {
request: any,
response: any,
}) => {
const body = await request.body();
const {name, level}: {name: string, level: number} = body.value;
pokemons.push({
name: name,
level: level,
});
response.body = {msg: 'OK'};
response.status = 200;
};
We will post the name and level of the Pokémon to add it to our local storage.
Deno Level Up a Pokémon permalink
Of course, we are very good trainers, and our Eevee will level up!
PUT: /pokemon/Eevee
export const levelUpPokemon = async ({
params,
request,
response,
}: {
params: {
name: string,
},
request: any,
response: any,
}) => {
const temp = pokemons.filter((pokemon) => pokemon.name === params.name);
const body = await request.body();
const {level}: {level: number} = body.value;
if (temp.length) {
temp[0].level = level;
response.status = 200;
response.body = {msg: 'OK'};
return;
}
response.status = 400;
response.body = {msg: `Cannot find pokemon ${params.name}`};
};
Deno Releasing a Pokémon permalink
There comes a time when you just have to let go of some Pokémon so let's release them back into the wild
DELETE /pokemon/snorlax
export const releasePokemon = ({
params,
response,
}: {
params: {
name: string,
},
response: any,
}) => {
const lengthBefore = pokemons.length;
pokemons = pokemons.filter((pokemon) => pokemon.name !== params.name);
if (pokemons.length === lengthBefore) {
response.status = 400;
response.body = {msg: `Cannot find pokemon ${params.name}`};
return;
}
response.body = {msg: 'OK'};
response.status = 200;
};
I hope you found this tutorial useful! You can find this project on GitHub.
Thank you for reading, and let's connect! permalink
Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter