Node.js boilerplate for building Services/API focused on separation of concerns and scalability.
It is heavily inspired by node-api-boilerplate of Talysson De Oliveira.
- Features
- Requirements
- Getting Started
- Directories
- Configuration
- Source Code
- Documentation
- Deployment
- Credits
Multilayer folder structure- following Domain Driven Design and Clean ArchitectureProduction Ready- setup with PM2Scalable Web Server- uses Express.jsDependency Injection- using awilixServerless Ready- via serverless frameworkContainerized Application Ready- via dockerOpenAPI 3.0 Documentation- using swaggerDatabase Integration- ORM support using sequelizeMulti-tenant Database SetupStructured Logging- using winstonCode Linting- using eslint following airbnb-style-guideBDD/TDD Ready- test suite using mocha and chai
- Node.js
v.10+- Javascript Runtime - npm - Node Package Manager
- sequelize-cli - for Database ORM Tool
- serverless - for Serverless Framework
- docker - for Containerizing Application
- Clone the repository.
$ git clone [email protected]:agaphetos/node-service-api-boilerplate.git- Install package dependencies.
$ npm install- Run the application. Application is running on http://localhost:3000/. You can also see the sample
API documentationon http://localhost:3000/api/v1/docs
$ npm startDirectory structure of the project
Configurations for are ready for the following with the use of ENVIRONMENT VARIABLES:
This contains Application specific configuration like API Integration, Service Configuration and all related for the application you are building.
We are using winston as our logging library.
By default, our application uses structured logging pattern using json format.
To customize the logging configuration. There is an example config file logging.js.example.
For more detailed usage about winston. See official documentation on https://github.com/winstonjs/winston.
We are using sequelize v5 as our ORM.
By default, our application loads our staged environment from config/database.js file.
To define the database connection and options. There is an example config file database.js.example.
For more detailed usage about sequelize. See official documentation on https://sequelize.org/master/.
A multi-tenant database allows us to support multiple database for our infra/database codebase.
This setup is inspired by the article Using multiple databases with NodeJS and Sequelize from Medium.
The steps below will help you setup a specific database source.
- Setup a datasource registration on
config/database.jsby adding a property(key: value)on the exportable object. Seeexampleon config/database.js.example andspecificationbelow:
<datasource-identifier>: {
host: process.env.SPECIFIC_DB_HOST,
username: process.env.SPECIFIC_DB_USERNAME,
password: process.env.SPECIFIC_DB_PASSWORD,
database: process.env.SPECIFIC_DB_DATABASE,
dialect: process.env.SPECIFIC_DB_DIALECT,
...options,
},- Add the desired
ENVIRONMENT VARIABLESon.envorenv.yml. Seespecificationbelow:
.env: See example on .env.example
SPECIFIC_DB_HOST=<value-here>
SPECIFIC_DB_USERNAME=<value-here>
SPECIFIC_DB_PASSWORD=<value-here>
SPECIFIC_DB_DATABASE=<value-here>
SPECIFIC_DB_DIALECT=<value-here>env.yml: See example on env.yml.example
<stage-name>:
SPECIFIC_DB_HOST: <value-here>
SPECIFIC_DB_USERNAME: <value-here>
SPECIFIC_DB_PASSWORD: <value-here>
SPECIFIC_DB_DATABASE: <value-here>
SPECIFIC_DB_DIALECT: <value-here>Note: The steps above (1 and 2) will enable the application to load database models to our application instance.
-
Create a
.sequelizercfor the specific datasource. Seeexampleon .sequelize.example -
Add an
npm-scriptentry for the datasource instance. See specification below:
{
"scripts": {
...,
"sequelize:<datasource-identifier>:migrate": "sequelize --options-path ./.sequelize-<datasource-identifier> --env <datasource-identifier> db:migrate",
"sequelize:<datasource-identifier>:migrate:undo": "sequelize --options-path ./.sequelize-<datasource-identifier> --env <datasource-identifier> db:migrate:undo",
"sequelize:<datasource-identifier>:seed:all": "sequelize --options-path ./.sequelize-<datasource-identifier> --env <datasource-identifier> db:seed:all"
...
}
}NOTE: The steps above (3 and 4) will enable the us to execute sequelize commands like migrate and seed using the npm-script defined.
Defined ENVIRONMENT VARIABLES are loaded by automatically upon runtime.
There are 2 runtimes supported by our application.
The ENVIRONMENT VARIABLES are loaded using dotenv. Setup with the use of .env file. See sample .env.example
The ENVIRONMENT VARIABLES are loaded by serverless upon package deployment and offline execution. Setup with the use of env.yml file. See sample [env.yml.examp
The src/ directory contains the API source code.
It uses a folder structure and logical architecture focused on separation of concerns based in Domain-driven design and Clean architecture.
Instead of the classical controllers/models/services folders, we now have layers inside the src/ folder. Each of the folder layers is scoped by a namespace regarding the concern it is about.
The application layer is responsible to mediate between your input interfaces and your business domain. In this layer we'll have the use cases of your application and your application services.
Here you'll define your business domain classes, functions and services that compose your domain model. All your business rules should be declared in this layer so the application layer can use it to compose your use cases.
This is the lowest of the layers. In the infra layer you'll have the communication with what is outside your application, like the database, external services and direct communication with frameworks.
This folder contains all the entry points for your application. From the beginning here's where your Express controllers will be (inside the interfaces/http folder).
Documentations about the API:
Shows the API Specs following OAS3 standard and was written following a swagger.yaml template using swagger.
The sample API Specification can be seen on http://localhost:3000/api/v1/docs/.
For more detailed usage about swagger. See official documentation on https://swagger.io/docs/specification/about/.
Currently our application supports the following deployments:
$ npm start$ sls deploy -s [your-stage]The contains separate Dockerfile for development and production stage releases.
To build a docker image. Use docker build command.
$ docker build -t <workspace/image-name:version> -f <stage>.DockerfileTo run a docker image. Use docker run command.
Use the following options for running our image:
-p- specify port mappings-d- docker image to run-e, --env, --env-file- specify an environment variable or environment file
$ docker run -p <machine-port>:<container-port> -d <workspace/image-name>- Talysson De Oliveira -
node-api-boilerplate - Lucas Spreiter -
multi-tenant database setup