The ultimate boilerplate to build REST APIs, Monolithic Modular and Microservice applications with Typescript.
Applications built with this boilerplate aims to run Anywhere, Anytime, Anyhow
. Dedicated servers
, virtual machines
, containers
, EC2
, ECS
or lambdas
, with Express
, Fastify
, Hyper-Express
and serverless
.
Security scan status | Tests in Main | Tests in Dev | Coverage in Main | Coverage in Dev |
---|---|---|---|---|
Overall Code Coverage
See it running as a Fastify application at:
It is built over a simplistic interpretation of Hexagonal Architecture, the Domain Driven Design and Event Driven Architecture philosophies.
It aims to be as much agnostic as possible, avoiding to add any frameworks or libraries to the stack.
It can be used as boilerplate to create modular monolith
or microservice
applications.
It implements incoming data validation, in the infrastructure level, through custom logic and based in the Open API specification.
It implements Basic and Bearer HTTP auth mechanism with a custom role system. Replaceable with other auth mechanisms. Tied to the API OAS spec.
It implements a HTTP web server port actually implementing adapters for aws Lambda
, Express.js
, Fastify
, Restify
and Hyper-Express
.
It implements an agnostic data repository port that actually writes/reads data from a In Memory database adapter. It is easily replaceable with Mongoose, Sequelize, etc.
Diagram illustrating the components:
https://miro.com/app/board/uXjVNq5nWJY=/?share_link_id=603404471489
The API OASdoc might be visualized at: http://localhost:3000/OASdoc/
Note: Remember to start the application before trying to reach it through the browser.
Request Handler - Controller - Domain Service - Domain Use Case - Data Repository - Data Adapter
Request Handler <- Controller <- Domain Service <- Domain Use Case <- Data Repository <- Data Adapter
It is the entry point in a HTTP
request made to the service.
It is a infrastructure's component.
It composes a Domain Event
using it income parameters such as body
and headers
. The domain event is passed to the Controller
by calling an associated method.
It may offers adapters for different outside service interfaces:
- HTTP - Lambdas (AWS, Azure, Google)
- HTTP - Express
- HTTP - Fastify
- HTTP - Hyper-Express
- HTTP - etc
- Events/SQS
- Events/SNS
- Events/etc
Controllers are responsible to forward the incoming Domain Events
to their specific corelated method in the Domain Service
.
It is a infrastructure's component.
It performs input data validation and access permission validation against the incoming Domain Events
using an associated OAS specification
It is the entry point for the application core (domains).
It is a domain's component.
May works as aggregation root / bounded contexts talking directly to injected domain services (aka domains and subdomains).
It should be the unique option working as communication interface between infrastructure
and domain components
.
It has a databaseClient adapter and a mutexService adapter injected on it instance.
It may lock resources to avoid race conditions by using the injected mutexService.
It knows it internal domain use cases.
It doesn't knows external domain use cases.
The Use Cases
, as the meaning of the words, are the use cases implemented in the Product.
They represents the features delivered to the customers.
It is a domain's component.
They known and are consumed by the Domain Service
component only.
They are the point entry for all Data Repository
calls. They handle Data Models
rather than raw objects.
They have an associated Data Repository
that is injected into it scope when calling Use Case
clojure.
The Data Repository
layer implements, in a agnostic manner, all actions related to the data persistency.
It does not talk directly to a database. I has a port to adapt different Database Clients.
It is a domain's component.
They are consumed by Use Case
component only.
The Data adapter
is a kind of database client implementation that respect the Data Repository
port.
It may implement database access through native drivers or ORMs and ODMs.
It is a domain's component.
- Node.js (^20 preferred) and pnpm
- Typescript
- Jest
- Redis - used to implement mutex (included as Docker image)
- OpenAPI official typings
- yaml - yaml parser
- Install the project
pnpm install
- Run Redis (if you don't have already)
pnpm run docker:composeredis
Run the entire test suite
pnpm test
Run unit tests
pnpm run test:unit
Run integration tests
pnpm run test:integration
Run integration tests - Express
pnpm run test:integration:express
Run integration tests - Fastify
pnpm run test:integration:fastify
Run integration tests - Restify
pnpm run test:integration:restify
Run integration tests - aws lambda
pnpm run test:integration:lambda
Run with Express
pnpm run dev:fastify
Run with Fastify
pnpm run dev:fastify
- Reach the URL http://localhost:3000/OASdoc/ and click in the
Version 1.0.0
. It will open the API documentation. - Reach http://localhost:3000/docs/1.0.0 to see the JSON version of the API documentation.
pnpm run dev:serverless
- Create a new branch.
Run the app in TDD mode - live reload of tests
pnpm run tdd
-
Make your changes.
-
Commit it
commit
It will run lint
and test
before asking info about the commit
pnpm run commit
- Ask for PR
lint code
pnpm run lint
lint && fix code
pnpm run lint:fix
bcryptjs - ^2.4.3
jsonwebtoken - ^9.0.2
openapi-types - ^12.1.3
reflect-metadata - ^0.2.2
uuid - ^9.0.1
xss - ^1.0.15
yaml - ^2.3.4
express - ^4.18.2
body-parser - ^1.20.2
cors - ^2.8.5
helmet - ^7.1.0
fastify - ^4.26.2
@fastify/cors - ^9.0.1
@fastify/formbody - ^7.4.0
@fastify/helmet - ^11.1.1
@fastify/static - ^7.0.1
restify - ^11.1.0 bunyan - ^1.8.15
hyper-express - ^6.14.12
live-directory - ^3.0.3
aws-lambda - ^1.0.7
serverless - ^4.2.4
redis - ^4.6.13