Skip to main content

RESTful CRUD API with Deno, Oak and MongoDB

In this post, we are going to build a RESTful CRUD API with Deno, Oak and MongoDB as database.

In the previous article, we discussed how to install deno in your local machine and start using Deno. If you haven’t read that article, please read the article below and install the deno first.

After installing the Deno, we will start building the restful crud api’s. We will use oak microframework.

Some of the other deno microframeworks are:

In this article we will be using oak, which is inspired by koa.

Setting up the project:

  1. Create a new directory called restful-api-deno
mkdir restful-api-deno

2. After creating the directory just cd into the directory

cd restful-api-deno

3. Create a new file server.ts and paste the following code init.

import { Application } from "https://deno.land/x/oak/mod.ts";const app = new Application();
const port: number = 8000;
app.use((ctx) => {
ctx.response.body = "Hello World!";
});
console.log('server is running on port ', port);
await app.listen({ port });

4. Let's fire up the server….

deno run --allow-net server.ts

5. The server will be started and you should see the following output:

Check file:///home/nineleaps/personal/restful-api-deno/server.ts
server is running on port 8000

Creating RESTful CRUD API

We will be creating create, read, update and delete API for users resource.

POST /users Create a new user

GET /users Get list of user

PUT /users/:id Update a particular user

DELETE /users/:id Delete a particular user

  1. Create a new directory called routes and create a file user.ts
mkdir routes
cd routes

2. In the routes/user.ts file paste the following code.

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

const router = new Router();
// controller
import userController from "../controllers/user.ts";

router
.get("/users", userController.get)
.post("/users", userController.create)
.put("/users/:id", userController.update)
.delete("/users/:id", userController.delete);

export default router;

3. Now let's go ahead and create a controller for our routes.

In the same root folder create a new directory called controllers and create a new file user.ts

4. In the controllers/users.ts file paste the following code.

export default {
create: async () => {},
get: async () => {},
update: async () => {},
delete: () => {},
};

For now, this is just a skeleton where we are just exploring 4 functions that we used in the route/user.ts file.

So far you might have realized there is some familiarity with Node.js and express if you have work with node.js before.

5. Finally open server.ts and make the following changes:

Import route in server.ts

// routes
import userRouter from "./routes/user.ts";

Next step is to use this router, final server.ts will like:

import { Application } from "https://deno.land/x/oak/mod.ts";
// routes
import userRouter from "./routes/user.ts";
const app = new Application();
const port: number = 8000;
app.use(userRouter.routes());
app.use(userRouter.allowedMethods());
app.use((ctx) => {
ctx.response.body = "Hello World!";
});
console.log('server is running on port ', port);
await app.listen({ port });

Connecting with MongoDB

  1. Create a new file called db.ts and paste the following code.
import { MongoClient } from "https://deno.land/x/mongo@v0.21.2/mod.ts";const client = new MongoClient();
await client.connect("mongodb://localhost:27017");
// Defining schema interface
interface UserSchema {
_id: { $oid: string };
name: string;
email: string;
}
const db = client.database("restful_api_deno");const User = db.collection<UserSchema>("users");export { User };

Here we are using MongoClient to connect with MongoDB database. We have specified database name as restful_api_deno and collection named users

So now we have glue server, routes, and controller and database, but our routes are with empty functionality. So let’s add some functionality to the controller.

Create User

Let’s add code to create a new user in the controller create function.

import { User } from "../db.ts";export default {
create: async (context: any) => {
try {
// Get the body from request
const body: any = await context.request.body();
// Get the fields from body
const { name, email } = body.value;
// Insert the data into the database
const id = await User.insertOne({
name: name,
email: email
});
// Send the response
context.response.body = {id};
context.response.status = 201;
} catch (error) {
context.response.body = error;
context.response.status = 500;
console.log(error);
}
},
get: async () => { },
update: async () => { },
delete: () => { },
};

Start the server

deno run --allow-net server.ts

Testing the create user API using Postman.

Image for post

Provide the name, and email in the json format in postman and hit the POST /users API. If everything works correctly user will be created in db and the created id will be returned in the response along with status code 201.

You can check the db that there is a document created.

Image for post

Lets finish up the rest of the API.

