Coder Social home page Coder Social logo

monstar-lab-oss / nestjs-starter-rest-api Goto Github PK

View Code? Open in Web Editor NEW
509.0 12.0 82.0 1.82 MB

NestJS Starter Kit. Monolithic Backend. REST API.

License: MIT License

JavaScript 0.49% TypeScript 97.87% Dockerfile 0.43% Shell 1.20%
monolithic rest-api nestjs starter-kit backend nodejs

nestjs-starter-rest-api's Introduction

NestJS Starter Kit [v2]

License: MIT build tests

This starter kit has the following outline:

  • Monolithic Project
  • REST API

This is a Github Template Repository, so it can be easily used as a starter template for other repositories.

Sample implementations

To view sample implementations based on this starter kit, please visit the nestjs-sample-solutions repository.

Starter kit Features

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
Devcontainer - 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, SonarCloud github actions, docker-compose for database dependencies, etc. :D

Consulting

Most of the features added to this starter kit have already been tried out in production applications by us here at MonstarLab. Our production applications are more feature rich, and we constantly strive to bring those features to this OSS starter kit.

If you would like to use a more feature rich starter kit, with more awesome features from Day 1, then please reach out to us and we can collaborate on it together as technology partners. :)

Installation

Note: when using docker, all the npm commands can also be performed using ./scripts/npm (for example ./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.

$ npm install

Create a .env file from the template .env.template file.

Generate public and private key pair for jwt authentication:

With docker

Run this command:

./scripts/generate-jwt-keys

It will output something like this. You only need to add it to your .env file.

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)"

Without docker

$ ssh-keygen -t rsa -b 2048 -m PEM -f jwtRS256.key
# Don't add passphrase
$ openssl rsa -in jwtRS256.key -pubout -outform PEM -out jwtRS256.key.pub

You may save these key files in ./local directory as it is ignored in git.

Encode keys to base64:

$ base64 -i local/jwtRS256.key

$ base64 -i local/jwtRS256.key.pub

Must enter the base64 of the key files in .env:

JWT_PUBLIC_KEY_BASE64=BASE64_OF_JWT_PUBLIC_KEY
JWT_PRIVATE_KEY_BASE64=BASE64_OF_JWT_PRIVATE_KEY

Running the app

We can run the project with or without docker.

Local

To run the server without Docker we need this pre-requisite:

  • Postgres server running

Commands:

# development
$ npm run start

# watch mode
$ npm run start:dev

# production mode
$ npm run start:prod

Docker

# build image
$ docker build -t my-app .

# run container from image
$ docker run -p 3000:3000 --volume 'pwd':/usr/src/app --network --env-file .env my-app

# run using docker compose
$ docker compose up

Learn more about Docker conventions here. (WIP - Currently this is an internal org link.)

Test

# unit tests
$ npm run test

# e2e tests
$ npm run test:e2e

# test coverage
$ npm run test:cov

Migrations

# using docker
$ docker compose exec app npm run migration:run

# generate migration (replace CreateUsers with name of the migration)
$ npm run migration:generate --name=CreateUsers

# run migration
$ npm run migration:run

# revert migration
$ npm run migration:revert

Architecture

Contributors

External Links

Nest Logo

SonarCloud

nestjs-starter-rest-api's People

Contributors

asad-mlbd avatar dependabot[bot] avatar devtanvir avatar felipeco14 avatar saad-amjad avatar sivanpayyadakath avatar war1oc avatar yashmurty avatar zulfikaralizihan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

nestjs-starter-rest-api's Issues

Rename package.json name

Let's rename nest-typescript-starter to nestjs-starter-rest-api and update the package.json and the lock file. Thanks.

`Bad request exception` message format

Currently, the starter kit returns a bad request exception(400) message details in the following pattern.

"message": [
    "name must be a string",
    "name should not be empty",
    "email must be an email",
    "email should not be empty"
],

There is no specification of the field for which the error has occurred. Then how would the frontend know in which field the error message should be displayed? How about returning the error messages like this? Or any better format?

"message": {
    "name": [
        "name must be a string",
        "name should not be empty",
    ],
    "email": [
        "email must be an email",
        "email should not be empty",
    ]
}

Exception from ArticleRepository is not tested

In this test: https://github.com/monstar-lab-oss/nestjs-starter-rest-api/blob/master/src/article/repositories/article.repository.spec.ts#L51

I think that this test does not work as expected, because if the repository does not throw an exception, the assertion will not be executed at all.

I think the right pattern would be like this:

let gotException: any = null
try {
  await repository.foo()
} catch (e) {
  gotException = e
} finally {
  expect(gotException).not.toBe(null);
  expect(gotException.constructor).toBe(NotFoundException);
}

License

First, thanks for this awesome solid starter project!

I was checking it out to use it but it misses a license, so I'm not sure I can use?

Exception Monitoring - Bugsnag vs Sentry

Integration

Both have easy to integrate nest module available

Pricing

Both have a good getting started free package for development

  • Bugsnag 7.5k message, 1 member - free
  • Sentry 14day trial, with 5k message - free

And for the paid model

  • Bugsnag 150k message, 5 member - $59/mo
  • Sentry 50K message, unlimited team member - $20/mo

Comparison

Some of the features offered by Bugsnag are:

  • Root cause error grouping
  • Real-time alerting to chat, email Slack, or SMS

Sentry provides the following key features:

  • Integration with Jira, Slack, etc.
  • Seems Sentry had more community approval compare to Bunnsnag.

