Application - Server - NestJs & GraphQL
# Installing:
# Nestjs
Để cài đặt NestJs có thể clone git hoặc thông qua NestCLI (opens new window)
## Clone git
$ git clone https://github.com/nestjs/typescript-starter.git project
$ cd project
$ npm install
$ npm run start
## NestCLI
$ npm i -g @nestjs/cli
$ nest new project-name
2
3
4
5
6
7
8
9
# GraphQL
NestJs sử dụng GraphQL thông qua Apollo (opens new window) Server (Nền tảng cho phép có thể làm việc với GraphQL và tương thích với bất kì Apollo Client nào).
Install Apollo và graphql.
$ npm i @nestjs/graphql graphql apollo-server-express
# Mongodb & TypeORM
Database được sử dụng là mongodb và thư viện ORM (Object Relational Mapper) được sử dụng là TypeORM. Và có thể làm việc tốt với NestJS vì sử dụng TypeScript.
$ npm install --save typeorm mysql
# Setting:
# Structure:
...
├── src/
| ├── config/
| | ├── graphql/
| | | ├── schemaDirectives/
| | | └── graphql.service.ts
| |
| | ├── typeorm/
| | | └── typeorm.service.ts
| | |
| ├── modules/
| |
| ├── app.module.ts
| ├── graphql.ts
| ├── main.ts
...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
AppModule:
Import các module trong AppModule. Với GraphQLModule và TypeOrmModule sử dụng method
forRootAsync
để pass các service chứa các option vào constructor của module class.import { Module, CacheModule } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { GraphQLModule } from '@nestjs/graphql'; import { GraphqlService, TypeOrmService, } from './config'; @Module({ imports: [ GraphQLModule.forRootAsync({ useClass: GraphqlService, }), TypeOrmModule.forRootAsync({ useClass: TypeOrmService, }), /* Other module */ ], }) export class AppModule { }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21GraphqlService:
import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; import { GqlOptionsFactory, GqlModuleOptions } from '@nestjs/graphql'; import { MemcachedCache } from 'apollo-server-cache-memcached'; import { UserService } from '../../modules/user/services'; import { join } from 'path'; import schemaDirectives from './schemaDirectives'; @Injectable() export class GraphqlService implements GqlOptionsFactory { constructor(private readonly userService: UserService) { } async createGqlOptions(): Promise<GqlModuleOptions> { return { typePaths: ['./**/*.graphql'], definitions: { path: join(process.cwd(), 'src/graphql.ts'), outputAs: 'class', }, schemaDirectives, context: async ({req, res, connection}) => { if (connection) { return { req: connection.context, }; } let currentUser: any; const {token} = req.headers; const excludeOperations = ['loginQuery', 'refreshTokenQuery']; if (req.body && !excludeOperations.includes(req.body.operationName) && token) { currentUser = await this.userService.findByToken(token); } return { req, res, currentUser, }; }, formatError: err => { return err; }, formatResponse: res => { return res; }, debug: false, persistedQueries: { cache: new MemcachedCache( ['memcached-server-1', 'memcached-server-2', 'memcached-server-3'], {retries: 10, retry: 10000}, ), }, installSubscriptionHandlers: true, subscriptions: { onConnect: async (connectionParams: any) => { const authToken = connectionParams.authToken; const currentUser = await this.userService.findByToken(authToken); return {currentUser}; }, }, introspection: true, playground: process.env.NODE_ENV === 'prod' ? false : { settings: { .... }, }, }; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74NestJs có thể triển khai GraqhQL bằng 2 phương pháp Code first hoặc Schema first.
Xem thêm để hiểu về 2 phương pháp này.
Trường hợp này mình sử dụng Schema first. Các properties:
- typePaths: khai báo cho GraphQLModule biết các file GraphQL Schema được định nghĩa. Các file Schema có thể được chia trong nhiều module khác nhau.
- definitions: GraphQLModule sẽ đọc tất cả file
.graphql
khai báo ởtypePaths
để tự động generate filesrc/graphql.ts
. Vì vậy trường hợp nhiều module tên của các type,.. trong.graphql
nên kèm prefix tên module để tránh trường hợp duplicate name. - schemaDirectives: Khai báo các directive trong folder schemaDirectives.
- context: handle context request, ở đây sử dụng để verify token và merge thông tin user vào request. Các directive có thể get thông tin context để xử lí.
- installSubscriptionHandlers: true để sử dụng GraphQL subscription.
- subscriptions: verify token cho subscription, get token từ
connectionParams
củaWebSocketLink
Apollo client và kiểm tra. - playground: 1 công cụ xịn sò cho phép thực hiện các query, mutation hay subscription thay vì sử dụng các tool khác như Postman,.. Ngoài ra còn có thể xem file schema và danh sách các queries, mutations, subscription ở dạng doc. Sử dụng browser và truy cập
http://localhost:3000/graphql
- Ngoài ra còn nhiều properties khác có thể xem tại https://docs.nestjs.com/graphql/quick-start (opens new window)
Series:
- Preview (opens new window)
- Server - NestJs & GraphQL (opens new window)
- Server - Module (opens new window)
- Server - Validation (opens new window)
- Server - Authentication (opens new window)
- Server - Supscription & Upload file (opens new window)
- Client - Angular & GraphQL (opens new window)
GitHub: https://github.com/ninhnguyen22/nestjs-angular-graphql (opens new window)