Skip to content

Commit 3bd5dc2

Browse files
committed
updates
1 parent 9626dee commit 3bd5dc2

File tree

1 file changed

+26
-18
lines changed

1 file changed

+26
-18
lines changed

content/graphql/resolvers-map.md

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
### Resolvers
22

3-
Resolvers provide the instructions for turning a [GraphQL](https://graphql.org/) operation (a query, mutation, or subscription) into data. They return the same shape of data we specify in our schema -- either synchronously or as a promise that resolves to a result of that shape. Typically, you create a **resolvers map** manually. The `@nestjs/graphql` package, on the other hand, generates a resolvers map automatically using the metadata provided by the decorators. To demonstrate the library basics, we'll create a simple authors API.
3+
Resolvers provide the instructions for turning a [GraphQL](https://graphql.org/) operation (a query, mutation, or subscription) into data. They return the same shape of data we specify in our schema -- either synchronously or as a promise that resolves to a result of that shape. Typically, you create a **resolver map** manually. The `@nestjs/graphql` package, on the other hand, generates a resolver map automatically using the metadata provided by the decorators. To demonstrate the library basics, we'll create a simple authors API.
44

55
#### Code first
66

@@ -156,7 +156,7 @@ In this example, we defined a query handler to get the author object based on th
156156

157157
We can define multiple `@Query()` resolver functions (both within this class, and in any other resolver class), and they will be aggregated into a single **Query type** definition in the generated SDL along with the appropriate entries in the resolver map. This allows you to define queries close to the models and services that they use, and to keep them well organized in modules.
158158

159-
In the above examples, the `@Query()` decorator generates a query type name based on the method name. For example, consider the following construction from the example above:
159+
In the above examples, the `@Query()` decorator generates a GraphQL schema query type name based on the method name. For example, consider the following construction from the example above:
160160

161161
```typescript
162162
@Query(returns => Author)
@@ -165,7 +165,7 @@ In the above examples, the `@Query()` decorator generates a query type name base
165165
}
166166
```
167167

168-
This generates the following resolver map entry for the author query in our schema (the query type entry uses the same name as the method name):
168+
This generates the following entry for the author query in our schema (the query type uses the same name as the method name):
169169

170170
```graphql
171171
type Query {
@@ -267,7 +267,9 @@ You may also notice that arguments classes like `GetAuthorArgs` play very well w
267267

268268
#### Schema first
269269

270-
As mentioned in the [previous](/graphql/quick-start) chapter, in the schema first approach we start by manually defining schema types in SDL (read [more](http://graphql.org/learn/schema/#type-language)). Consider the following type definitions:
270+
As mentioned in the [previous](/graphql/quick-start) chapter, in the schema first approach we start by manually defining schema types in SDL (read [more](http://graphql.org/learn/schema/#type-language)). Consider the following SDL type definitions.
271+
272+
> info **Hint** For convenience in this chapter, we've aggregated all of the SDL in one location (e.g., one `.graphql` file, as shown below). In practice, you may find it appropriate to organize your code in a modular fashion. For example, it can be helpful to create individual SDL files with type definitions representing each domain entity, along with related services, resolver code, and the Nest module definition class, in a dedicated directory for that entity. Nest will aggregate all the individual schema type definitions at run time.
271273

272274
```graphql
273275
type Author {
@@ -288,7 +290,9 @@ type Query {
288290
}
289291
```
290292

291-
This schema exposes a single query - `author(id: Int!): Author`. Let's now create an `AuthorResolver` class that resolves author queries:
293+
### Schema first resolver
294+
295+
The schema above exposes a single query - `author(id: Int!): Author`. Let's now create an `AuthorResolver` class that resolves author queries:
292296

293297
```typescript
294298
@Resolver('Author')
@@ -315,7 +319,7 @@ export class AuthorResolver {
315319
316320
> warning **Warning** The logic inside the `AuthorsService` and `PostsService` classes can be as simple or sophisticated as needed. The main point of this example is to show how to construct resolvers and how they can interact with other providers.
317321
318-
The `@Resolver()` decorator is used to inform Nest that each `@ResolveField()` method inside the class has a parent (the `Author` type in this case). The `@Resolver()` decorator **does not** affect queries (`@Query()` decorator) or mutations (`@Mutation()` decorator). Alternatively, instead of setting `@Resolver()` at the top of the class, this can be done for each method:
322+
The `@Resolver()` decorator is required. It takes an optional string argument with the name of a class. This class name is required whenever the class includes `@ResolveField()` decorators to inform Nest that the decorated method is associated with a parent type (the `Author` type in our current example). Alternatively, instead of setting `@Resolver()` at the top of the class, this can be done for each method:
319323

320324
```typescript
321325
@Resolver('Author')
@@ -328,9 +332,11 @@ async posts(@Parent() author) {
328332

329333
In this case (`@Resolver()` decorator at the method level), if you have multiple `@ResolveField()` decorators inside a class, you must add `@Resolver()` to all of them. This is not considered the best practice (as it creates extra overhead).
330334

335+
> info **Hint** Any class name argument passed to `@Resolver()` **does not** affect queries (`@Query()` decorator) or mutations (`@Mutation()` decorator).
336+
331337
> warning **Warning** Using the `@Resolver` decorator at the method level is not supported with the **code first** approach.
332338
333-
In the above examples, the `@Query()` and `@ResolveField()` decorators are associated with the types based on the method name. For example, consider the following construction from the example above:
339+
In the above examples, the `@Query()` and `@ResolveField()` decorators are associated with GraphQL schema types based on the method name. For example, consider the following construction from the example above:
334340

335341
```typescript
336342
@Query()
@@ -339,15 +345,15 @@ In the above examples, the `@Query()` and `@ResolveField()` decorators are assoc
339345
}
340346
```
341347

342-
This generates the resolver map entry for the author query in our schema (the query type entry uses the same name as the method name):
348+
This generates the following entry for the author query in our schema (the query type uses the same name as the method name):
343349

344350
```graphql
345351
type Query {
346352
author(id: Int!): Author
347353
}
348354
```
349355

350-
Conventionally, we would prefer to decouple these, using names like `getAuthor()` or `getPosts()` for our resolver methods. We can easily do this by passing the mapping names as arguments of the decorator, as shown below
356+
Conventionally, we would prefer to decouple these, using names like `getAuthor()` or `getPosts()` for our resolver methods. We can easily do this by passing the mapping name as an argument to the decorator, as shown below:
351357

352358
```typescript
353359
@Resolver('Author')
@@ -372,7 +378,7 @@ export class AuthorResolver {
372378

373379
#### Generating types
374380

375-
Assuming that we use the schema first approach and have enabled the typings generation feature (with `outputAs: 'class'` as shown in the [previous](/graphql/quick-start) chapter), once you run the application it should generate the following file:
381+
Assuming that we use the schema first approach and have enabled the typings generation feature (with `outputAs: 'class'` as shown in the [previous](/graphql/quick-start) chapter), once you run the application it will generate the following file (in the location you specified in the `GraphQLModule.forRoot()` method. For example, in `src/graphql.ts`)
376382

377383
```typescript
378384
export class Author {
@@ -393,7 +399,7 @@ export abstract class IQuery {
393399
}
394400
```
395401

396-
Generating classes (instead of the default technique of generating interfaces) allows you to use declarative validation **decorators** in combination with the schema first approach, which is an extremely useful technique (read [more](/techniques/validation)). For example, you could add these `class-validator` decorators to the generated `CreatePostInput` class as shown below:
402+
By generating classes (instead of the default technique of generating interfaces), you can use declarative validation **decorators** in combination with the schema first approach, which is an extremely useful technique (read [more](/techniques/validation)). For example, you could add `class-validator` decorators to the generated `CreatePostInput` class as shown below to enforce minimum and maximum string lengths on the `title` field:
397403

398404
```typescript
399405
import { MinLength, MaxLength } from 'class-validator';
@@ -405,7 +411,7 @@ export class CreatePostInput {
405411
}
406412
```
407413

408-
> warning **Notice** To enable auto-validation of your inputs (and parameters), use `ValidationPipe`. Read more about validation [here](/techniques/validation) or more specifically about pipes [here](/pipes).
414+
> warning **Notice** To enable auto-validation of your inputs (and parameters), use `ValidationPipe`. Read more about validation [here](/techniques/validation) and more specifically about pipes [here](/pipes).
409415
410416
However, if you add decorators directly to the automatically generated file, they will be **overwritten** each time the file is generated. Instead, create a separate file and simply extend the generated class.
411417

@@ -420,9 +426,9 @@ export class CreatePostInput extends Post {
420426
}
421427
```
422428

423-
#### Decorators
429+
#### GraphQL resolver argument decorators
424430

425-
We refer to several arguments using dedicated decorators. Below is a comparison of the provided decorators and the plain Apollo parameters they represent.
431+
We can access the standard GraphQL resolver arguments using dedicated decorators. Below is a comparison of the Nest decorators and the plain Apollo parameters they represent.
426432

427433
<table>
428434
<tbody>
@@ -456,7 +462,11 @@ These arguments have the following meanings:
456462

457463
#### Module
458464

459-
Once we're done with the above steps, we have to provide the `AuthorResolver` somewhere (list it as a `provider` in some module, for dependency injection). For example, we can do this in an `AuthorsModule`, which can also provide other services needed in this context.
465+
Once we're done with the above steps, we have declaratively specified all the information needed by the `GraphQLModule` to generate a resolver map. The `GraphQLModule` uses reflection to introspect the meta data provided via the decorators, and transforms classes into the correct resolver map automatically.
466+
467+
The only other thing you need to take care of is to **provide** (i.e., list as a `provider` in some module) the resolver class(es) (`AuthorResolver`), and importing the module (`AuthorsModule`) somewhere, so Nest will be able to utilize it.
468+
469+
For example, we can do this in an `AuthorsModule`, which can also provide other services needed in this context. Be sure to import `AuthorsModule` somewhere (e.g., in the root module, or some other module imported by the root module).
460470

461471
```typescript
462472
@Module({
@@ -466,11 +476,9 @@ Once we're done with the above steps, we have to provide the `AuthorResolver` so
466476
export class AuthorsModule {}
467477
```
468478

469-
The `GraphQLModule` will take care of reflecting the metadata and transforming classes into the correct resolvers map automatically. The only thing you need to be aware of is that you need to import this module somewhere, so Nest will be able to utilize `AuthorsModule`.
470-
471479
> info **Hint** Learn more about GraphQL queries [here](http://graphql.org/learn/queries/).
472480
473-
> info **Hint** It is helpful to organize your code by what we can call your **domain model** (similar to the way you would organize entry points in a REST API). In this approach, keep your models (`ObjectType` classes), resolvers and services together within a Nest module representing the domain model. Keep all of these components in a single folder per module. When you do this, and use the [Nest CLI](/cli/overview) to generate each element, Nest will wire all of these parts together automatically for you.
481+
> info **Hint** It is helpful to organize your code by your so-called **domain model** (similar to the way you would organize entry points in a REST API). In this approach, keep your models (`ObjectType` classes), resolvers and services together within a Nest module representing the domain model. Keep all of these components in a single folder per module. When you do this, and use the [Nest CLI](/cli/overview) to generate each element, Nest will wire all of these parts together automatically for you.
474482
475483
#### CLI Plugin
476484

0 commit comments

Comments
 (0)