/node-service-api-boilerplate

DDD/Clean Architecture inspired boilerplate for Node web APIs (inspired by https://github.com/talyssonoc/node-api-boilerplate/)

Primary LanguageJavaScriptMIT LicenseMIT

Node Service/API Boilerplate

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.

Table of Contents

Features

Requirements

Getting Started

  1. Clone the repository.
$ git clone git@github.com:agaphetos/node-service-api-boilerplate.git
  1. Install package dependencies.
$ npm install
  1. Run the application. Application is running on http://localhost:3000/. You can also see the sample API documentation on http://localhost:3000/api/v1/docs
$ npm start

Directories

Directory structure of the project

  • config - Configuration Setup for the API
  • src - Source Code inspired by DDD and Clean Architecture

Configuration

Configurations for are ready for the following with the use of ENVIRONMENT VARIABLES:

Application Configuration

This contains Application specific configuration like API Integration, Service Configuration and all related for the application you are building.

Logging Configuration

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.

Database Configuration

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/.

Multi-tenant Database Setup

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.

  1. Setup a datasource registration on config/database.js by adding a property (key: value) on the exportable object. See example on config/database.js.example and specification below:
<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,
},
  1. Add the desired ENVIRONMENT VARIABLES on .env or env.yml. See specification below:

.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.

  1. Create a .sequelizerc for the specific datasource. See example on .sequelize.example

  2. Add an npm-script entry 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.

Runtime Setup

Defined ENVIRONMENT VARIABLES are loaded by automatically upon runtime.

There are 2 runtimes supported by our application.

Server-based Runtime

The ENVIRONMENT VARIABLES are loaded using dotenv. Setup with the use of .env file. See sample .env.example

Serverless Runtime

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

Source Code

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.

Application layer

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.

Domain layer

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.

Infrastructure layer

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.

Interfaces layer

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).

Documentation

Documentations about the API:

API Specifications

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/.

Deployment

Currently our application supports the following deployments:

Server Hosted Deployment

$ npm start

Serverless Deployment

$ sls deploy -s [your-stage]

Containerizing Application

The contains separate Dockerfile for development and production stage releases.

Building a Docker Image

To build a docker image. Use docker build command.

$ docker build -t <workspace/image-name:version> -f <stage>.Dockerfile

Running the Docker Image

To 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>

Credits