NestJS template to create REST Monoliths. Includes common boilerplate, including integration test db up/down mechanisms.
MIT License
The very first step you must take in this project is simple:
Find all occurrences of my-nest-rest-starter
Replace them with your project's name composed of characters matching the regex:
/^[(a-z\-){+}]$/
(at least one character, all being lower case or hyphen)Then go to your project's GitHub repository
Settings
, select Environments
and create new environments
test
, staging
production
being created; With these exact names!Settings
, select Secrets > Actions
and create two Environment
JWT_PRIVATE_KEY_BASE64
JWT_PUBLIC_KEY_BASE64
Dependabot
, non secret-environment variables whichSecrets > Actions > Dependabot
,Dependabot
Pull Requests will constantly fail. For the initial setupDependabot Secrets
.Wether you are on MacOS or Linux, we recommend that you install the following tooling:
oh-my-zsh with your favorite plugins
# We personally enjoy using at least these:
plugins=(
git
zsh-autosuggestions
zsh-completions
zsh-syntax-highlighting
)
Homebrew and remember to follow the instructions at the end of the program output.
.zshrc
,.bashrc
or other profile files.brew install openssl
brew install direnv
# Directory Environment requires additional setup in your rc file
brew install libpq
# Node Version Manager requires additional setup in your rc file
brew install nvm
# Installs the latest Node LTS that satisfies the `.nvmrc` file given by the project
nvm use
If you installed nvm
and libpq
you do not need anything other than Docker
and
Docker-Compose
.
NodeJS matching the project's version
zsh
as a shell you canNode
for any project which.nvmrc
, when switching to it's directory or a child of it. Just add this.zshrc
# place this after nvm initialization!
autoload -Uz add-zsh-hook
load-nvmrc() {
if [[ -f .nvmrc && -r .nvmrc ]]; then
nvm use
elif [[ $(nvm version) != $(nvm version default) ]]; then
echo "Reverting to nvm default version"
nvm use default
fi
}
add-zsh-hook chpwd load-nvmrc
load-nvmrc
Postgres or compatible binaries
When using docker, all of the project's 'npm
commands can also be performed using
./scripts/npm
(e.g.: ./scripts/npm install
). This script allows you to run the same
commands inside the same environment and versions than the service, without relying on
what is installed on the host and without decorating fancy docker/docker-compose exec
commands.
We use NPM and we disallow any attempt to use Yarn or PNPM; We recognize that Yarn and especially PNPM are faster than NPM; But GitHub Actions PNPM support is still somewhat limited, it is also harder to find professional grade examples using these managers, when it comes to private packaging, CI/CD, among others.
npm install
.env
file from the template .env.template
file.cp .env.template .env
JWT_PUBLIC_KEY_BASE64
and JWT_PRIVATE_KEY_BASE64
These variables are key to the application proper operation. Without these
environment variables, the application runtime
will fail and e2e
will certainly
pick that up!
Run this command:
./scripts/generate-jwt-keys
Copy the output of that command and add it to your .env
file. It looks something
like this:
To setup the JWT keys, please add the following values to your .env file:
JWT_PUBLIC_KEY_BASE64="(long base64 content)"
JWT_PRIVATE_KEY_BASE64="(long base64 content)"
The keys will be generated on .local
folder, which is ignored by .gitignore
.
mkdir ./local
ssh-keygen -t rsa -b 2048 -m PEM -f ./local/jwtRS256.key -N ""
openssl rsa -in jwtRS256.key -pubout -outform PEM -out ./local/jwtRS256.key.pub
base64 -i ./local/jwtRS256.key
base64 -i ./local/jwtRS256.key.pub
Must enter the base64 of the key files in .env
:
# Ensure that you insert both outputs in your environment without any newlines
JWT_PUBLIC_KEY_BASE64="BASE64_OF_JWT_PUBLIC_KEY"
JWT_PRIVATE_KEY_BASE64="BASE64_OF_JWT_PRIVATE_KEY"
We can run the project with or without docker.
To run the server without Docker we need this pre-requisite:
Commands:
# Apply the migrations if needed
npm run typeorm:migration:run
# development
npm run start
# watch mode
npm run start:dev
# production mode
npm run start:prod
# build image
docker build -t my-nest-rest-starter .
# run container from image
docker run -p 3000:3000 --volume 'pwd':/usr/src/app --network --env-file .env my-nest-rest-starter
# run using docker compose
docker compose up
# unit tests (with or without JEST coverage)
npm run test
npm run test:cov
# integration
# not available yet
# e2e tests
npm run test:e2e
# Example using docker (all remaining commands can also be used in the same way)
docker-compose exec app npm run typeorm:migration:run
# Directly on host machine
# Apply migrations on local machine
npm run typeorm:migration:run
# Revert the previous migration applied on your local machine
npm run typeorm:migration:revert
# Generate migration file from changes applied to the entities. Be aware that
# the generated file may need some fine tuning. Always verify the generated
# migration instructions as they can easily compromise dev, qa and production
# databases when applied.
npm run typeorm:migration:generate --name='name'
# Create an empty migration file
npm run typeorm:migration:create --name'name'
# Write in the console the pending changes
npm run typeorm:migration:log
# Write in the console the pending migrations to be applied
npm run typeorm:migration:show
# Drop database, deletes all tables
npm run schema:drop
# Sync entities with database, creates, and updates database tables
# We do this automatically on application start-up.
npm run schema:sync
Any environment variable which is not a secret or is just a placeholder for test should be added to any workflows (.github/workflows/*.yml
files) as the project grows.
testing-workflow
and do not communicate with real systems, and instead communicate with transient dockerized containers (running as local processes on the host where the workflow is executing), they do not need to be treated as such!Any environment variable considered secret should be added as Environment, Repository or Organization Secret
on GitHub. Examples include API KEYS, Database Connection Credentials, Public/Private Key pairs like the ones we created earlier (JWT_PRIVATE_KEY_BASE64
/JWT_PUBLIC_KEY_BASE64
)
staging
environment variables to load them into the workflow.(repository) Settings > Secrets > Actions
testing
workflows, which is not hardcoded on the workflow itself should also be added a Dependabot Secrets. By default, pull requests created by Dependabot do not have access to any GitHub Secrets (for security purposes). Without this effort, all Dependabot pull requests will fail on the testing step!# You must provide the correct relative or absolute path to -f option
# When prompted for a password, type in the value of DATABASE_PASSWORD of `.env`
export NODE_ENV=dev;
npm run typeorm schema:drop;
psql --dbname=$DB_NAME --username=$DB_USER --host=$DB_HOST --port=$DB_PORT -f ~/Downloads/example-dump.sql;
The baseline for this project was taken from MonstraLab OSS template
To view sample implementations based on this starter kit, please visit the nestjs-sample-solutions repository.
One of our main principals has been to keep the starter kit as lightweight as possible. With that in mind, here are some of the features that we have added in this starter kit.
Feature | Info | Progress |
---|---|---|
Authentication | JWT | Done |
Authorization | RBAC (Role based) | Done |
ORM Integration | TypeORM | Done |
DB Migrations | TypeORM | Done |
Logging | winston | Done |
Request Validation | class-validator | Done |
Pagination | SQL offset & limit | Done |
Docker Ready | Dockerfile | Done |
Auto-generated OpenAPI | - | Done |
Auto-generated ChangeLog | - | WIP |
Apart from these features above, our start-kit comes loaded with a bunch of minor awesomeness like prettier integration, commit-linting husky hooks, package import sorting, docker-compose for database dependencies, etc.