An open API service indexing awesome lists of open source software.

https://github.com/eocode/nestjs-graphql

NestJS project with GraphQL
https://github.com/eocode/nestjs-graphql

js project software-engineering

Last synced: about 1 month ago
JSON representation

NestJS project with GraphQL

Awesome Lists containing this project

README

          

# Instructions

Starter template for 😻 [NestJS](https://nestjs.com/) and [Prisma](https://www.prisma.io/).

> Checkout [NestJS Prisma Schematics](https://github.com/marcjulian/nestjs-prisma) to automatically add Prisma support to your Nest application.

## Version

| Branch |  Nest | Prisma |  Graphql |
| ------------------------------------------------------------------------------------------------------------ | ----- | ---------------------------------------------------- | --------------------------------------------------------------------- |
| master | v7 | [prisma2](https://github.com/prisma/prisma2) | [Code-first](https://docs.nestjs.com/graphql/quick-start#code-first) |
| [Prisma2 Code First](https://github.com/fivethree-team/nestjs-prisma-starter/tree/nest-6-prisma2-code-first) | v6 | [prisma2-preview](https://github.com/prisma/prisma2) | [Code-first](https://github.com/19majkel94/type-graphql) |
| [Prisma1 Code First](https://github.com/fivethree-team/nestjs-prisma-starter/tree/nest-6-code-first) | v6 | [v1](https://github.com/prisma/prisma) | [Code-first](https://github.com/19majkel94/type-graphql) |
| [Prisma1 SDL First]() | v6 | [v1](https://github.com/prisma/prisma) | [SDL First](https://docs.nestjs.com/graphql/quick-start#schema-first) |
| [Prisma1 SDL First](https://github.com/fivethree-team/nestjs-prisma-starter/tree/nest-5) | v5 | [v1](https://github.com/prisma/prisma) | [SDL First](https://docs.nestjs.com/graphql/quick-start#schema-first) |

## Features

- GraphQL w/ [playground](https://github.com/prisma/graphql-playground)
- Code-First w/ [decorators](https://docs.nestjs.com/graphql/quick-start#code-first)
- [Prisma](https://www.prisma.io/) for database modelling, migration and type-safe access (Postgres, MySQL & MongoDB)
- 🔐 JWT authentication w/ [passport-jwt](https://github.com/mikenicholson/passport-jwt)
- REST API docs w/ [Swagger](https://swagger.io/)

## Overview

- [Instructions](#instructions)
- [Features](#features)
- [Overview](#overview)
- [Prisma Setup](#prisma-setup)
- [1. Install Dependencies](#1-install-dependencies)
- [2. Prisma2: Prisma Migrate](#2-prisma2-prisma-migrate)
- [3. Prisma2: Prisma Client JS](#3-prisma2-client-js)
- [4. Seed the database data with this script](#4-seed-the-database-data-with-this-script)
- [5. Install Nestjs](#5-install-nestjs)
- [Start NestJS Server](#start-nestjs-server)
- [Playground](#playground)
- [Rest Api](#rest-api)
- [Docker](#docker)
- [Schema Development](#schema-development)
- [NestJS - Api Schema](#nestjs---api-schema)
- [Resolver](#resolver)
- [Graphql Client](#graphql-client)
- [Angular](#angular)
- [Setup](#setup)
- [Queries](#queries)
- [Mutations](#mutations)
- [Subscriptions](#subscriptions)
- [Authentication](#authentication)

## Prisma Setup

### 1. Install Dependencies

Install the dependencies for the nest server:

```bash
npm install
```

### 2. Prisma2: Prisma Migrate

[Prisma Migrate](https://github.com/prisma/prisma2/tree/master/docs/prisma-migrate) is used to manage the schema and migration of the database.

Saving the migration of the database:

```bash
npx prisma migrate save --experimental
# or
npm run prisma:save
```

Perform the database migration:

```bash
npx prisma migrate up --experimental
# or
npm run prisma:up
```

### 3. Prisma2: Prisma Client JS

[Prisma Client JS](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/api) is a type-safe database client auto-generated based on the data model.

To generate Prisma Client JS execute, this will always be executed after `npm install`:

```bash
npx prisma generate
# or
npm run prisma:generate
```

### 4. Seed the database data with this script

Execute the script with this command:

```bash
npm run seed
```

### 5. Install Nestjs

The [Nestjs CLI](https://docs.nestjs.com/cli/usages) can be used to generate controller, services, resolvers and more.

```bash
npm i -g @nestjs/cli
```

**[⬆ back to top](#overview)**

## Start NestJS Server

Run Nest Server in Development mode:

```bash
npm run start

# watch mode
npm run start:dev
```

Run Nest Server in Production mode:

```bash
npm run start:prod
```

Playground for the NestJS Server is available here: http://localhost:3000/graphql

**[⬆ back to top](#overview)**

## Playground

Some queries and mutations are secured by an auth guard. You have to acquire a JWT token from `signup` or `login`. Add the the auth token as followed to **HTTP HEADERS** in the playground and replace `YOURTOKEN` here:

```json
{
"Authorization": "Bearer YOURTOKEN"
}
```

## Rest Api

[RESTful API](http://localhost:3000/api) documentation available with Swagger.

## Docker

Nest serve is a Node.js application and it is easily [dockerized](https://nodejs.org/de/docs/guides/nodejs-docker-webapp/).

See the [Dockerfile](./Dockerfile) on how to build a Docker image of your Nest server.

Now to build a Docker image of your own Nest server simply run:

```bash
# give your docker image a name
docker build -t /nest-prisma-server .
# for example
docker build -t nest-prisma-server .
```

After Docker build your docker image you are ready to start up a docker container running the nest server:

```bash
docker run -d -t -p 3000:3000 --env-file .env nest-prisma-server
```

Now open up [localhost:3000](http://localhost:3000) to verify that your nest server is running.

## Schema Development

Update the Prisma schema `prisma/schema.prisma` and after that run the following two commands:

```bash
npx prisma generate
# or in watch mode
npx prisma generate --watch
# or
npm run prisma:generate
npm run prisma:generate:watch
```

**[⬆ back to top](#overview)**

## NestJS - Api Schema

The [schema.graphql](./src/schema.graphql) is generated with [code first approach](https://docs.nestjs.com/graphql/quick-start#code-first). The schema is generated from the [models](./src/models/user.ts), the [resolvers](./src/resolvers/auth/auth.resolver.ts) and the [input](./src/resolvers/auth/dto/login.input.ts) classes.

You can use [class-validator](https://docs.nestjs.com/techniques/validation) to validate your inputs and arguments.

### Resolver

To implement the new query, a new resolver function needs to be added to `users.resolver.ts`.

```ts
@Query(returns => User)
async getUser(@Args() args): Promise {
return await this.prisma.client.user(args);
}
```

Restart the NestJS server and this time the Query to fetch a `user` should work.

**[⬆ back to top](#overview)**

## Graphql Client

A graphql client is necessary to consume the graphql api provided by the NestJS Server.

Checkout [Apollo](https://www.apollographql.com/) a popular graphql client which offers several clients for React, Angular, Vue.js, Native iOS, Native Android and more.

### Angular

#### Setup

To start using [Apollo Angular](https://www.apollographql.com/docs/angular/basics/setup.html) simply run in an Angular and Ionic project:

```bash
ng add apollo-angular
```

`HttpLink` from apollo-angular requires the `HttpClient`. Therefore, you need to add the `HttpClientModule` to the `AppModule`:

```ts
imports: [BrowserModule,
HttpClientModule,
...,
GraphQLModule],
```

You can also add the `GraphQLModule` in the `AppModule` to make `Apollo` available in your Angular App.

You need to set the URL to the NestJS Graphql Api. Open the file `src/app/graphql.module.ts` and update `uri`:

```ts
const uri = 'http://localhost:3000/graphql';
```

To use Apollo-Angular you can inject `private apollo: Apollo` into the constructor of a page, component or service.

**[⬆ back to top](#overview)**

#### Queries

To execute a query you can use:

```ts
this.apollo.query({query: YOUR_QUERY});

# or

this.apollo.watchQuery({
query: YOUR_QUERY
}).valueChanges;
```

Here is an example how to fetch your profile from the NestJS Graphql Api:

```ts
const CurrentUserProfile = gql`
query CurrentUserProfile {
me {
id
email
name
}
}
`;

@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage implements OnInit {
data: Observable;

constructor(private apollo: Apollo) {}

ngOnInit() {
this.data = this.apollo.watchQuery({
query: CurrentUserProfile,
}).valueChanges;
}
}
```

Use the `AsyncPipe` and [SelectPipe](https://www.apollographql.com/docs/angular/basics/queries.html#select-pipe) to unwrap the data Observable in the template:

```html


Me id: {{me.id}}


Me email: {{me.email}}


Me name: {{me.name}}



```

Or unwrap the data using [RxJs](https://www.apollographql.com/docs/angular/basics/queries.html#rxjs).

This will end up in an `GraphQL error` because `Me` is protected by an `@UseGuards(GqlAuthGuard)` and requires an `Bearer TOKEN`.
Please refer to the [Authentication](#authentication) section.

**[⬆ back to top](#overview)**

#### Mutations

To execute a mutation you can use:

```ts
this.apollo.mutate({
mutation: YOUR_MUTATION,
});
```

Here is an example how to login into your profile using the `login` Mutation:

```ts
const Login = gql`
mutation Login {
login(email: "test@example.com", password: "pizzaHawaii") {
token
user {
id
email
name
}
}
}
`;

@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage implements OnInit {
data: Observable;

constructor(private apollo: Apollo) {}

ngOnInit() {
this.data = this.apollo.mutate({
mutation: Login,
});
}
}
```

**[⬆ back to top](#overview)**

#### Subscriptions

To execute a subscription you can use:

```ts
this.apollo.subscribe({
query: YOUR_SUBSCRIPTION_QUERY,
});
```

**[⬆ back to top](#overview)**

#### Authentication

To authenticate your requests you have to add your `TOKEN` you receive on `signup` and `login` [mutation](#mutations) to each request which is protected by the `@UseGuards(GqlAuthGuard)`.

Because the apollo client is using `HttpClient` under the hood you are able to simply use an `Interceptor` to add your token to the requests.

Create the following class:

```ts
import { Injectable } from '@angular/core';
import {
HttpEvent,
HttpInterceptor,
HttpHandler,
HttpRequest,
} from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class TokenInterceptor implements HttpInterceptor {
constructor() {}

intercept(
req: HttpRequest,
next: HttpHandler
): Observable> {
const token = 'YOUR_TOKEN'; // get from local storage
if (token !== undefined) {
req = req.clone({
setHeaders: {
Authorization: `Bearer ${token}`,
},
});
}

return next.handle(req);
}
}
```

Add the Interceptor to the `AppModule` providers like this:

```ts
providers: [
...
{ provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true },
...
]
```

After you configured the Interceptor and retrieved the `TOKEN` from storage your request will succeed on resolvers with `@UseGuards(GqlAuthGuard)`.

**[⬆ back to top](#overview)**