nestjs-boilerplate Agent Skills & AI Rules

GitHub

NestJS boilerplate. Auth, TypeORM, Mongoose, Postgres, MongoDB, Mailing, I18N, Docker.

4,302 stars TypeScript TypeScript 1 file ยท ~11,368 tokens #auth#boilerplate#ci#crud#database#docker#e2e#i18n
RAW Rules
3 Discovered Rules โ€ข ~2,146 Estimated Tokens
Quick:
Loading skill content...

docs - System Architecture & Module Boundaries

docs/architecture.md project-spec ~1,009 tokens
Raw
# Architecture

---

## Table of Contents <!-- omit in toc -->

- [Hexagonal Architecture](#hexagonal-architecture)
- [Motivation](#motivation)
- [Description of the module structure](#description-of-the-module-structure)
- [Recommendations](#recommendations)
  - [Repository](#repository)
- [FAQ](#faq)
  - [Is there a way to generate a new resource (controller, service, DTOs, etc) with Hexagonal Architecture?](#is-there-a-way-to-generate-a-new-resource-controller-service-dtos-etc-with-hexagonal-architecture)
- [Links](#links)

---

## Hexagonal Architecture

NestJS Boilerplate is based on [Hexagonal Architecture](https://en.wikipedia.org/wiki/Hexagonal_architecture_(software)). This architecture is also known as Ports and Adapters.

![Hexagonal Architecture Diagram](https://github.com/brocoders/nestjs-boilerplate/assets/6001723/6a6a763e-d1c9-43cc-910a-617cda3a71db)

## Motivation

The main reason for using Hexagonal Architecture is to separate the business logic from the infrastructure. This separation allows us to easily change the database, the way of uploading files, or any other infrastructure without changing the business logic.

## Description of the module structure

```txt
.
โ”œโ”€โ”€ domain
โ”‚   โ””โ”€โ”€ [DOMAIN_ENTITY].ts
โ”œโ”€โ”€ dto
โ”‚   โ”œโ”€โ”€ create.dto.ts
โ”‚   โ”œโ”€โ”€ find-all.dto.ts
โ”‚   โ””โ”€โ”€ update.dto.ts
โ”œโ”€โ”€ infrastructure
โ”‚   โ””โ”€โ”€ persistence
โ”‚       โ”œโ”€โ”€ document
โ”‚       โ”‚   โ”œโ”€โ”€ document-persistence.module.ts
โ”‚       โ”‚   โ”œโ”€โ”€ entities
โ”‚       โ”‚   โ”‚   โ””โ”€โ”€ [SCHEMA].ts
โ”‚       โ”‚   โ”œโ”€โ”€ mappers
โ”‚       โ”‚   โ”‚   โ””โ”€โ”€ [MAPPER].ts
โ”‚       โ”‚   โ””โ”€โ”€ repositories
โ”‚       โ”‚       โ””โ”€โ”€ [ADAPTER].repository.ts
โ”‚       โ”œโ”€โ”€ relational
โ”‚       โ”‚   โ”œโ”€โ”€ entities
โ”‚       โ”‚   โ”‚   โ””โ”€โ”€ [ENTITY].ts
โ”‚       โ”‚   โ”œโ”€โ”€ mappers
โ”‚       โ”‚   โ”‚   โ””โ”€โ”€ [MAPPER].ts
โ”‚       โ”‚   โ”œโ”€โ”€ relational-persistence.module.ts
โ”‚       โ”‚   โ””โ”€โ”€ repositories
โ”‚       โ”‚       โ””โ”€โ”€ [ADAPTER].repository.ts
โ”‚       โ””โ”€โ”€ [PORT].repository.ts
โ”œโ”€โ”€ controller.ts
โ”œโ”€โ”€ module.ts
โ””โ”€โ”€ service.ts
```

`[DOMAIN ENTITY].ts` represents an entity used in the business logic. Domain entity has no dependencies on the database or any other infrastructure.

`[SCHEMA].ts` represents the **database structure**. It is used in the document-oriented database (MongoDB).

`[ENTITY].ts` represents the **database structure**. It is used in the relational database (PostgreSQL).

`[MAPPER].ts` is a mapper that converts **database entity** to **domain entity** and vice versa.

`[PORT].repository.ts` is a repository **port** that defines the methods for interacting with the database.

`[ADAPTER].repository.ts` is a repository that implements the `[PORT].repository.ts`. It is used to interact with the database.

`infrastructure` folder - contains all the infrastructure-related components such as `persistence`, `uploader`, `senders`, etc.

Each component has `port` and `adapters`. `Port` is interface that define the methods for interacting with the infrastructure. `Adapters` are implementations of the `port`.

## Recommendations

### Repository

Don't try to create universal methods in the repository because they are difficult to extend during the project's life. Instead of this create methods with a single responsibility.

```typescript
// โŒ
export class UsersRelationalRepository implements UserRepository {
  async find(condition: UniversalConditionInterface): Promise<User> {
    // ...
  }
}

// โœ…
export class UsersRelationalRepository implements UserRepository {
  async findByEmail(email: string): Promise<User> {
    // ...
  }
  
  async findByRoles(roles: string[]): Promise<User> {
    // ...
  }
  
  async findByIds(ids: string[]): Promise<User> {
    // ...
  }
}
```

---

## FAQ

### Is there a way to generate a new resource (controller, service, DTOs, etc) with Hexagonal Architecture?

Yes, you can use the [CLI](cli.md) to generate a new resource with Hexagonal Architecture.

---

## Links

- [Dependency Inversion Principle](https://trilon.io/blog/dependency-inversion-principle) with NestJS.

---

Previous: [Installing and Running](installing-and-running.md)

Next: [Command Line Interface](cli.md)