Skip to content

Instantly share code, notes, and snippets.

@iamsarthakjoshi
Created July 9, 2021 05:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iamsarthakjoshi/3bb275187ef5c8b083e46484b2bdc46a to your computer and use it in GitHub Desktop.
Save iamsarthakjoshi/3bb275187ef5c8b083e46484b2bdc46a to your computer and use it in GitHub Desktop.
Typescript & Node.js Clean Architecture

Typescript & Node.js Clean Architecture

Project Structure

.
└── src
    ├── app                         → Application services layer
    │   └── usecase                 → Application business rules
    ├── domain                      → Enterprise core business layer such as domain model objects (Aggregates, Entities, Value Objects) and repository interfaces
    └── infra                       → Frameworks, drivers and tools such as Database, the Web Framework, mailing/logging/glue code etc.
        ├── config                  → Application configuration files, modules and services
        ├── data                    → Database ORMs middleware
        ├── entrypoint              → Main application entry point
        │   └── web
        │       └── controller
        └── repositories            → Implementation of domain repository interfaces

src: This is a project directory one level up from the root directory. It hold all necessary folders and files that make clean architecture.

  • domain: It's core/domain layer. It does not depends on any layer as outer layer rather depends on it. It holds all the core entities of the domain. For example: If a domain has User as a core component, that User becomes the part of domain layer.

  • app: It's an application layer. It consists of:

    • usecase: It's an interactor layer. It also acts as a service component which interacts with the domain layer. It injects repositories and implements certain boundry|port, in other words an interface.
  • infra: It's an infrastructure layer. It is also the outermost layer which may have server components as follows:

    • config: Holds configuration of entier layer and the project itself.
    • data: The database could be any of your choice. Holds database schemas.
    • repository: Repository is a place/file (or a class that implements certain boundry|port) which mainly has CRUD operations implementation (for rg: createUser, deleteUser) and gets injected in particular usecases. Also, it could be for each type of database. For example: UserRepositoryMongoDb, UserRepositoryMysql, etc. This way usecase/service layer will be intact and does not need to get updated per database type, just inject UserRepositoryMongoDb or UserRepositoryMysql.
    • framework: any framework of your choice. For example: express
    • entrypoint: It's a presentation layer. It is also the outermost layer which may have several components as follows:
      • web/controller: That receives HTTP req and then send back approriate response. It implements Input Port or an Interface (for example: IUserInputDto) that governs the incoming values, and communicates with the presenter. Controller injects the usecases as per need.
      • presenter: A component that pass the response to the UI. It implements Output Port or an Interface (for example: IUserOutoutDto) that governs the outgoing values (DTO), and presents to the UI.
      • gateway: This could be an API Gateway.
    • ui: This could be a view of the application. For example: a console prompt, web UI.

Both Input & Output Ports are called Boundry or Interface to govern the incoming/outgoing data or make mandatory to implement any function/method/properties that must be implemented. They're implemented by the usecases and repositories. It's a good practice to add a definition folder under each layer so that you could define types, interface or base-class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment