• Building CRUD APIs using Deno and Oak
  • By Kailas Walldoddi
  • The Nuggets translation Project
  • Permanent link to this article: github.com/xitu/gold-m…
  • Translator: lhd951220
  • Proofreader: MangoTsing

Deno is a fairly new environment compared to Node. One of the first things developers usually want to do when learning Deno is build a CRUD API. Deno has a number of projects to help us achieve this, including denO-Express, Oak, Servest, Deno-Drash and Pogo. In this article, we’ll use Deno and Oak to learn how to build a to-do list.

What are we building?

Oak is a project inspired by Koa, a popular Node.js middleware framework that provides HTTP services. We’ll use Oak and Deno to build a small application that handles to-do implementation lists. The API we will create is shown below as an Endpoint.

How do we build it?

We need to create two files in our project library, app.ts and routes.ts. One is used for applications and the other is used for routing services.

The contents of the app.ts file are shown as follows. Take a look at how we imported the Application module from Oak in the app.ts file. We create the new Oak application in line 8. We made the application use the route that will be defined later in the routes.ts file. The application will now run at the address specified in line 6 and on the port specified in line 5.

import { Application } from 'https://deno.land/x/oak/mod.ts';
import { router } from "./routes.ts";

const env = Deno.env.toObject()
const PORT = env.PORT || 4000
const HOST = env.HOST || '127.0.0.1'

const app = new Application()

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

console.log(`Listening on port ${PORT}. `)

await app.listen(`${HOST}:${PORT}`)
Copy the code

We will create a Todo interface in routes.ts with two fields ID and description. We will store the to-do ID and the to-do description on these two fields, respectively. We also have a to-do list that contains the initial list to use on the first return.

interface Todo {
    description: string
    id: number
}

let todos: Array<Todo> = [
    {
        description: 'Todo 1',
        id: 1,
    },
    {
        description: 'Todo 2',
        id: 2,},]Copy the code

Let’s now define some functions that support list operations of to-do items, get the specified to-do item by ID, create a new to-do item, update/delete the description of the specified to-do item by ID. You can see similar code in the file below.

export const getTodos = ({ response }: { response: any }) = > {
    response.body = todos
}

export const getTodo = ({
    params,
    response,
}: {
    params: {
        id: string
    }
    response: any= > {})const todo = todos.filter((todo) = > todo.id === parseInt(params.id))
    if (todo.length) {
        response.status = 200
        response.body = todo[0]
        return
    }

    response.status = 400
    response.body = { msg: `Cannot find todo ${params.id}`}}export const addTodo = async ({
    request,
    response,
}: {
    request: any
    response: any= > {})const body = await request.body()
    const { description, id }: { description: string; id: number } = body.value
    todos.push({
        description: description,
        id: id,
    })

    response.body = { msg: 'OK' }
    response.status = 200
}

export const updateTodo = async ({
    params,
    request,
    response,
}: {
    params: {
        id: string
    }
    request: any
    response: any= > {})const temp = todos.filter((existingTodo) = > existingTodo.id === parseInt(params.id))
    const body = await request.body()
    const { description }: { description: string } = body.value.description

    if (temp.length) {
        temp[0].description = description
        response.status = 200
        response.body = { msg: 'OK' }
        return
    }

    response.status = 400
    response.body = { msg: `Cannot find todo ${params.id}`}}export const removeTodo = ({
    params,
    response,
}: {
    params: {
        id: string
    }
    response: any= > {})const lengthBefore = todos.length
    todos = todos.filter((todo) = >todo.id ! = =parseInt(params.id))

    if (todos.length === lengthBefore) {
        response.status = 400
        response.body = { msg: `Cannot find todo ${params.id}` }
        return
    }

    response.body = { msg: 'OK' }
    response.status = 200
}

export const getHome = ({ response }: { response: any }) = > {
    response.body = 'Deno API server is running... '
    response.status = 200
}
Copy the code

We created and exported routes using the following functions.

import { Router } from 'https://deno.land/x/oak/mod.ts'

export const router = new Router()
router
    .get('/', getHome)
    .get('/todos', getTodos)
    .get('/todos/:id', getTodo)
    .post('/todos', addTodo)
    .put('/todos/:id', updateTodo)
    .delete('/todos/:id', removeTodo)
Copy the code

Run the following command to get the application running on http://localhost:4000

Deno run -allow-env -allow-net app.ts

Now, the application runs on localhost:4000, using Postman or some similar tool to test these API routing interfaces. Below is a screenshot of the results obtained using the Postman test.

If you want to clone the code I use in this article to see how it works. You can check it out on GitHub using the link below.

Source: https://github.com/Kailashw/deno-api-oak

If you find any mistakes in your translation or other areas that need to be improved, you are welcome to the Nuggets Translation Program to revise and PR your translation, and you can also get the corresponding reward points. The permanent link to this article at the beginning of this article is the MarkDown link to this article on GitHub.


The Nuggets Translation Project is a community that translates quality Internet technical articles from English sharing articles on nuggets. The content covers Android, iOS, front-end, back-end, blockchain, products, design, artificial intelligence and other fields. If you want to see more high-quality translation, please continue to pay attention to the Translation plan of Digging Gold, the official Weibo, Zhihu column.