☰ Mục lục series
Tài liệu NestJS tiếng Việt
  1. Nhập môn (Overview)
    1. Giới thiệu
    2. First steps
    3. Controllers
    4. Providers
    5. Modules
    6. Middleware
    7. Exception filters
    8. Pipes
    9. Guards
    10. Interceptors
    11. Custom decorators
  2. Nền tảng (Fundamentals)
    1. Custom providers
    2. Asynchronous providers
    3. Dynamic modules
    4. Injection scopes
    5. Circular dependency
    6. Module reference
    7. Lazy-loading modules
    8. Execution context
    9. Lifecycle events
    10. Discovery service
    11. Platform agnosticism
    12. Testing
  3. Kỹ thuật (Techniques)
    1. Configuration
    2. Database (SQL)
    3. MongoDB
    4. Validation
    5. Caching
    6. Serialization
    7. Versioning
    8. Task scheduling
    9. Queues
    10. Logging
    11. Cookies
    12. Events
    13. Compression
    14. File upload
    15. Streaming files
    16. HTTP module
    17. Session
    18. MVC
    19. Performance (Fastify)
    20. Server-Sent Events
  4. Bảo mật (Security)
    1. Authentication
    2. Authorization
    3. Encryption & Hashing
    4. Helmet
    5. CORS
    6. CSRF
    7. Rate limiting
    8. Vòng đời request
  5. OpenAPI (Swagger)
    1. Introduction
    2. Types and parameters
    3. Operations
    4. Security
    5. Mapped types
    6. Decorators
    7. CLI plugin
    8. Other features
  6. Recipes
    1. REPL
    2. CRUD generator
    3. SWC (fast compiler)
    4. Passport (auth)
    5. Hot reload
    6. MikroORM
    7. Router module
    8. Health checks (Terminus)
    9. CQRS
    10. Prisma
    11. Serve static
    12. Commander
    13. Async local storage
  7. WebSockets
    1. Gateways
    2. Exception filters
    3. Pipes
    4. Guards
    5. Interceptors
    6. Adapters
  8. Microservices
    1. Overview
    2. Redis
    3. MQTT
    4. NATS
    5. RabbitMQ
    6. Kafka
    7. gRPC
    8. Custom transporters
    9. Exception filters
    10. Pipes
    11. Pre-request hooks
    12. Guards
    13. Interceptors
  9. GraphQL
    1. Quick start
    2. Resolvers
    3. Mutations
    4. Subscriptions
    5. Scalars
    6. Directives
    7. Interfaces
    8. Unions and enums
    9. Field middleware
    10. Mapped types
    11. Plugins
    12. Complexity
    13. Extensions
    14. CLI plugin
    15. Generating SDL
    16. Sharing models
    17. Other features
    18. Federation
  10. CLI & triển khai
    1. CLI overview
    2. Workspaces
    3. Libraries
    4. Usage
    5. Scripts
    6. Deployment
    7. Standalone apps
  11. FAQ
    1. Serverless
    2. HTTP adapter
    3. Keep-Alive connections
    4. Global path prefix
    5. Raw body
    6. Hybrid application
    7. HTTPS & multiple servers
    8. Common errors
  12. Phụ lục
    1. Bảng thuật ngữ
GraphQL

Tận dụng sức mạnh của TypeScript & GraphQL

Bản dịch từ docs.nestjs.com/graphql/quick-start

GraphQL là một ngôn ngữ truy vấn (query language) mạnh mẽ cho API và là một runtime để thực thi các truy vấn đó dựa trên dữ liệu sẵn có của bạn. Đây là một cách tiếp cận thanh thoát, giải quyết được nhiều vấn đề thường gặp với REST API. Để có thêm bối cảnh, bạn nên đọc bài so sánh này giữa GraphQL và REST. GraphQL kết hợp với TypeScript giúp bạn phát triển với type safety tốt hơn cho các GraphQL query, mang lại kiểm tra kiểu dữ liệu xuyên suốt từ đầu đến cuối (end-to-end typing).

Trong chương này, chúng ta giả định bạn đã hiểu cơ bản về GraphQL, và tập trung vào cách làm việc với module @nestjs/graphql có sẵn. GraphQLModule có thể được cấu hình để dùng Apollo server (thông qua driver @nestjs/apollo) hoặc Mercurius (thông qua @nestjs/mercurius). Chúng tôi cung cấp tích hợp chính thức cho các package GraphQL đã được kiểm chứng này để bạn dùng GraphQL với Nest một cách đơn giản (xem thêm các tích hợp khác tại đây).

