Create REST-API with Clean Architecture in NestJS

Arsy Opraza
Level Up Coding
Published in
6 min readJul 11, 2023

--

In developing applications, especially large-scale applications, it important to design good architecture so that the application is easy to develop in the future when the company or organization scale up or more bigger. In this article we will learn to design application architectures with Clean Architecture. A professional developer who can design good applications is an added value, so take a good look at this material!

What is clean architecture?

Clean architecture is a software architecture that applies the concept of clean code and SOLID principles in building scalable, testable, and maintainable applications.

Clean architecture was popularized by Robert C. Martin, better known as “Uncle Bob” in 2008.

Clean architecture focuses on separating business logic from external frameworks or applications. Each component is independent and does not depend on specific external libraries.

Clean architecture is divided into 4 layers, namely:

  • Entities (Enterprise Business Rules)

Entities is a description of the business rules or business objects of the application. In this layer are written application business rules that are static and do not change. Entities will not change when external changes occur. Entities can be objects with methods, or a collection of data structures and functions.

  • Use Cases (Application Business Rules)

Use cases orchestrate the flow of data to and from entities, and direct entities to use business rules to achieve the objective of business needs. When a use case changes, it will not affect entities. Likewise, changes that occur in externals such as databases and UI will not affect use cases.

  • Interface adapters

This layer is a collection of adapters that translate data into formats used by use cases and entities and also translate data into formats used by external layers such as frameworks.

  • Frameworks and drivers

The outer layer that consists of frameworks and tools such as databases, web frameworks and others. Not much code is written in this layer except for the need to communicate to the next layer inside.

The Dependency Rule

The dependency rule says that code dependencies can only be inward-looking, meaning that the inner layer cannot know anything about the outer layer and does not depend on the outer layer. Instead, the outer layer depends on the inner layer.

Benefits of Clean Architecture

  • Independent of Framework: Not dependent on frameworks and libraries because frameworks and libraries are only tools.
  • Testable: Business rules can be tested easily because they do not depend on interfaces, databases, or external elements.
  • Independent of UI: User interface can be changed easily without changing the whole system.
  • Independent of Database: Database can be changed from for example Oracle to MongoDB, business rules are not tied to the database.
  • Independent of External: The existing business rule does not know what is outside it.

Clean Architecture Example

To understand the clean architecture, we’ll practice creating a simple project.

Prepare the project

Create a new project named clean-arch with the following command: nest new clean-arch

Delete app.controller.ts and app.service.ts. Then create a folder structure as follows:

Currently we have 4 main folders:
- applications: This is the applications business layer, in this folder it will contain the existing business flows of the application in the form of use cases.
- domains : Represents the enterprise business layer in the form of models and abstractions from the repository.
- infrastructures : Contains frameworks and external tools, such as database, repository configuration and implementation.
- presentations : Adapter that connects the use case with the external layer.

Then install the dependencies package that will be used with the command: npm install @nestjs/config @nestjs/typeorm typeorm pg --save

Project configuration

Create folder config in domains and add interface config called database.interface.ts

Then, create a config config folder on the infrastructures folder. Inside the config folder, add environment-config folder.

Then, add environment module and service with the names environment-config.module.ts and environment-config.service.ts

And implement database interface in environment-config service.

Then, in the environment-config module add the following code:

Then, change the start:dev script in package.json

"start:dev": "NODE_ENV=development nest start --watch",

And add .env file with the following code:

DATABASE_HOST=127.0.0.1
DATABASE_PORT=32768
DATABASE_USER=your_user
DATABASE_PASSWORD=your_password
DATABASE_NAME=your_db_name
DATABASE_SCHEMA=public
DATABASE_SYNCHRONIZE=false
NODE_ENV=development

TypeORM Configuration

To make TypeORM can access the database, add a new module called typeorm.module.ts in the typeormfolder ininfrastructures/config.

Then, add typeorm.config.ts in the typeorm folder with the following code:

Prepare Database

Create folder database outside thesrc and create folder migrations.

Create new script on package.jsonfor the migrations database.

"typeorm": "typeorm-ts-node-commonjs",
"typeorm_src": "typeorm-ts-node-commonjs -d src/infrastructures/config/typeorm/typeorm.config.ts"

And create new migrations with following command:

npx typeorm migration:create ./database/migrations/User

The command will generate migration file, to create the database table follow this code:

Run the migration with this command:

npm run typeorm_src migration:run

Entity

Entity is a class that maps to database tables. Entities can be created by adding the @Entity() flag. Entities are in infrastructures so create a new folder called entitiesand add the user.entity.ts file. Add the following code:

Add the user model in the domainsby adding a new folder named model in the domains. Then create a new file user.ts with the following code:

Domains

The next step is to create a repository interface in domains. Create a new folder named repositoriesthen add the user.repository.ts file with the following code:

To implement this interface, add therepositories folder in infrastructures, then add the repository.module.ts in repositories folder with the following code:

The code above will cause an error, because the user repository has not been created yet, for that add user.repository.ts in the same folder with the following code:

Applications

Next we will add use cases, because use cases are in the applications layer, create a use-cases folder in applications and add the user.usecase.tsfile which contains the following code:

Inside this use case contains code, that regulates the flow of data to and from the entity, each use case will only handle one action, for example the use case get all users which aims to get data for all users.

Next, we need a use cases proxy that will connect the use cases with the infrastructure. So create a usecase-proxyfolder in infrastructures and add module usecase-proxy.module.ts and write the following code:

Presentations

Next we will add a presentations layer. Add a user folder inside presentations and create a user controller in presentations/user.

Then add the following code:

Then add the user module which contains the user controller.

The next step is to edit the app.module.tsthat was generated by nest.

In the app module we will import Usecase Proxy, User Module, and Environment Config Module.

Then add the following code inmain.ts:

app.setGlobalPrefix('api/v1');

Its function is to add a prefix in front of the url end point.

Running App

To run and test the API that we have created, run the following command:

npm run start:dev

Then, access this link to test your app http://localhost:3000/api/v1/users

Summary

So far, we have known the theory of Clean Architecture and have also tried to make a Clean Architecture project.

Clean architecture is a software architecture that applies the concept of clean code and the SOLID principle in building scalable, testable and maintainable applications. Clean architecture was popularized by Robert C. Martin, or better known as “Uncle Bob” in 2008.

The benefits of a clean architecture are:

  1. Independent of Framework.
  2. Testable.
  3. Independent of UI.
  4. Independent of Databases.
  5. Independent of External.

For code example you can visit this github repository: https://github.com/arasopraza/NestJS-Starter-Template.git

Want to connect?
https://www.linkedin.com/in/arasopraza/
https://github.com/arasopraza

Level Up Coding

Thanks for being a part of our community! Before you go:

🔔 Follow us: Twitter | LinkedIn | Newsletter

🚀👉 Join the Level Up talent collective and find an amazing job

--

--