Amazon web service will be the cloud provider. This is why this project is focused on AWS features.
Http NestJs v9.x boilerplate. Best uses for backend service.
You can request feature or report bug with following this link
- Important
- Next Todo
- Build With
- Objective
- Features
- Structure
- Prerequisites
- Getting Started
- API Reference
- Environment
- Api Key Encryption
- Adjust Mongoose Setting
- License
- Contact
If you want to implementΒ
database transactions
, you must run MongoDB as aΒreplication set
.
If you change the environment value of APP_ENV
to production
, that will trigger.
- CorsMiddleware will implement
src/configs/middleware.config.ts
.Otherwise is*
. - Documentation will
disable
.
Next development
- Implement Repository Design Pattern / Data Access Object Design Pattern
- Swagger for API Documentation
- Mongo Repository soft delete
- Make it simple
- Encrypt jwt payload
- Optimize Unit Testing
- Make serverless separate repo
- Optimize Swagger
- Export to excel and Import from excel add options to background process
- SSO Google
- AuthApi Controller
- Update Documentation, include an diagram for easier comprehension
- OAuth2 Client Credentials
- Maybe will adopt CQRS
Describes which version.
Name | Version |
---|---|
NestJs | v9.1.x |
NodeJs | v18.4.x |
Typescript | v4.8.x |
Mongoose | v6.6.x |
MongoDB | v6.0.x |
Yarn | v1.22.x |
NPM | v8.12.x |
Docker | v20.10.x |
Docker Compose | v2.6.x |
Swagger | v6.1.x |
- Easy to maintenance
- NestJs Habit
- Component based folder structure
- Repository Design Pattern or Data Access Layer Design Pattern
- Support Microservice Architecture, Serverless Architecture, Clean Architecture, and/or Hexagonal Architecture
- Follow The Twelve-Factor App
- Adopt SOLID and KISS principle
- NestJs v9.x π₯³
- Typescript π
- Production ready π₯
- Repository Design Pattern
- Swagger included
- Authentication and authorization (
JWT
,API Key
) πͺ - Role management system
- Storage integration with
AwsS3
- Upload file
single
andmultipart
to AwsS3 - Support multi-language
i18n
π£ - Request validation with
class-validation
- Serialization with
class-transformer
- Url Versioning
- Server Side Pagination, there have 3 of types
- Import and export data with excel by using
decorator
- MongoDB integrate by using mongoose π
- Multi Database
- Database Transaction
- Database Soft Delete
- Database Migration
- Logger with
Morgan
- Debugger with
Winston
π
- Apply
helmet
,cors
, andrate-limit
- Timeout awareness and can override βοΈ
- User agent awareness, and can whitelist user agent
- Support environment file
- Centralize configuration π€
- Centralize response
- Centralize exception filter
- Setting from database πΏ
- Maintenance mode on / off from database π€
- Support Docker Installation
- Support CI/CD with Github Action or Jenkins
- Husky GitHook For Check Source Code, and Run Test Before Commit πΆ
- Linter with EsLint for Typescript
/app
The final wrapper module/common
The common module/configs
The configurations for this project/health
health check module for every service integrated/jobs
cron job or schedule task/language
json languages/migration
migrate all init data for test the project/modules
other modules based on service/project/router
endpoint router.Controller
will put in this
Full structure of module
.
βββ module1
βββ abstracts
βββ constants // constant like enum, static value, status code, etc
βββ controllers // business logic for rest api
βββ decorators // warper decorator, custom decorator, etc
βββ dtos // request validation
βββ docs // swagger
βββ errors // custom error
βββ filters // custom filter
βββ guards // validate related with database
βββ indicators // custom health check indicator
βββ interceptors // custom interceptors
βββ interfaces
βββ pipes
βββ repository
βββ entities // database entities
βββ repositories // database repositories
βββ serializations // response serialization
βββ services
βββ tasks // task for cron job
βββ module1.module.ts
This section will describe the structure of the response.
This is useful when we need to give the frontend some information that is not related to the endpoint.
export interface IResponseMetadata {
languages: ENUM_MESSAGE_LANGUAGE[];
timestamp: number;
timezone: string;
requestId: string;
path: string;
version: string;
repoVersion: string;
nextPage?: string;
previousPage?: string;
firstPage?: string;
lastPage?: string;
[key: string]: any;
}
Default response for the response
export interface IResponse {
metadata?: IResponseMetadata;
[key: string]: any;
}
Default response for pagination.
export interface IResponsePaging {
totalData: number;
totalPage?: number;
currentPage?: number;
perPage?: number;
availableSearch?: string[];
availableSort?: string[];
metadata?: IResponseMetadata;
data: Record<string, any>[];
}
We assume that everyone who comes here is programmer with intermediate knowledge
and we also need to understand more before we begin in order to reduce the knowledge gap.
- Understand NestJs Fundamental, Main Framework. NodeJs Framework with support fully TypeScript.
- UnderstandTypescript Fundamental, Programming Language. It will help us to write and read the code.
- Understand ExpressJs Fundamental, NodeJs Base Framework. It will help us in understanding how the NestJs Framework works.
- Understand what NoSql is and how it works as a database, especially MongoDB.
- Understand Repository Design Pattern or Data Access Object Design Pattern. It will help to read, and write the source code
- Understand The SOLID Principle and KISS Principle for better write the code.
- Optional. Understand Microservice Architecture, Clean Architecture, and/or Hexagonal Architecture. It can help to serve the project.
- Optional. Understanding The Twelve Factor Apps. It can help to serve the project.
- Optional. Understanding Docker. It can help to run the project.
Before start, we need to install some packages and tools. The recommended version is the LTS version for every tool and package.
Make sure to check that the tools have been installed successfully.
Clone the project with git.
git clone https://github.com/andrechristikan/ack-nestjs-boilerplate.git
This project needs some dependencies. Let's go install it.
yarn install
Make your own environment file with a copy of env.example
and adjust values to suit your own environment.
cp .env.example .env
The migration will do data seeding to MongoDB. Make sure to check the value of the
DATABASE_
prefix in your.env
file.
The Database migration used NestJs-Command
For seeding
yarn seed
For remove all data do
yarn rollback
The test is still not good net. I'm still lazy too do that.
The project provide 3 automation testing unit testing
, integration testing
, and e2e testing
.
yarn test
For specific test do this
-
Unit testing
yarn test:unit
-
Integration testing
yarn test:integration
-
E2E testing
yarn test:e2e
Finally, Cheers π»π» !!! you passed all steps.
Now you can run the project.
yarn start:dev
docker-compose up -d
We have already provided the API reference. To visit, click here.
Detail information about the environment
Key | Type | Description |
---|---|---|
APP_NAME | string |
Application name |
APP_ENV | string |
|
APP_LANGUAGE | string |
Enum languages, separator , |
Key | Type | Description |
---|---|---|
HTTP_HTTP_ENABLE | boolean |
Application Http on/off |
HTTP_HOST | string |
Application host serve |
HTTP_PORT | number |
Application port serve |
HTTP_VERSIONING_ENABLE | boolean |
Application url versioning on/off |
HTTP_VERSION | number |
Application url version number. When HTTP_VERSIONING_ENABLE is enabled, the application version number is used. |
Key | Type | Description |
---|---|---|
DEBUGGER_HTTP_WRITE_INTO_FILE | boolean |
Http debugger write into file |
DEBUGGER_HTTP_WRITE_INTO_CONSOL | boolean |
Http debugger write into console |
DEBUGGER_SYSTEM_WRITE_INTO_FILE | boolean |
System debugger write into file |
DEBUGGER_SYSTEM_WRITE_INTO_CONSOLE | boolean |
System debugger write into console |
Key | Type | Description |
---|---|---|
MIDDLEWARE_TIMESTAMP_TOLERANCE | string |
Tolerance timestamp and used for validate the ApiKey . ms package value |
MIDDLEWARE_TIMEOUT | string |
Request timeout. ms package value |
Key | Type | Description |
---|---|---|
DOC_NAME | string |
Documentation tittle |
DOC_VERSION | number |
Documentation version |
Key | Type | Description |
---|---|---|
JOB_ENABLE | boolean |
Application Job or Schedule turn on/off |
Key | Type | Description |
---|---|---|
DATABASE_TYPE | string |
Enum of database Type MONGODB or POSTGRES |
DATABASE_HOST | string |
Mongodb URL. Support standard url , replication , or srv |
DATABASE_NAME | string |
Database name |
DATABASE_USER | string |
Database user |
DATABASE_PASSWORD | string |
Database user password |
DATABASE_DEBUG | boolean |
Trigger database DEBUG |
DATABASE_OPTIONS | string |
Mongodb connect options |
Key | Type | Description |
---|---|---|
AUTH_JWT_PAYLOAD_ENCRYPTION | boolean |
Jwt payload encrypt |
AUTH_JWT_SUBJECT | string |
Jwt subject |
AUTH_JWT_SUBJECT | string |
Jwt subject |
AUTH_JWT_AUDIENCE | string |
Jwt audience |
AUTH_JWT_ISSUER | string |
JWT issuer |
Key | Type | Description |
---|---|---|
AUTH_JWT_ACCESS_TOKEN_SECRET_KEY | string |
Secret access token, free text. |
AUTH_JWT_ACCESS_TOKEN_EXPIRED | string |
Expiration time for access token. ms package value |
AUTH_JWT_ACCESS_TOKEN_ENCRYPT_KEY | string |
Encrypt key for access token payload |
AUTH_JWT_ACCESS_TOKEN_ENCRYPT_IV | string |
Encrypt IV for access token payload |
Key | Type | Description |
---|---|---|
AUTH_JWT_REFRESH_TOKEN_SECRET_KEY | string |
Secret refresh token, free text. |
AUTH_JWT_REFRESH_TOKEN_EXPIRED | string |
Expiration time for refresh token. ms package value |
AUTH_JWT_REFRESH_TOKEN_REMEMBER_ME_EXPIRED | string |
Expiration time for refresh token when remember me is checked. ms package value |
AUTH_JWT_REFRESH_TOKEN_NOT_BEFORE_EXPIRATION | string |
Token active for refresh token before x time. ms package value |
AUTH_JWT_REFRESH_TOKEN_ENCRYPT_KEY | string |
Encrypt key for refresh token payload |
AUTH_JWT_REFRESH_TOKEN_ENCRYPT_IV | string |
Encrypt IV for refresh token payload |
Key | Type | Description |
---|---|---|
AWS_CREDENTIAL_KEY | string |
AWS account credential key |
AWS_CREDENTIAL_SECRET | string |
AWS account credential secret |
AWS_S3_REGION | string |
AWS S3 Region |
AWS_S3_BUCKET | string |
AWS S3 Name of Bucket |
Please keep theΒ
secret and passphrase
Β private.
ApiKeyHashed uses sha256
encryption, dataObject
encryption is AES256
.
Here ApiKey data from seeding
{
"name": "Api Key Migration",
"description": "From migration",
"key": "qwertyuiop12345zxcvbnmkjh",
"secret": "5124512412412asdasdasdasdasdASDASDASD",
"passphrase": "cuwakimacojulawu",
"encryptionKey": "opbUwdiS1FBsrDUoPgZdx"
}
To do the encryption.
The encryption process must be on client-side.
-
Make sure to have value of
key
: You can find the key for apiKey in the database.secret
: This value isonly generated when the apiKey is created
. After that, if you lose the secret, you need to recreate the apiKey.encryptionKey
: You can find the key for encryption in the database.passphrase
: This is IV for encrypt AES 256. This is need to be private too. Same withsecret
.
-
Concat the
key
andsecret
.const concatApiKey = `${key}:${secret}`;
-
Encryption
concatApiKey
withsha256
const apiKeyHashed = this.helperHashService.sha256(concatApiKey);
-
Then create
dataObject
and put theapiKeyHashed
into itconst timestamp: number = this.helperDateService.timestamp(); const dataObject: IAuthApiRequestHashedData = { key, // from 1.key timestamp, // ms timestamp hash: apiKeyHashed, // from 3 }
-
Encryption the
dataObject
withAES 256
These data
encryptionKey
, andpassphrase
can be find in database.const passphrase = 'cuwakimacojulawu'; // <--- IV for encrypt AES 256 const encryptionKey = 'opbUwdiS1FBsrDUoPgZdx'; const apiKeyEncryption = await authApiService.encryptApiKey( data, encryptionKey, passphrase );
-
Last, combine the
key
andapiKeyEncryption
const xApiKey = `${key}:${apiEncryption}`;
-
Send into request. Put the
xApiKey
,timestamp
, andpassphrase
in the request headers{ "headers": { "x-api-key": "${xApiKey}", // from 6.xApiKey "x-timestamp": "${timestamp}" // from 4.timestamp ... ... ... } }
Optional, if your mongodb version is < 5
Go to file src/common/database/services/database.options.service.ts
and add useMongoClient
to mongooseOptions
then set value to true
.
const mongooseOptions: MongooseModuleOptions = {
uri,
useNewUrlParser: true,
useUnifiedTopology: true,
serverSelectionTimeoutMS: 5000,
useMongoClient: true
};
Distributed under MIT licensed.
How to contribute in this repo
-
Fork the project with click
Fork
button of this repo. -
Clone the fork project
git clone "url you just copied"
-
Make necessary changes and commit those changes
-
Commit the changes
git commit -m "your message"
-
Push changes to fork project
git push origin -u main
-
Back to browser, goto your fork repo github. Then, click
Compare & pull request
If your code behind commit with the original, please update your code and resolve the conflict. Then, repeat from number 6.
- Avoid Circular Dependency
- Consume component folder structure, and repository design pattern
- Always make
service
for every module is independently. - Do not put
controller
into service modules, cause this will break the dependency. Only put the controller intorouter
and then inject the dependency. - Put the config in
/configs
folder, and for dynamic config put asenvironment variable
CommonModule
only for main package, and put the module that related of service/project into/src/modules
. So, if we want to clear the unnecessary module, we just need to delete thesrc/modules/**
- If there a new service in CommonModule. Make sure to create the unit test in
/test/unit
. - If there a new controller, make sure to create the e2e testing in
test/e2e