Bạn cũng có thể tự xây dựng driver riêng cho mình (đọc thêm tại đây).

Ghi chú người dịch Nếu bạn từng làm REST với Express, hãy hình dung GraphQLModule như một middleware/router đặc biệt: thay vì bạn tự định nghĩa nhiều route (GET /posts, GET /posts/:id…), bạn định nghĩa một schema duy nhất và client tự chọn field nào mình cần trong một request.

Cài đặt

Bắt đầu bằng việc cài các package cần thiết:

# Dành cho Express và Apollo (mặc định)
$ npm i @nestjs/graphql @nestjs/apollo @apollo/server @as-integrations/express5 graphql

# Dành cho Fastify và Apollo
# npm i @nestjs/graphql @nestjs/apollo @apollo/server @as-integrations/fastify graphql

# Dành cho Fastify và Mercurius
# npm i @nestjs/graphql @nestjs/mercurius graphql mercurius

Cảnh báo Các package @nestjs/graphql@>=9 và @nestjs/apollo^10 tương thích với Apollo v3 (xem hướng dẫn migration của Apollo Server 3 để biết thêm chi tiết), trong khi @nestjs/graphql@^8 chỉ hỗ trợ Apollo v2 (ví dụ package [email protected]).

Tổng quan

Nest cung cấp hai cách để xây dựng ứng dụng GraphQL: code first và schema first. Bạn nên chọn cách phù hợp nhất với mình. Hầu hết các chương trong phần GraphQL này đều chia làm hai phần chính: một phần dành cho ai theo code first, phần còn lại dành cho ai theo schema first.

Trong cách tiếp cận code first, bạn dùng decorator và class TypeScript để tạo ra schema GraphQL tương ứng. Cách này hữu ích nếu bạn muốn làm việc hoàn toàn với TypeScript và tránh phải chuyển đổi qua lại giữa các cú pháp ngôn ngữ khác nhau.

Trong cách tiếp cận schema first, nguồn chân lý (source of truth) là các file GraphQL SDL (Schema Definition Language). SDL là một cách viết schema độc lập với ngôn ngữ, dùng để chia sẻ file schema giữa các nền tảng khác nhau. Nest sẽ tự động sinh ra các định nghĩa TypeScript (dùng class hoặc interface) dựa trên schema GraphQL để giảm bớt việc phải viết code khung (boilerplate) trùng lặp.

Bắt đầu với GraphQL & TypeScript

Gợi ý Trong các chương tiếp theo, chúng ta sẽ tích hợp package @nestjs/apollo. Nếu bạn muốn dùng package mercurius thay thế, hãy xem phần này.

Sau khi cài xong các package, chúng ta có thể import GraphQLModule và cấu hình nó bằng static method forRoot().

import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';

@Module({
  imports: [
    GraphQLModule.forRoot<ApolloDriverConfig>({
      driver: ApolloDriver,
    }),
  ],
})
export class AppModule {}

Gợi ý Với tích hợp mercurius, bạn nên dùng MercuriusDriver và MercuriusDriverConfig thay thế. Cả hai đều được export từ package @nestjs/mercurius.

Method forRoot() nhận một object options làm tham số. Các option này được truyền thẳng xuống instance driver bên dưới (đọc thêm về các cấu hình khả dụng tại đây: Apollo và Mercurius). Ví dụ, nếu bạn muốn tắt GraphQL IDE, truyền các option sau:

import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';

@Module({
  imports: [
    GraphQLModule.forRoot<ApolloDriverConfig>({
      driver: ApolloDriver,
      graphiql: false,
    }),
  ],
})
export class AppModule {}

Cảnh báo IDE graphql-playground đã bị loại bỏ khỏi @nestjs/graphql từ v14. Option playground vẫn còn tồn tại nhưng chỉ là một alias boolean đã deprecated cho GraphiQL — playground: false sẽ tắt landing page và playground: true sẽ bật GraphiQL — nhưng code mới nên dùng graphiql thay thế.

Trong trường hợp này, các option sẽ được chuyển tiếp đến constructor của ApolloServer.

Truy cập đối tượng request và response

Một option driver đáng chú ý là context, một factory dùng để xây dựng ngữ cảnh thực thi (execution context) GraphQL cho mỗi request. Dùng option này để đưa các đối tượng request và response gốc vào resolver:

