image
How To Code A Simple CRUD RESTful API in Deno
#Deno #Server #TypeScript

Hey There, deno was just released recently and it seems to be the talk as most backend developers are getting to work with it and see how it works. In this article I will show you how to create a simple CRUD RESTful API deno. I won't be working with any databases here but I will do another article on how to connect it to a database.

if you are still asking, What is deno? Worry not, I did an article an article on that, you can read it here . So let's get started.

Create a folder and in it create our main file and name it server.ts, this will be our main file that will connect to other files within our folder. In the file have the codes below:

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

const port = 5000;

const app = new Application();

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

console.log(`Server Running on Port ${port}`);

await app.listen({ port });

In our server.ts file we are importing Application from the oak module from deno.land site, oak is used for routing functionalities and then we are importing router from routes.ts file which we create in a few. we then create a constant port, we will use port 5000 for this. then we are just allowing our app to use routes from our routes.ts. If you are familiar with TypeScript or JavaScript then understanding this won't be a problem.

Now we need to create our routes.ts. Here we will have all the routes which we use in our project. Create another file and name it routes.ts and have the codes below:

import { Router } from "https://deno.land/x/oak/mod.ts";
import {
  getProducts,
  getProduct,
  addProduct,
  updateProduct,
  deleteProduct,
} from "./controllers/products.ts";

const router = new Router();

router.get("/API/products", getProducts)
  .get("/API/products/:id", getProduct)
  .post("/API/products", addProduct)
  .put("/API/products/:id", updateProduct)
  .delete("/API/products/:id", deleteProduct);

export default router;

In our routes.ts we are importing Router from oak module and then we also import our routes from our products.ts file which is in the controllers folder. 

To get all our products we need to run "/API/products which uses the GET method eg.

localhost:5000/API/products

This will list all the products we have.

 

To get one specific product we need to pass the id of the product we want to fetch, this also uses the GET method

localhost:5000/API/products/1

This will get one product with has the id of 1. We will see this in practice after we are done with all the codes.

 

To add a product we need to use POST method.

localhost:5000/API/products

 

To update a product we can use POST method because browsers only understanf POST and GEt methods, but since we are testing our API in postman we will use the PUT method and we pass in the specific id of the product we want to update.

localhost:5000/API/products/1

This will update a product that has the id of 1.

 

To delete a product we use the DELETE method and pass in the id of the product we want to delete.

localhost:5000/API/products/1

This will delete the product which has an id of 1.

 

After going through that, weed need now to add our products.ts file which will hold all of our products details, since we are now using any database and this will act as our controller. So create a folder and name it controllers, then inside the controllers folder add a file and name it products.ts and add the code below.

import { v4 } from "https://deno.land/std/uuid/mod.ts";
import { Product } from "../types.ts";

let products: Product[] = [
  {
    id: "1",
    name: "Product One",
    description: "This is Product One",
    price: 50,
  },
  {
    id: "2",
    name: "Product Two",
    description: "This is Product Two",
    price: 100,
  },
  {
    id: "3",
    name: "Product Three",
    description: "This is Product Three",
    price: 150,
  },
];

const getProducts = ({ response }: { response: any }) => {
  response.body = {
    success: true,
    data: products,
  };
};

// Get A Product @route GET /API/products
const getProduct = (
  { params, response }: { params: { id: string }; response: any },
) => {
  const product: Product | undefined = products.find((p) => p.id === params.id);

  if (product) {
    response.status = 200;
    response.body = {
      success: true,
      data: product,
    };
  } else {
    response.status = 404;
    response.body = {
      success: false,
      msg: "No Product Found",
    };
  }
};

// Add A Product @route POST /API/products
const addProduct = async (
  { request, response }: { request: any; response: any },
) => {
  const body = await request.body();

  if (!request.hasBody) {
    response.status = 400;
    response.body = {
      success: false,
      msg: "No Data",
    };
  } else {
    const product: Product = body.value;
    product.id = v4.generate();
    products.push(product);
    response.status = 201;
    response.body = {
      success: true,
      data: product,
    };
  }
};

// Update A Product @route PUT /API/products/:id
const updateProduct = async (
  { params, request, response }: {
    params: { id: string };
    request: any;
    response: any;
  },
) => {
  const product: Product | undefined = products.find((p) => p.id === params.id);

  if (product) {
    const body = await request.body();

    const updateData: { name?: string; description?: string; price?: number } =
      body.value;

    products = products.map((p) =>
      p.id === params.id ? { ...p, ...updateData } : p
    );

    response.status = 200;
    response.body = {
      success: true,
      data: products,
    };
  } else {
    response.status = 404;
    response.body = {
      success: false,
      msg: "No Product Found",
    };
  }
};

// Delete A Product @route DELETE /API/products/:id
const deleteProduct = (
  { params, response }: { params: { id: string }; response: any },
) => {
  products = products.filter((p) => p.id !== params.id);
  response.body = {
    success: true,
    msg: "Product Removed",
  };
};

export { getProducts, getProduct, addProduct, updateProduct, deleteProduct };

I wont explain each and every bit of the code above because it is long, but what that file does is we import V4 which is version 4 of the uuid. uuid is a module that generates id automatically. for instance when we use auto-increment id field we will get like 1,2,3 etc but with uuid we will an id that looks like "925ba5dc-57a5-4706-b24a-5864b6efad04".

Then we are now importing our product type from types.ts which we will also create a few, and that's the fun thing about TypeScript, you can create your types apart from number, string...

After that we are having our products and then we create logics for the different methods used within our API. If you dont understand anything in the file, leave a comment and I'll reply as soon as I can.

Lastly we now create our types.ts file. Create a file in the main directory outside of the controllers folder and name it types.ts and have the code below:

interface Product {
  id: string;
  name: string;
  description: string;
  price: number;
}

In the file we are creating our interface Product which takes id as a string, name as a string, description as a string and price as a number.

 

That's all we need for now. Now open your terminal and type in

deno run --allow-net server.ts

This will start our server on Port 5000 and you'll get a message "Server Running on Port 5000 as shown below

You can now open postman and have 

localhost:5000/API/products

Use a GET method and this will show you all the products as shiwn below, use different methods as stated above and see the different outputs you get.

 

That's all I had for you today, hope ou learned something today. See ou soon and don't forget to give an upvote if it helped. You can find the whole repository here

See you soon