DEV Community

SJ W
SJ W

Posted on

Online Bookshop Project (Part 3)

Introduction

Back at it again with the project for developing an e-commerce website for selling books. In the previous post, we went over the phase of designing the database schema for the system using the E-R diagram. Through the process, we were able to identify a few key entities - User, Book and Order - pivotal in storing data that we may need for the system. And each entity shares relationships with various additional entities whose existence came about with the help of the concept of normalization, to avoid the duplication of the data. For this post, there are going to be two main things that are going to be covered: the DB initialization and creating the project using Express.js. Since we have completed the schema for the DB in the last post, we will move on to actually implementing them using MariaDB, by creating the new DB and a number of its tables. And also, we are finally going to get into the real fun of the project, which is coding! Since the bootcamp I attend is fully based on JavaScript from frontend to backend, we will go over some of the endpoints that I identified, and start implementing the API endpoints using Express.js and various third-party libraries from Node.js.

Identifying API Endpoints

An API is essentially an interface that allows two different programs to talk to one another. Think of it as a bridge that connects one or more independent programs to facilitate the data exchanges. For example, the system I am creating is a facilitator of the data exchange between the browser and the database for the necessary data for buying books. Through the system, a user may be able to create, fetch, update and delete various information that it has access to. The system exposes a various number of "bridges" designed for the specific functionalities that they try to perform for end users.

Since I am trying to separate the frontend and backend using the different technologies - Express.js and React.js, the backend will return data to users in the form of JSON for the most part, which is parsed by the frontend, and ultimately rendered and viewed as a component for display for the users. The backend system will adhere to various principles in regard to what we call REST. REST is an architectural style for distributing data using HTTP endpoints. Offering the guidelines rather than a set of rules and laws that one must strictly adhere to, it provides developers freedom to implement the system in a variety of ways. There are various principles that one must conform to for the system to be considered RESTful, and if you are interested in what makes the system RESTful, please check out the link here for more information.

With my mind in REST :), It is time to create each URL for every endpoint that gives off the vibes of REST. An endpoint is where the system and a user meet to interact with one another. There are two main important aspects when it comes to each HTTP endpoint - name and method.

  • Name - Since it represents a specific functionality or the resource that one intends to exchange or perform, the URL of an endpoint must be both simple and descriptive at face value. For example, If I create an endpoint for returning the information of all the books in the system at the moment, it might be better to stick with something like "/books". Just from the name "/books", you can easily tell that it has something to do with books. To go further, if you want an endpoint that has to do with a specific book, you may utilize the URL, such as "/books/{:book_id}" - replace the curly braces and its content with a unique ID of a book you need.
  • Method - In addition to the mere name of an endpoint, each endpoint may have one or more methods that further describe the actions to undertake for the resource you are trying to access. For communication, the REST style uses the HTTP protocol, and it has four main methods that achieve what we call CRUD functions (Create, Read, Update, and Delete): POST, GET, PUT, DELETE. Let's say an endpoint "/users" allows the HTTP methods of POST, GET. With the POST method often being associated with submitting the information, we can use the endpoint "/users" of POST for creating a new user. And since the method GET is associated with fetching the existing information stored in the system, we can use the GET method to retrieve the information of all the users in a system.

As you can see in what I said, there is a hierarchy in each URL. For this project, the RESTful API endpoints will have their names starting with the most generic thing that you can have in the system - since we are making the backend for selling books online, books, orders, and users come to mind - and become more detailed as it goes further and gets appended by slashes (/). Here are the types of API endpoints that I identified and implemented as a result.

  • Authentication / Authorization
  • Authors
  • Books
  • Carts
  • Categories
  • Orders
  • Users

To run the e-commerce website for selling books, you can kind of guess the types of functionalities needed based on the list above. For example, at the very basic level, we need to control who can have access to various information at various levels. To control the access to information, we will have Authentication / Authorization, which represent functionalities that have to do with accessing the system in general. Some of the example include logging in and out, password change, etc. For the rest of the main entities, it will have the following functionalities, such as creating, retrieving, updating, and deleting objects.

Project Structure

Currently, the project is structured in various files and modules to keep it largely modular. Here is how I structured my project:

Project Structure

Let's try to go over some of the files and folders that are integral to the system.

  • controllers - This is the directory for various controller modules that contain various callback functions directly associated with API endpoints. Essentially, each file in this directory holds various functions that get invoked whenever a user makes a request to the system with a specific URL. Each callback function is directly tied to a specific endpoint. To learn more about what the controller is, check out this link here.
  • middlewares - This directory stores various middleware modules. S*imply, middleware is a function that gets invoked before the request makes its way to a function in one of the functions in the modules in the directory of controllers.* There are many different use cases for middleware, but it's really useful for deciding whether a user is authorized to access the resource or not. By checking the credentials provided by a user inside the request object, you can determine whether one has rights to access the certain information.
  • models - Sequelize uses a class called model to represent each table in DB. Since the system involves about more than 20 different tables of the DB for storing various critical information, creating a separate directory as a module for storing various models related to the project just makes sense, and most importantly, makes the project look a lot cleaner.
  • routes - The directory stores various files that store the API endpoints, from which the interaction between the system and users may occur. Each endpoint accepts the URL pattern and the callback functions that we define in files inside the directory of controllers as arguments.
  • services - The directory contains files which store the domain-specific logic. What I mean by domain is the entity, in which the system basically revolves around. For example, there is a service file just for handling the users-related logic, including the fetching of the information of a user, registration of a new user, etc. Also, since the system is all about selling books to users, you can easily infer that the system may contain logic for books as well.
  • db.js - A file for storing the information on the DB for the system. It initializes the instances of the modules of both MySQL and Sequelize. The system currently makes uses of both for the DB-related activities, but plans on making a full transition to Sequelize in the near future.
  • app.js - A file that starts the web server for accepting connections from users. This is where all the routes and middlewares get converged and merged into the server instance. To start the server, we run the following command in the project directory: "node ./app.js".

In the next blog post, we will go over each file and directory mentioned, and see how they interact with another in unison to form the backend of the e-commerce website for books!

Top comments (0)