GraphQLModule.forRoot<ApolloDriverConfig>({
  driver: ApolloDriver,
  context: ({ req, res }) => ({ req, res }),
}),

Với cấu hình này, bạn có thể đọc chúng trong resolver thông qua decorator @Context():

@Query(() => String)
userAgent(@Context('req') req: Request): string {
  return req.headers['user-agent'] ?? '';
}

Gợi ý Guard, interceptor và các enhancer khác chạy trong ngữ cảnh GraphQL đều có thể truy cập cùng một object đó thông qua GqlExecutionContext.create(context).getContext() (xem Các tính năng khác).

Ghi chú người dịch Nếu bạn quen Express thuần, context ở đây tương tự việc bạn gắn req, res vào một object dùng chung cho middleware chain — chỉ khác là GraphQL gói tất cả field/query của một request lại thành một “execution context” duy nhất, thay vì mỗi route có req/res riêng như REST.

GraphQL IDE

GraphiQL là IDE GraphQL đồ họa, tương tác, chạy ngay trên trình duyệt, được phục vụ mặc định trên cùng URL với GraphQL server. Để truy cập, bạn cần có một GraphQL server cơ bản đã được cấu hình và đang chạy. Để xem ngay, bạn có thể cài đặt và build ví dụ mẫu tại đây. Ngoài ra, nếu bạn đang theo các ví dụ code trong tài liệu này, sau khi hoàn thành các bước ở chương Resolver, bạn có thể truy cập GraphiQL.

Khi đã có cấu hình trên, và ứng dụng của bạn đang chạy nền, bạn có thể mở trình duyệt và truy cập http://localhost:3000/graphql (host và port có thể khác tùy cấu hình của bạn). Bạn sẽ thấy GraphiQL như hình dưới đây.

Lưu ý Tích hợp @nestjs/mercurius cũng dùng GraphiQL.

Bật và tắt GraphiQL

Kể từ @nestjs/graphql v14, GraphiQL là IDE GraphQL duy nhất — graphql-playground cũ đã bị loại bỏ hoàn toàn. GraphiQL được tự động bật bất cứ khi nào NODE_ENV khác production, nên trong môi trường development bạn có nó mà không cần cấu hình gì thêm, còn trong production thì landing page mặc định bị tắt.

Để kiểm soát rõ ràng, dùng option graphiql:

GraphQLModule.forRoot<ApolloDriverConfig>({
  driver: ApolloDriver,
  graphiql: true, // ép bật, kể cả trong production
}),
GraphQLModule.forRoot<ApolloDriverConfig>({
  driver: ApolloDriver,
  graphiql: false, // tắt hoàn toàn landing page
}),

Cảnh báo Option playground vẫn còn tồn tại, nhưng chỉ là một alias boolean đã deprecated cho graphiql. Nếu cả hai được set, graphiql sẽ được ưu tiên. Hãy chuyển playground: false thành graphiql: false và playground: true thành graphiql: true.

Cấu hình GraphiQL

Truyền một object thay vì boolean để vừa bật GraphiQL vừa cấu hình nó:

GraphQLModule.forRoot<ApolloDriverConfig>({
  driver: ApolloDriver,
  graphiql: {
    url: '/graphql',
    headers: {
      authorization: 'Bearer <token>',
    },
    shouldPersistHeaders: true,
    isHeadersEditorEnabled: true,
    inputValueDeprecation: false,
  },
}),

Các option khả dụng gồm:

url Endpoint mà IDE gửi operation đến. Mặc định lấy theo option path của driver, nên bạn chỉ cần set giá trị này khi IDE cần trỏ tới một URL khác với URL mà nó đang được phục vụ.
headers Các header được áp dụng cho mọi request. Hữu ích khi bạn muốn cấu hình sẵn header authorization trong lúc phát triển. Nếu trình chỉnh sửa header được bật và người dùng set cùng một header, giá trị của họ sẽ được ưu tiên.
shouldPersistHeaders Có lưu lại nội dung của trình chỉnh sửa header vào bộ nhớ trình duyệt hay không. Mặc định: true.
isHeadersEditorEnabled Có hiển thị trình chỉnh sửa header trong các công cụ của editor hay không. Set false để không cho người dùng chỉnh sửa header. Mặc định: true.
inputValueDeprecation Nếu true, tài liệu schema sẽ bao gồm cả các input field và giá trị argument đã deprecated, và introspection sẽ trả về chúng. Mặc định: false.