Contribution: personal workflow to autogenerate version, CHANGELOG.md and tags based on Angular's convetion commits

Hello guys, I'm using this repo and wanted to contribute with a workflow I made using github actions.
This workflow will autogenerate the last version and tag, the CHANGELOG.md file and updated them in the destination branch, and in the package.json file (the version) and generate a new release on github releases.

Here is the code, it was made for an UI release but I think it will work anyways in any repo. In any case we can arrange it for this repo if you want it (I would be glad to help with it).

name: Release new version
on:
  pull_request: # in my repo, for each pull request closed on main. we can change it accordingly.
    branches: [main]
    types: [closed]
    paths-ignore:
      - '*.md'

jobs:
  build:
    name: Publish new release
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [16.x] 
    # if: github.event.pull_request.merged == true && github.event.pull_request.head.ref == 'staging' # For only merged pull requests from staging to trigger this job
    steps:
      - uses: actions/checkout@v2
        with:
          ref: ${{ github.head_ref }}
          token: ${{ secrets.GITHUB_TOKEN }} 

      # Generate tag and the version of the current release
      - name: Bump version and push tag
        id: tag_version
        uses: mathieudutour/[email protected]
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          release_branches: main
          pre_release_branches: staging
          append_to_pre_release_tag: 'pre-'

      # set the version of the current release without the prefix
      - name: Set version
        run: |
          VERSION=${{ steps.tag_version.outputs.new_tag }}
          echo "VERSION=${VERSION:1}" >> $GITHUB_ENV

      # Updated the package.json file with the new version
      - name: 'Package.json Version update'
        uses: 'phips28/gh-action-bump-version@master'
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          skip-tag: 'true'
          target-branch: ${{ github.event.pull_request.base.ref }}
          commit-message: 'CI: bumps version to {{version}} [skip ci]'
          default: '${{ env.VERSION }}'

      # update changelog file based on data from the previous step
      - name: Update Changelog
        uses: stefanzweifel/changelog-updater-action@v1
        with:
          # Pass the output from the tag_version step: new tag, release date, changelog generated and version to the Action.
          latest-version: ${{ steps.tag_version.outputs.new_tag }}
          release-notes: ${{ steps.tag_version.outputs.changelog }}
          release-date: ${{ steps.tag_version.outputs.release_date }}
          compare-url-target-revision: ${{ github.event.pull_request.head.ref }}

      # Commit the changelog file updated on PR base branch
      - name: Commit updated CHANGELOG on PR base branch
        uses: stefanzweifel/git-auto-commit-action@v4
        with:
          skip_fetch: false
          skip_checkout: false
          branch: ${{ github.event.pull_request.base.ref }}
          commit_message: Update CHANGELOG for ${{ steps.tag_version.outputs.new_tag }}
          file_pattern: CHANGELOG.md
          push_options: '--force'
          # User configuration that will made the commit to the branch, maybe we need to configure it accordingly
          commit_user_name: John Doe # defaults to "github-actions[bot]"
          commit_user_email: [email protected] # defaults to "github-actions[bot]@users.noreply.github.com"
          commit_author: John Doe <[email protected]> # defaults to author of the commit that triggered the run

      # Generate the release
      - name: Create a GitHub release
        uses: ncipollo/release-action@v1
        with:
          tag: ${{ steps.tag_version.outputs.new_tag }}
          name: Release ${{ steps.tag_version.outputs.new_tag }}
          body: ${{ steps.tag_version.outputs.changelog }}

I hope it helps! And also thanks for the hard work of this starter template. It rocks!!
Happy to be helping you guys.

Best regards!

Advance refresh token

Currently, the refresh token feature is implemented in a simple stateless way. Here are some of advanced features we have to discuss for further enhancement.

  • User entity can have isActive flag so that we can sometimes block a user to generate new auth token thru refresh token or log in.
  • Currently refresh token is stateLess (not saving it in DB). We can make some module configuration to save refreshToken in DB.
  • For stateful we can have configuration value to decide whether to keep multiple refreshToken alive for same user at a time.
  • Optionally we can save device id to keep track of devices logged in.
  • For stateful refresh token, we have to write logout API, and optional parameter top logout from all device.
Authmodule.forRoot({
   stateLessTokenRefresh: true, // will not save, or check refresh token validity in db
   supportMultiDeviceLogin: true, // will store multiple refresh token for one user
})

[questions] migrations and deployments

Question: What is the proper way to apply migrations in this project?

I've noticed that we do not use migrationsRun: true on application startup; How are we applying migrations in production and CI/CD?

Question: What is the recommended way of deploying this monolith?

I understand this is a very generic and broad question, but the repository is vastly different from my typical workflow and also different from the company I work at; So I am wondering how you guys do it at Monstar;

:)

Unique constraint error while registering user with existing data

If a user with username x or email [email protected] is already registered, while registering with the same input, it throws 500 internal server error.

{
    "error": {
        "statusCode": 500,
        "message": "ER_DUP_ENTRY: Duplicate entry 'x' for key 'users.username'",
        "errorName": "QueryFailedError",
        "path": "/api/v1/auth/register",
        "requestId": "280f8680-1642-4518-9b51-c3ab57010e00",
        "timestamp": "2022-06-27T12:18:36.999Z"
    }
}

Handling while trying to register with existing data and throwing 400 Bad request would be more suitable instead of 500.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.