Skip to content

REST API Starter, using the good Node.js and architecture patterns and practices

License

Notifications You must be signed in to change notification settings

aagamezl/rest-api-starter

Repository files navigation

REST API Starter

Node.js CI Coverage Status js-standard-style GitHub issues GitHub

Node.js REST API Starter using best practices and patterns.

Included Technologies

This is a list of the main technologies included in this Starter:

  • Express Fast, unopinionated, minimalist web framework for Node.js.
  • Prisma Next-generation Node.js and TypeScript ORM.
  • Postgres the World's Most Advanced Open Source Relational Database.
  • Docker An open source containerization platform
  • Docker Compose tool for defining and running multi-container Docker applications
  • Ava Test runner.
  • Sinon Mocking library.
  • JSON Web Token is a compact, URL-safe means of representing claims to be transferred between two parties.
  • OpenAPI Language-agnostic interface description for HTTP APIs.
  • Best Practices Node.js Best Practices.
  • Conventional Commits A specification for adding human and machine readable meaning to commit messages.
  • Commitizen Define a standard way of committing rules and communicating it.
  • Husky Git hooks made easy woof!.
  • c8 Code-coverage using Node.js' built in functionality that's compatible with Istanbul's reporters.
  • Pino Very low overhead Node.js logger.
  • Standard JavaScript Style Guide, with linter & automatic code fixer.
  • nodemon Simple monitor script for use during development.
  • Joi Lets you describe and validate your data using a simple, intuitive, and readable language.
  • Thunder Client Lightweight Rest API Client for VS Code.

Usage

The starter use docker and docker compose to run the application and the database in development.

We need to setup the enviroment variables for production or development. For production there are 3 environment variables NODE_ENV, PORT and HOSTNAME in the docker-compose.yml file; these variable have default values that you can change according to your needs:

NODE_ENV: production  # Node.js environment
PORT: 3000            # API running port
HOSTNAME: 0.0.0.0     # API hostname

For development you need to setup the docker-compose.override.yml, this is a development override docker compose file that define the database container and environment variable for the database and for development in general.

docker-compose.override.yml file is ignored in the repo, because although it is a file destined for the development environment, it can leak some sensitive information if it is sent to the remote repository.

In the code you will find a docker-compose.override.yml.dist file, you should rename this file to docker-compose.override.yml (remove the .dist at the end of the name) and modify the environment variables that this file defines, as these will be used to configure the database inside the database container and to make the connection to the database from the API container.

Database Container Variables

POSTGRES_DB: rest-api-starter           # Database name
POSTGRES_USER: rest-api-starter         # Database username
POSTGRES_PASSWORD: ujt9ack5gbn_TGD4mje  # Database password

API Container Variables

NODE_ENV: development                   # Node.js environment

DATABASE_TYPE: postgres                 # Database engine
DATABASE_HOST: postgres                 # Database hostname
DATABASE_PORT: 5432                     # Database port
DATABASE_NAME: rest-api-starter         # Database name
DATABASE_USERNAME: rest-api-starter     # Database username
DATABASE_PASSWORD: ujt9ack5gbn_TGD4mje  # Database password

TOKEN_SECRET: ERN7kna-hqa2xdu4bva       # Secret for JWT token generation
EXPIRES_IN: 3600 # 1 hour               # JWT token expiration time

To run the API and database you need to use the next command in your terminal:

$ sudo docker-compose up -d

Database Configuration And Administration

Prisma

This API starter use Prisma ORM to manage the access to the database. The first thing to do is to create the project setup, and the starter have a npm script to perform this task and any other project setup actions.

$ npm run app:setup

This will create a directory called prisma with a file called schema.prisma, and in this file is where we will define the structure of the tables that will make up the database of our API.

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

You now need to adjust the connection URL to point to your own database, the url is set via an environment variable. In our development environment this url must be defined in the docker-compose.override.yml file and in our production environments we must define it in the server or execution environment of our API.

environment:
  NODE_ENV: development
  DATABASE_URL: "PROVIDER://USER:PASSWORD@HOST:PORT/DATABASE?schema=SCHEMA"
  TOKEN_SECRET: XXXXXXXXXXXXXXXXXXX
  EXPIRES_IN: 3600

The format of the connection URL for your database depends on the database you use. For PostgreSQL, it looks as follows (the parts spelled all-uppercased are placeholders for your specific connection details):

PROVIDER://USER:PASSWORD@HOST:PORT/DATABASE?schema=SCHEMA

Here's a short explanation of each component:

  • USER: The name of your database user
  • PASSWORD: The password for your database user
  • HOST: The name of your host name (for the local environment, it is localhost)
  • PORT: The port where your database server is running (typically 5432 for PostgreSQL)
  • DATABASE: The name of the database
  • SCHEMA: The name of the schema inside the database

Entities

The data model definition part of the Prisma schema defines your application models (also called Prisma models). We define our entities using the schema file; the schema file is written in Prisma Schema Language (PSL). Models:

  • Represent the entities of your application domain.
  • Map to the tables (relational databases like PostgreSQL) or collections (MongoDB) in your database.
  • Form the foundation of the queries available in the generated Prisma Client API.
  • When used with TypeScript, Prisma Client provides generated type definitions for your models and any variations of them to make database access entirely type safe.

The following schema describes a User entity:

model User {
  id      String   @id @default(uuid()) @db.Uuid()
  email   String   @unique
  name    String?
  role    Role     @default(USER)
  posts   Post[]
  profile Profile?
}

Migrations

Database migrations are a controlled set of changes that modify and evolve the structure of your database schema. Migrations help you transition your database schema from one state to another. For example, within a migration you can create or remove tables and columns, split fields in a table, or add types and constraints to your database.

Prisma Migrate generates a history of .sql migration files, and plays a role in both development and deployment.

Running Migrations

After creating or modifying an entity, and creating the corresponding migration, it is time to run the migration to create or modify the table associated with the entity.

To run the migrations we will use the next command:

$ npm run migrate:run

Reset The Development Database

You can also reset the database yourself to undo manual changes or db push experiments by running:

$ npm run migrate:reset

NOTE: migrate reset is a development command and should never be used in a production environment.


This command:

  1. Drops the database/schema¹ if possible, or performs a soft reset if the environment does not allow deleting databases/schemas¹
  2. Creates a new database/schema¹ with the same name if the database/schema¹ was dropped
  3. Applies all migrations
  4. Runs seed scripts

¹ For MySQL and MongoDB this refers to the database, for PostgreSQL and SQL Server to the schema, and for SQLite to the database file.

TODO

Objetives

My main goal is to add support for a wider range of libraries, ORMs, and other relevant technologies.

Initially I will do this by creating separate branches for each implementation, and in the future I will create a CLI that allows the starter to be created based on the available options.

  1. Add support for Fastify (other libraries like Restify?).
  2. Add support for TypeScript.
  3. Add support for TypeORM.
  4. Add support for other Relational Database Engines (providing different docker-compose.override.yml files).
  5. Add Support for NoSQL Database Engines (providing different docker-compose.override.yml files and different ORMs).
  6. CLI to config the starter.

About

REST API Starter, using the good Node.js and architecture patterns and practices

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages