Node.js REST API Starter using best practices and patterns.
This is a list of the main technologies included in this Starter:
- Fastify Fast and low overhead web framework, for Node.js.
- Drizzle ORM Drizzle ORM is a headless TypeScript ORM with a head.
- TypeBox Json Schema Type Builder.
- Pino Very low overhead Node.js logger.
- Standard JavaScript Style Guide, with linter & automatic code fixer.
- 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.
The starter use docker and docker compose to run the application and the database in development.
We need to setup the environment 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 configure docker-compose.override.yml
, this overrides the docker-compose.yml
file and defines the database container and environment variables for the database and for development in general.
The docker-compose.override.yml
file is ignored in the repository because, although it is a file intended for the development environment, it can leak sensitive information if pushed 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: ******************* # Database password
NODE_ENV: development|production # Node.js environment
PORT: 3000 # Database hostname
HOSTNAME: localhost # Database engine
TOKEN_SECRET: ******************* # Secret for JWT token generation
REFRESH_TOKEN_SECRET: ******************* # Secret for JWT token generation
EXPIRES_IN: 3600 # 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 Drizzle ORM is a headless TypeScript ORM with a head. It looks and feels simple, performs on day 1000 of your project, lets you do things your way, and is there when you need it.
It’s the only ORM with both relational and SQL-like query APIs, providing you best of both worlds when it comes to accessing your relational data.
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.
After creating or modifying an entity, it is time to generate the corresponding migration; the project has a script to execute this task:
npm run migrate:generate
or
sudo docker exec -it rest-api npm run migrate:generate
After 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
or
sudo docker exec -it rest-api npm run migrate:run
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
Drizzle ORM provides you with an API to declare SQL tables, in this starter each domain must contain the corresponding schema declaring the table for the domain.
If you declare an entity within a schema, query builder will prepend schema names in queries:
The following schema describes a User
entity:
import {
integer,
pgEnum,
pgTable,
serial,
uniqueIndex,
varchar
} from 'drizzle-orm/pg-core'
// declaring enum in database
export const popularityEnum = pgEnum('popularity', ['unknown', 'known', 'popular'])
export const countries = pgTable('countries', {
id: serial('id').primaryKey(),
name: varchar('name', { length: 256 }),
}, (countries) => {
return {
nameIndex: uniqueIndex('name_idx').on(countries.name),
}
})
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.
After creating or modifying an entity, it is time to generate the corresponding migration; the project has a script to execute this task:
npm run migrate:generate
or
sudo docker exec -it rest-api npm run migrate:generate
After 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
or
sudo docker exec -it rest-api npm run migrate:run
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 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 and generate code.