Gợi ý Vì GraphiQL mặc định bật ngoài môi trường production, một cấu hình phổ biến là cứ để nguyên khi phát triển và chỉ set graphiql: false khi bạn cần ẩn schema trong môi trường không phải production nhưng lại có thể truy cập công khai.

Subscription trong IDE

Nếu ứng dụng của bạn dùng subscription, hãy dùng graphql-ws. Việc hỗ trợ subscriptions-transport-ws đã bị loại bỏ — nó không còn được chấp nhận như một key subscriptions và package này cũng không còn là dependency nữa:

GraphQLModule.forRoot<ApolloDriverConfig>({
  driver: ApolloDriver,
  subscriptions: {
    'graphql-ws': true,
  },
}),

Với cấu hình này, GraphiQL có thể thực thi trực tiếp các operation subscription lên server của bạn.

Code first

Trong cách tiếp cận code first, bạn dùng decorator và class TypeScript để tạo ra schema GraphQL tương ứng.

Để dùng cách tiếp cận code first, bắt đầu bằng cách thêm property autoSchemaFile vào object options:

GraphQLModule.forRoot<ApolloDriverConfig>({
  driver: ApolloDriver,
  autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
}),

Giá trị của property autoSchemaFile là đường dẫn nơi schema tự động sinh ra sẽ được tạo. Ngoài ra, schema cũng có thể được sinh ngay trong bộ nhớ (in memory). Để bật tính năng này, set property autoSchemaFile thành true:

GraphQLModule.forRoot<ApolloDriverConfig>({
  driver: ApolloDriver,
  autoSchemaFile: true,
}),

Mặc định, các type trong schema sinh ra sẽ theo đúng thứ tự chúng được định nghĩa trong các module được include. Để sắp xếp schema theo thứ tự bảng chữ cái (lexicographically), set property sortSchema thành true:

GraphQLModule.forRoot<ApolloDriverConfig>({
  driver: ApolloDriver,
  autoSchemaFile: join(process.cwd(), 'src/schema.gql'),
  sortSchema: true,
}),

Ví dụ

Một ví dụ code first đầy đủ có tại đây.

Schema first

Để dùng cách tiếp cận schema first, bắt đầu bằng cách thêm property typePaths vào object options. Property typePaths cho biết GraphQLModule nên tìm các file định nghĩa schema GraphQL SDL mà bạn sẽ viết ở đâu. Các file này sẽ được gộp lại trong bộ nhớ; điều này cho phép bạn chia schema thành nhiều file và đặt chúng gần resolver tương ứng.

GraphQLModule.forRoot<ApolloDriverConfig>({
  driver: ApolloDriver,
  typePaths: ['./**/*.graphql'],
}),

Thông thường bạn cũng cần có các định nghĩa TypeScript (class và interface) tương ứng với các type trong GraphQL SDL. Việc tự tay viết các định nghĩa TypeScript tương ứng vừa dư thừa vừa tốn công. Nó cũng khiến chúng ta không còn một nguồn chân lý duy nhất – mỗi thay đổi trong SDL đều buộc ta phải chỉnh lại định nghĩa TypeScript. Để giải quyết vấn đề này, package @nestjs/graphql có thể tự động sinh định nghĩa TypeScript từ cây cú pháp trừu tượng (AST). Để bật tính năng này, thêm property options definitions khi cấu hình GraphQLModule.

GraphQLModule.forRoot<ApolloDriverConfig>({
  driver: ApolloDriver,
  typePaths: ['./**/*.graphql'],
  definitions: {
    path: join(process.cwd(), 'src/graphql.ts'),
  },
}),

Property path trong object definitions cho biết nơi lưu output TypeScript được sinh ra. Mặc định, tất cả các type TypeScript được sinh ra đều là interface. Để sinh ra class thay vì interface, chỉ định property outputAs với giá trị 'class'.

GraphQLModule.forRoot<ApolloDriverConfig>({
  driver: ApolloDriver,
  typePaths: ['./**/*.graphql'],
  definitions: {
    path: join(process.cwd(), 'src/graphql.ts'),
    outputAs: 'class',
  },
}),

Cách trên sẽ sinh động (dynamically) các định nghĩa TypeScript mỗi khi ứng dụng khởi động. Ngoài ra, bạn cũng có thể muốn viết một script đơn giản để sinh chúng theo yêu cầu. Ví dụ, giả sử ta tạo script sau với tên generate-typings.ts:

import { GraphQLDefinitionsFactory } from '@nestjs/graphql';
import { join } from 'node:path';

const definitionsFactory = new GraphQLDefinitionsFactory();
definitionsFactory.generate({
  typePaths: ['./src/**/*.graphql'],
  path: join(process.cwd(), 'src/graphql.ts'),
  outputAs: 'class',
});

Giờ bạn có thể chạy script này theo yêu cầu:

$ ts-node generate-typings

Gợi ý Bạn có thể biên dịch script này trước (ví dụ bằng tsc) rồi dùng node để chạy nó.

Để bật chế độ watch cho script (tự động sinh typings mỗi khi có file .graphql thay đổi), truyền option watch vào method generate().

definitionsFactory.generate({
  typePaths: ['./src/**/*.graphql'],
  path: join(process.cwd(), 'src/graphql.ts'),
  outputAs: 'class',
  watch: true,
});

Để tự động sinh thêm field __typename cho mỗi object type, bật option emitTypenameField:

definitionsFactory.generate({
  // ...
  emitTypenameField: true,
});

Để sinh resolver (query, mutation, subscription) dưới dạng field thuần không có argument, bật option skipResolverArgs:

definitionsFactory.generate({
  // ...
  skipResolverArgs: true,
});

Để sinh enum dưới dạng TypeScript union type thay vì enum TypeScript thông thường, set option enumsAsTypes thành true:

definitionsFactory.generate({
  // ...
  enumsAsTypes: true,
});

Apollo Sandbox

Để dùng Apollo Sandbox thay vì GraphiQL làm IDE GraphQL cho phát triển local, dùng cấu hình sau:

import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { ApolloServerPluginLandingPageLocalDefault } from '@apollo/server/plugin/landingPage/default';

@Module({
  imports: [
    GraphQLModule.forRoot<ApolloDriverConfig>({
      driver: ApolloDriver,
      graphiql: false,
      plugins: [ApolloServerPluginLandingPageLocalDefault()],
    }),
  ],
})
export class AppModule {}

Ví dụ

Một ví dụ schema first đầy đủ có tại đây.

Truy cập schema đã được sinh ra

Trong một số trường hợp (ví dụ như test end-to-end), bạn có thể muốn lấy tham chiếu tới object schema đã được sinh ra. Trong test end-to-end, bạn có thể chạy query bằng object graphql mà không cần dùng bất kỳ HTTP listener nào.

Bạn có thể truy cập schema đã sinh (dù theo cách code first hay schema first), bằng class GraphQLSchemaHost:

const { schema } = app.get(GraphQLSchemaHost);

Gợi ý Bạn phải gọi getter GraphQLSchemaHost#schema sau khi ứng dụng đã được khởi tạo (sau khi hook onModuleInit đã được kích hoạt bởi method app.listen() hoặc app.init()).

Cấu hình bất đồng bộ

Khi bạn cần truyền option module một cách bất đồng bộ thay vì tĩnh, dùng method forRootAsync(). Cũng như hầu hết các dynamic module khác, Nest cung cấp nhiều kỹ thuật để xử lý cấu hình bất đồng bộ.

Một kỹ thuật là dùng factory function:

 GraphQLModule.forRootAsync<ApolloDriverConfig>({
  driver: ApolloDriver,
  useFactory: () => ({
    typePaths: ['./**/*.graphql'],
  }),
}),

Cũng như các factory provider khác, factory function của chúng ta có thể là bất đồng bộ (async) và có thể inject dependency thông qua inject.

GraphQLModule.forRootAsync<ApolloDriverConfig>({
  driver: ApolloDriver,
  imports: [ConfigModule],
  useFactory: async (configService: ConfigService) => ({
    typePaths: configService.get<string>('GRAPHQL_TYPE_PATHS'),
  }),
  inject: [ConfigService],
}),

Ngoài ra, bạn cũng có thể cấu hình GraphQLModule bằng một class thay vì factory, như dưới đây:

GraphQLModule.forRootAsync<ApolloDriverConfig>({
  driver: ApolloDriver,
  useClass: GqlConfigService,
}),

Cách viết trên sẽ khởi tạo GqlConfigService bên trong GraphQLModule, dùng nó để tạo ra object options. Lưu ý rằng trong ví dụ này, GqlConfigService phải implement interface GqlOptionsFactory, như dưới đây. GraphQLModule sẽ gọi method createGqlOptions() trên instance của class được cung cấp.

@Injectable()
class GqlConfigService implements GqlOptionsFactory {
  createGqlOptions(): ApolloDriverConfig {
    return {
      typePaths: ['./**/*.graphql'],
    };
  }
}

Nếu bạn muốn tái sử dụng một options provider đã có sẵn thay vì tạo một bản riêng bên trong GraphQLModule, dùng cú pháp useExisting.

GraphQLModule.forRootAsync<ApolloDriverConfig>({
  imports: [ConfigModule],
  useExisting: ConfigService,
}),

Ghi chú người dịch Nếu bạn từng dùng Laravel service container, forRootAsync với useFactory/useClass/useExisting gợi nhớ đến việc bind một service vào container thông qua closure hoặc class — Nest chỉ đơn giản là chuẩn hóa 3 kiểu binding phổ biến đó thành một API dùng chung cho mọi dynamic module, không riêng gì GraphQL.

Tích hợp Mercurius

Thay vì dùng Apollo, người dùng Fastify (đọc thêm tại đây) có thể dùng driver @nestjs/mercurius thay thế.

import { Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
import { MercuriusDriver, MercuriusDriverConfig } from '@nestjs/mercurius';

@Module({
  imports: [
    GraphQLModule.forRoot<MercuriusDriverConfig>({
      driver: MercuriusDriver,
      graphiql: true,
    }),
  ],
})
export class AppModule {}

Gợi ý Sau khi ứng dụng chạy, mở trình duyệt và truy cập http://localhost:3000/graphiql. Bạn sẽ thấy GraphQL IDE.

Method forRoot() nhận một object options làm tham số. Các option này được truyền thẳng xuống instance driver bên dưới. Đọc thêm về các cấu hình khả dụng tại đây.

Nhiều endpoint

Một tính năng hữu ích khác của module @nestjs/graphql là khả năng phục vụ nhiều endpoint cùng lúc. Điều này cho phép bạn quyết định module nào sẽ được đưa vào endpoint nào. Mặc định, GraphQL sẽ tìm resolver trên toàn bộ ứng dụng. Để giới hạn việc quét chỉ trong một tập con module, dùng property include.

GraphQLModule.forRoot({
  include: [CatsModule],
}),

Trong cách tiếp cận code first, option include chỉ quyết định module nào được quét để tìm resolver. Các type được decorate bằng @ObjectType(), @InputType(), @InterfaceType(), @ArgsType(), hoặc được đăng ký qua registerEnumType() / createUnionType() vẫn sẽ xuất hiện trong mọi schema được sinh ra. Để giới hạn một type vào một module cụ thể, dùng option registerIn:

@ObjectType({ registerIn: () => CatsModule })
export class Cat {
  @Field()
  name: string;
}

Giờ đây, khi schema được build với include: [CatsModule], chỉ những type được gán cho CatsModule mới trở thành một phần của nó, còn các type được gán cho module khác sẽ bị bỏ qua. Các type không có registerIn vẫn giữ hành vi mặc định và có mặt trong mọi schema có tham chiếu tới chúng.

Option registerIn khả dụng trên @InputType(), @InterfaceType(), và @ArgsType(), cũng như registerEnumType() và createUnionType():

@InputType({ registerIn: () => CatsModule })
export class CreateCatInput {
  @Field()
  name: string;
}

registerEnumType(CatBreed, {
  name: 'CatBreed',
  registerIn: () => CatsModule,
});

export const CatsUnion = createUnionType({
  name: 'CatsUnion',
  types: () => [Lion, Tiger] as const,
  registerIn: () => CatsModule,
});

Gợi ý Bạn có thể truyền trực tiếp class module hoặc một factory function trả về nó. Ưu tiên dùng dạng factory (() => CatsModule) bất cứ khi nào type và module tham chiếu lẫn nhau, vì cách này trì hoãn việc resolve module, nhờ đó tránh được lỗi do circular import gây ra.

Cảnh báo Nếu bạn dùng @apollo/server với package @as-integrations/fastify cùng nhiều endpoint GraphQL trong một ứng dụng, hãy nhớ bật setting disableHealthCheck trong cấu hình GraphQLModule.

Tích hợp bên thứ ba

Ví dụ

Một ví dụ hoạt động đầy đủ có tại đây.

Nội dung gốc: NestJS Documentation © Kamil Myśliwiec, giấy phép MIT. Bản dịch và ghi chú: Lê Văn Dũng.