Node.js REST API Starter using best practices and patterns.
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.
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.
POSTGRES_DB: rest-api-starter # Database name
POSTGRES_USER: rest-api-starter # Database username
POSTGRES_PASSWORD: ujt9ack5gbn_TGD4mje # Database password
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
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 userPASSWORD
: The password for your database userHOST
: The name of your host name (for the local environment, it islocalhost
)PORT
: The port where your database server is running (typically5432
for PostgreSQL)DATABASE
: The name of the databaseSCHEMA
: The name of the schema inside the database
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?
}
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.
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
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:
- Drops the database/schema¹ if possible, or performs a soft reset if the environment does not allow deleting databases/schemas¹
- Creates a new database/schema¹ with the same name if the database/schema¹ was dropped
- Applies all migrations
- 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.
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.
- Add support for Fastify (other libraries like Restify?).
- Add support for TypeScript.
- Add support for TypeORM.
- Add support for other
Relational Database Engines
(providing differentdocker-compose.override.yml
files). - Add Support for
NoSQL Database Engines
(providing differentdocker-compose.override.yml
files and differentORMs
). - CLI to config the starter.