90-Nodejs Course 2023: Restful Routes: Restful Resource
Tags: node, typescript, mongodb, fastify
Published: 2022-12-08 07:22:46

---
title: 90-Nodejs Course 2023: Restful Routes: Restful Resource
published: true
description: 
series: Nodejs Course 2023
tags: nodejs, typescript, mongodb, fastify
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ub6zoat0ne7t9ediwd29.png
# Use a ratio of 100:42 for best results.
---

So, we got to know what is meant by `Restful Api` concept, now let's start implementing it in our project.

## Workflow

Before we start implementing the `Restful Api` concept, we need to know the workflow of the project, so we can understand how to implement it.

Our first step is to create a `route.resource` method, this method will be used to generate all the routes for a specific resource, so we need to pass the resource name to it.

This method is supposed to generate the following routes:

1. `GET /resource` - Get all resources
2. `GET /resource/:id` - Get a specific resource
3. `POST /resource` - Create a new resource
4. `PUT /resource/:id` - Update a specific resource
5. `DELETE /resource/:id` - Delete a specific resource
6. `PATCH /resource/:id` - Update a specific resource

The second argument is resource object, that object should have certain methods, each method represents a handler for a specific route, so we need to pass the handler for each route to the resource object.

For example:

```ts

const resource = {
  list: listUsers,
  get: getSingleUser,
  create: createUser,
  update: updateUser,
  delete: deleteUser,
  patch: patchUser,
};
```

So based on what the resource contains, we'll add the routes accordingly.

The other good feature is that we can also pass route options to be used with these routes, as we do with single route call.

We'll also use route name feature to name the routes, so we can use them in the future.

Enough talking now let's move to the code.

## Implementation

First off, let's define our `Resource Type`.

```ts
// src/core/router/types.ts

/** Route resource */
export type RouteResource = {
  /**
   * list route
   */
  list?: RouteHandler;
  /**
   * Single resource route
   */
  get?: RouteHandler;
  /**
   * Create resource route
   */
  create?: RouteHandler;
  /**
   * Update resource route
   */
  update?: RouteHandler;
  /**
   * Patch resource route
   */
  patch?: RouteHandler;
  /**
   * Delete resource route
   */
  delete?: RouteHandler;
};
```

So we just defined a type that is used to define the resource object, it contains all the methods that will be used to handle the routes, the handler is the same as the single route handler, so nothing new here.

## Resource Method

Now let's define our `resource` method, this method will receive three arguments, the first one is the resource path, the second one is the resource object, and the third one is the route options.

We need also to set the resource name if it is not passed in the options, let's see in action.

```ts
// src/core/router/index.ts
import { ltrim, merge, toCamelCase } from "@mongez/reinforcements";
// ...
  /**
   * Add full restful resource routes
   * This method will generate the following routes:
   * 1. GET /path: list all resources
   * 2. GET /path/:id: get a single resource
   * 3. POST /path: create a new resource
   * 4. PUT /path/:id: update a resource
   * 5. DELETE /path/:id: delete a resource
   * 6. PATCH /path/:id: update a resource partially
   */
  public resource(
    path: string,
    resource: RouteResource,
    options: RouteOptions = {},
  ) {
    // get base resource name
    const baseResourceName = options.name || toCamelCase(ltrim(path, "/"));

    if (resource.list) {
      const resourceName = baseResourceName + ".list";
      this.get(path, resource.list, { ...options, name: resourceName });
    }

    if (resource.get) {
      const resourceName = baseResourceName + ".get";

      this.get(path + "/:id", resource.get, { ...options, name: resourceName });
    }

    if (resource.create) {
      const resourceName = baseResourceName + ".create";

      this.post(path, resource.create, { ...options, name: resourceName });
    }

    if (resource.update) {
      const resourceName = baseResourceName + ".update";

      this.put(path + "/:id", resource.update, {
        ...options,
        name: resourceName,
      });
    }

    if (resource.patch) {
      const resourceName = baseResourceName + ".patch";

      this.patch(path + "/:id", resource.patch, {
        ...options,
        name: resourceName,
      });
    }

    if (resource.delete) {
      const resourceName = baseResourceName + ".delete";

      this.delete(path + "/:id", resource.delete, {
        ...options,
        name: resourceName,
      });
    }

    return this;
  }
```

Nothing hard here, firstly i got the `baseResourceName`, you can pass it in the options list, otherwise it will be taken from the path.

```ts
const baseResourceName = options.name || toCamelCase(ltrim(path, "/"));
```

[toCamelCase](https://github.com/hassanzohdy/reinforcements#camel-case) is used to transform the path to camel case, for example `users-groups` will be transformed to `usersGroups`.

And i used [ltrim](https://github.com/hassanzohdy/reinforcements#left-trimming-values-from-string) to remove the `/` from the path, so if the path is `/users` it will be `users`.

Then we checked for each route type, we started with `list`, if it exists we'll add the route, we used the `baseResourceName` and added `.list` to it, so the route name will be `users.list` for example, then we added it as a route to our router system.

And the same applies for the rest of the routes.

## Usage

Now let's see how we can use it.

```ts
// src/app/users/routes.ts
import router from "core/router";
import login from "./controllers/auth/login";
import listUsers from './controllers/users/list';
import getUser from './controllers/users/get';
import createUser from './controllers/users/create';
import updateUser from './controllers/users/update';
import patchUser from './controllers/users/patch';

const restfulUser = {
    list: listUsers,
    get: getUser,
    create: createUser,
    update: updateUser,
    patch: patchUser,
};

router.resource("/users", restfulUser);

router.post("/login", login);
```

And that's it!, now you can use the resource routes in your application.

## 🎨 Conclusion

In this article, we learned how to create a resource route, and how to use it in our application.

In our next article, we'll see how to create our first Restful Class, that manages everything within a one place!, stay tuned.

## ☕♨️ Buy me a Coffee ♨️☕

If you enjoy my articles and see it useful to you, you may [buy me a coffee](https://www.paypal.com/paypalme/hassanzohdy), it will help me to keep going and keep creating more content.

## 🚀 Project Repository

You can find the latest updates of this project on [Github](https://github.com/hassanzohdy/nodejs-2023)

## 😍 Join our community

Join our community on [Discord](https://discord.gg/pb2vmdfhGf) to get help and support (Node Js 2023 Channel).

## 🎞️ Video Course (Arabic Voice)

If you want to learn this course in video format, you can find it on [Youtube](https://www.youtube.com/playlist?list=PLGO8ntvxgiZMJc7RN2lIq9WmMOlWZGzmz), the course is in Arabic language.

## 📚 Bonus Content 📚

You may have a look at these articles, it will definitely boost your knowledge and productivity.

General Topics

* [Event Driven Architecture: A Practical Guide in Javascript](https://dev.to/hassanzohdy/event-driven-architecture-the-best-paradigm-that-i-love-to-work-with-in-javascript-and-node-js-1gnk)
* [Best Practices For Case Styles: Camel, Pascal, Snake, and Kebab Case In Node And Javascript](https://dev.to/hassanzohdy/best-practices-for-case-styles-camel-pascal-snake-and-kebab-case-in-node-and-javascript-55oi)
* [After 6 years of practicing MongoDB, Here are my thoughts on MongoDB vs MySQL
](https://dev.to/hassanzohdy/after-6-years-of-practicing-mongodb-here-are-my-thoughts-on-mongodb-vs-mysql-574b)

Packages & Libraries

* [Collections: Your ultimate Javascript Arrays Manager](https://dev.to/hassanzohdy/collections-your-ultimate-javascript-array-handler-3o15)
* [Supportive Is: an elegant utility to check types of values in JavaScript](https://dev.to/hassanzohdy/supportive-is-an-elegant-utility-to-check-types-of-values-in-javascript-1b3e)
* [Localization: An agnostic i18n package to manage localization in your project](https://dev.to/hassanzohdy/mongez-localization-the-simplest-way-to-translate-your-website-regardless-your-favorite-framework-4gi3)

 React Js Packages

* [useFetcher: easiest way to fetch data in React Js](https://dev.to/hassanzohdy/usefetcher-the-easiest-way-to-fetch-data-in-react-45o9)

Courses (Articles)

* [OOP In JS And TS From The Very Beginning](https://dev.to/hassanzohdy/jsts-oop-course-1-introduction-2ld)
* [ES6++: The Ultimate Guide to ES6 and Beyond](https://dev.to/hassanzohdy/es6-1-introduction-h3e)
* [React Js: Let"s Create File Manager With React Js and Node Js](https://dev.to/hassanzohdy/lets-create-a-file-manager-from-scratch-with-react-and-typescript-chapter-i-a-good-way-to-expand-your-experience-5g4k)