Skip to content

Ho-s/NestJS-GraphQL-TypeORM-PostgresQL

Repository files navigation

NestJS/TypeORM/GraphQL/PostgresQL

NestJS boilerplate with TypeORM, GraphQL and PostgreSQL

Open for Contribution

Totally open for any Pull Request, please feel free to contribute in any ways. There can be errors related with type or something. It would be very helpful to me for you to fix these errors.

Base NestJS, We like it

We use Nestjs/TypeORM In this template, We've been trying not to use Pure SQL to make the most of TypeORM.

We use postgresQL for backend database, The default database taht will be used is named 'postgres' You have to have postgresql Database server before getting started. You can use Docker postgresQL to have server easily

packages: graphql, apollo-server-express and @nestjs/graphql, graphqlUpload ...

We use GraphQL in a Code First approach (our code will create the GraphQL Schemas).

We don't use swagger now, but you can use this if you want to. You can see playground

We use apollographql as playground. but if you want to use default playground, you can do like below.

// setting.service.ts

GraphQLModule.forRootAsync <
  ApolloDriverConfig >
  {
    ...
    useFactory: (configService: ConfigService) => ({
      ...
      playground: true,
      ...
    }),
    ...
  };

Protected queries/mutation by user role with guard

Some of the GraphQL queries are protected by a NestJS Guard (GraphqlPassportAuthGuard) and requires you to be authenticated (and some also requires to have the Admin role). You can solve them with Sending JWT token in Http Header with the Authorization.

# Http Header
{
  "Authorization": "Bearer TOKEN"
}

Example of some protected GraphQL

  • getMe (must be authenticated)
  • All methods generated by the generator (must be authenticated and must be admin)

License

MIT

Custom CRUD

To make most of GraphQL's advantage, We created its own api, such as GetMany or GetOne. We tried to make it as comfortable as possible, but if you find any mistakes or improvements, please point them out or promote them.

You can see detail in folder /src/common/graphql files

// query
query($input:GetManyInput) {
  getManyPlaces(input:$input){
    data{
      id
      logitude
      count
    }
  }
}
// variables
{
  input: {
    pagination: {
      size: 10,
      page: 0, // Started from 0
    },
    order: { id: 'DESC' },
    dataType: 'data', //all or count or data - default: all
    where: {
      id: 3,
    },
  },
};

You can see detail here.

Code generator

There is CRUD Generator in NestJS. In this repository, It has its own generator with plopjs. You can use like below.

$ yarn g

Getting Started

Installation

Before you start, make sure you have a recent version of NodeJS environment >=14.0 with NPM 6 or Yarn.

The first thing you will need is to install NestJS CLI.

$ yarn -g @nestjs/cli

And do install the dependencies

$ yarn install # or npm install

Run

for development

$ yarn dev # or npm run dev

for production

$ yarn build # or npm run build
$ yarn start # or npm run start

or run with docker following below

Docker

Docker-compose installation

Download docker from Official website

Before getting started

Before running Docker, you need to create an env file named .production.env. The content should be modified based on .example.env. The crucial point is that DB_HOST must be set to 'postgres'.

Run

Open terminal and navigate to project directory and run the following command.

# Only for prduction
$ docker-compose --env-file ./.production.env up

Note

If you want to use docker, you have to set DB_HOST in .production.env to be postgres. The default set is postgres

Only database

You can just create postgresql by below code, sync with .development.env

$ docker run -p 5432:5432 --name postgres -e POSTGRES_PASSWORD=1q2w3e4r -d postgres

TDD

Introduction

@nestjs/testing = supertest + jest

Before getting started

Before starting the test, you need to set at least jwt-related environment variables in an env file named .test.env.

Unit Test (Use mock)

Unit test(with jest mock) for services & resolvers (*.service.spec.ts & *.resolver.spec.ts)

Run

$ yarn test

Integration Test (Use in-memory DB)

Integration test(with pg-mem) for modules (*.module.spec.ts)

Run

$ yarn test

End To End Test (Use docker)

E2E Test(with docker container)

Run

$ yarn test:e2e:docker

CI

Github actions

To ensure github actions execution, please set the 'ENV' variable within your github actions secrets as your .test.env configuration.

Note: Github Actions does not recognize newline characters. Therefore, you must remove any newline characters from each environment variable value in your .env file, ensuring that the entire content is on a single line when setting the Secret. If you need to use an environment variable value that includes newline characters, encode the value using Base64 and store it in the Github Secret, then decode it within the workflow.

ex)

JWT_PRIVATE_KEY= -----BEGIN RSA PRIVATE KEY-----...MIIEogIBAAKCAQBZ...-----END RSA PRIVATE KEY-----

Before getting started

$ yarn prepare

Pre commit

You can check detail here

Before commit, The pre-commit hooks is executed.

Lint checks have been automated to run before a commit is made.

If you want to add test before commit actions, you can add follow line in pre-commit file.

...
yarn test
...

Pre push

You can check detail here

The pre-push hooks is executed before the push action.

The default rule set in the pre-push hook is to prevent direct pushes to the main branch.

If you want to enable this action, you should uncomment the lines in the pre push file.

SWC (Speedy Web Compiler) is an extensible Rust-based platform that can be used for both compilation and bundling. Using SWC with Nest CLI is a great and simple way to significantly speed up your development process.

SWC + Jest error resolution

After applying SWC, the following error was displayed in jest using an in-memory database (pg-mem):

    QueryFailedError: ERROR: function obj_description(regclass,text) does not exist
    HINT: πŸ”¨ Please note that pg-mem implements very few native functions.

                πŸ‘‰ You can specify the functions you would like to use via "db.public.registerFunction(...)"

    🐜 This seems to be an execution error, which means that your request syntax seems okay,
        but the resulting statement cannot be executed β†’ Probably not a pg-mem error.

    *️⃣ Failed SQL statement: SELECT "table_schema", "table_name", obj_description(('"' || "table_schema" || '"."' || "table_name" || '"')::regclass, 'pg_class') AS table_comment FROM "information_schema"."tables" WHERE ("table_schema" = 'public' AND "table_name" = 'user');

    πŸ‘‰ You can file an issue at https://github.com/oguimbal/pg-mem along with a way to reproduce this error (if you can), and  the stacktrace:

pg-mem is a library designed to emulate PostgreSQL, however, it does not support all features, which is why the above error occurred.

This error can be resolved by implementing or overriding existing functions. Below is the function implementation for the resolution. Related issues can be checked here.

db.public.registerFunction({
  name: 'obj_description',
  args: [DataType.text, DataType.text],
  returns: DataType.text,
  implementation: () => 'test',
});

Todo

  • TDD

    • Unit Test (Use mock)
    • Integration Test (Use in-memory DB)
    • End To End Test (Use docker)
  • Add Many OAUths (Both of front and back end)

    • Kakao
    • Google
    • Apple
    • Naver
  • CI

    • Github actions
    • husky
  • GraphQL Upload

  • Healthcheck

  • Divide usefactory

  • SWC Compiler

  • Refresh Token

  • Redis

  • ElasticSearch

  • Caching

  • Graphql Subscription

  • Remove lodash

  • CASL