Go to Blogs
Making REST API with Deno 2 and Oak

Making REST API with Deno 2 and Oak

Create project and write starter code

Start by initializing a Deno project

deno init rest_deno_oak

Open this project in VS Code

code rest_deno_oak

Open main.ts and import the Application and Router from Oak

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

Now initialize the Application and Router

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

Register all route handlers

app.use(router.routes());

Start listening on PORT 8000

await app.listen({ port: 8000 });

Create a test route

router.get("/", (context) => {
    context.response.body = "Hello World"
})

After this, the entire main.ts file should look like this.

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

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

router.get("/", (context) => {
    context.response.body = "Hello World"
})

app.use(router.routes());

await app.listen({ port: 8000 });

Start the server by running the following command

deno task dev

Open Postman and make a GET request at the following URL

http://localhost:8000

Database Operations

Let's do some database operations in this deno app.

Create a .env file in the root directory of the project

DATABASE_USER="<YOUR_DATABASE_USER>"
DATABASE_NAME="<YOUR_DATABASE_NAME>"
DATABASE_PORT=<YOUR_DATABASE_PORT>
DATABASE_HOST="<YOUR_DATABASE_HOST>"
DATABASE_PASS="<YOUR_DATABASE_PASSWORD>"

Replace values in all of the above keys in the .env file with your actual values.

Create a file inside db/db.ts and paste below code inside it.

import postgres from "https://deno.land/x/postgresjs@v3.4.4/mod.js";
import { load } from "https://deno.land/std@0.224.0/dotenv/mod.ts";

// Load all environment variables in envVars.
const envVars = await load();

export const DB_NAME = envVars.DATABASE_NAME;
export const DB_USERNAME = envVars.DATABASE_USER;
export const DB_PORT = Number(envVars.DATABASE_PORT);
export const DB_HOST = envVars.DATABASE_HOST;
export const DB_PASS = envVars.DATABASE_PASS;

// Create a connection with Postgres database
export const sql = postgres({
  user: DB_USERNAME,
  port: DB_PORT,
  host: DB_HOST,
  database: DB_NAME,
  password: DB_PASS,
});

The above code will help us establish a connection with our Postgres database and perform database operations.

Now, create a file inside db/seed.ts and paste the code below

import type { Author, AuthorCreateInput } from "../types/author.ts";
import type { Post, PostCreateInput } from "../types/post.ts";
import { sql } from "./db.ts";
import { faker } from "https://esm.sh/@faker-js/faker@9.0.3";

// Create Author table
await sql`
    CREATE TABLE IF NOT EXISTS author (
        id SERIAL PRIMARY KEY,
        name VARCHAR(100) NOT NULL,
        age INT,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    );
`;

// Create post table
await sql`
    CREATE TABLE IF NOT EXISTS post (
        id SERIAL PRIMARY KEY,
        title TEXT NOT NULL,
        content TEXT NOT NULL,
        slug TEXT NOT NULL,
        author_id INT NOT NULL,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
        FOREIGN KEY (author_id) REFERENCES author (id) ON DELETE CASCADE
    );
`;

// Create fake authors
const authors: AuthorCreateInput[] = Array(4)
  .fill(null)
  .map(() => ({
    name: faker.person.fullName(),
    age: faker.number.int({ min: 10, max: 100 }),
  }));

// Insert author details into author table
const authorInsertResult: Author[] = await sql`
    INSERT INTO author ${sql(authors)} returning id,name,age,created_at`;

console.log(authorInsertResult);

// Create fake posts
const postsToCreate: PostCreateInput[] = [];
authorInsertResult.forEach((author) => {
  const posts: PostCreateInput[] = [];
  const numberOfPosts = Math.floor(Math.random() * 10) + 1;
  for (let i = 0; i < numberOfPosts; i++) {
    posts.push({
      title: faker.lorem.sentence(),
      content: faker.lorem.paragraphs(),
      author_id: author.id,
      slug: faker.lorem.slug(),
    });
  }
  postsToCreate.push(...posts);
});

// Insert post details into post table
const postInsertResult: Pick<Post, "id">[] = await sql`
    INSERT INTO post ${sql(postsToCreate)} returning id, slug`;

console.log(postInsertResult);

self.close();

This file will create two tables in our database, post and author. It will also insert some dummy data in both of these tables. Let's create type files for them.

Create a file inside types/author.ts and paste below code in it.

export type Author = {
  id: number;
  name: string;
  age?: number;
  created_at: Date;
};

export type AuthorCreateInput = Omit<Author, "id" | "created_at">;

Create a file inside types/post.ts and paste below code in it.

export type Post = {
  id: number;
  title: string;
  content: string;
  slug: string;
  author_id: number;
  created_at: Date;
};

export type PostCreateInput = Omit<Post, "id" | "created_at">;

Create route to get authors from database

Create a file inside modules/author/handler.ts and paste the code below.

import type { Context } from "https://deno.land/x/oak@v11.1.0/mod.ts";
import { sql } from "../../db/db.ts";

// Get all authors from database
export const getAuthors = async (context: Context) => {
  const authors = await sql`
        SELECT * FROM author
    `;
  context.response.body = authors;
};

Now create another file inside module/author/routes.ts and paste the code below.

import { Router } from "https://deno.land/x/oak@v11.1.0/mod.ts";
import { getAuthors } from "./handler.ts";

// Initialize a new router
export const authorRouter = new Router();

// Bind "/" route on authorRouter
authorRouter.get("/", getAuthors);

Now bind authorRouter to the router in the main.ts file.

import { authorRouter } from "./modules/author/routes.ts";
...
router.use("/author", authorRouter.routes());

Open Postman and make a GET request at the following URL. You should see the list of all authors present in the database.

http://localhost:8000/author

Source Code

https://github.com/abhidiwakar/rest_api_deno_oak

Written On: 11 Nov, 2024

Last Updated On: 11 Nov, 2024

Abhishek Diwakar

Abhishek Diwakar

Software Engineer