import { User } from "../db.ts";export default {
create: async (context: any) => {
try {
// Get the body from request
const body: any = await context.request.body();
// Get the fields from body
const { name, email } = await body.value;
// Insert the data into the database
const id = await User.insertOne({
name: name,
email: email
});
// Send the response
context.response.body = { id };
context.response.status = 201;
} catch (error) {
context.response.body = error;
context.response.status = 500;
console.log(error);
}
},
get: async (context: any) => {
try {
// Fetch the data from the database
const users = await User.find({});
// Send the response
context.response.body = users;
context.response.status = 200;
} catch (error) {
context.response.body = error;
context.response.status = 500;
console.log(error);
}
},
update: async (context: any) => {
try {
// Get the id
const id: string = await context.params.id;
// Get the body from request
const body: any = await context.request.body();
// Get the fields from body
const { name, email } = await body.value;
// Insert the data into the database
const result = await User.updateOne({
_id: id,
}, {
$set: {
name: name,
email: email,
}
});
// Send the response
context.response.body = { result };
context.response.status = 201;
} catch (error) {
context.response.body = error;
context.response.status = 500;
console.log(error);
}
},
delete: async (context: any) => {
try {
// Get the id
const id: string = await context.params.id;
// Delete the data from the database
const result = await User.deleteOne({
_id: id,
});
// Send the response
context.response.body = { result };
context.response.status = 204;
} catch (error) {
context.response.body = error;
context.response.status = 500;
console.log(error);
}
},
};

We finished the CRUD functionality in our deno app. You can test the other API’s too using Postman.

If you want to check out the code, you can find the source code in Github.

Thanks for reading. If you have some feedback, please reach out to me on Twitter or Github.

Comments

Popular posts from this blog

Track stock market information right in your Terminal.

     Introduction: As a developer, I love working with the terminal. The plain, simple, and in my opinion the best way to interact with the computer (also it makes you look geeky). I spent most of my time in the terminal. By now you must have guessed I am a huge fan of the terminal and terminal-based applications. Recently I developed an interest in stock markets and started tracking the stock markets. Since I love working with the terminal I decided to build a terminal oriented application that can help me to track the stock market. Inspir e d by  wttr.in  I build  terminal-stocks  which can provide the stock's current prices, historical prices, and global market summary. How to use terminal-stocks terminal-stocks  is available and can be used without installation. Get the current price of the stock. curl terminal-stocks.herokuapp.com/ITC.NS Current price of stocks You need to provide the ticker of the stock and terminal-stocks will give you the price information of the stock.  t

Free to use tools for maintaining your OpenSource projects

In this post, we will talk about how to effectively maintain your OpenSource projects using tools/softwares which are free to use for OpenSource and the public repositories. Over time, when the project grows you, need to set up a few tools which can help you maintain the project and automate the trivial tasks. 1. Setup CI/CD Having an OpenSource project to which you might b e  contributing just as a hobby, but doesn’t mean you don’t need to set up CI/CD pipeline. You don’t need to expend a single dime on servers or need to use cloud services to run your CI/CD. There are a lot of CI/CD tools available free for open source projects and public repositories. One such tool is  Travis CI  which you can use for setting up CI/CD for your project. Travis CI Travis CI You can run test cases and deploy code to your servers. Travis CI works great and easy to set up the CI/CD pipeline. 2. Code Analysis and Code Quality Maintaining code quality as the project grows can be very hard and time-consumi

Why I switched to Brave browser from Google Chrome.

  I have used Google Chrome for the last 5–6 years, Chrome was the perfect browser and it has many features like syncing everything across the platform and devices, bookmarks, history, lots of extensions, password manager, auto-complete, developer options to name a few. All of these in with just a Google Id. Google ecosystem is very rich and useful. So why I decided to switch to  Brave  browser after giving it a trial for a month. Although chrome has everything, there were few issues that led me to hunt for a new browser and finally switched to Brave. Why Brave? 1. Chrome hogs the RAM “Aw ,  Snap! Google Chrome ran out of memory while trying to display this webpage.” I am sure you might have seen this message. This message appears when chrome has eaten all of the available RAM memory. I understand the reason behind Chrome using a lot of memory because of its architecture. It runs all the tabs in a separate process so that it can provide isolation. Modern sites and designers/developer