You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: content/graphql/resolvers-map.md
+26-18Lines changed: 26 additions & 18 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
### Resolvers
2
2
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.
4
4
5
5
#### Code first
6
6
@@ -156,7 +156,7 @@ In this example, we defined a query handler to get the author object based on th
156
156
157
157
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.
158
158
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:
160
160
161
161
```typescript
162
162
@Query(returns=>Author)
@@ -165,7 +165,7 @@ In the above examples, the `@Query()` decorator generates a query type name base
165
165
}
166
166
```
167
167
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):
169
169
170
170
```graphql
171
171
typeQuery {
@@ -267,7 +267,9 @@ You may also notice that arguments classes like `GetAuthorArgs` play very well w
267
267
268
268
#### Schema first
269
269
270
-
Asmentionedinthe [previous](/graphql/quick-start) chapter, intheschema 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
+
Asmentionedinthe [previous](/graphql/quick-start) chapter, intheschema 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.
271
273
272
274
```graphql
273
275
type Author {
@@ -288,7 +290,9 @@ type Query {
288
290
}
289
291
```
290
292
291
-
Thisschema 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
+
Theschema above exposes a single query - `author(id: Int!): Author`. Let's now create an `AuthorResolver` class that resolves author queries:
292
296
293
297
```typescript
294
298
@Resolver('Author')
@@ -315,7 +319,7 @@ export class AuthorResolver {
315
319
316
320
> 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.
317
321
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:
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).
330
334
335
+
> info **Hint** Any class name argument passed to `@Resolver()`**does not** affect queries (`@Query()` decorator) or mutations (`@Mutation()` decorator).
336
+
331
337
> warning **Warning** Using the `@Resolver` decorator at the method level is not supported with the **code first** approach.
332
338
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:
334
340
335
341
```typescript
336
342
@Query()
@@ -339,15 +345,15 @@ In the above examples, the `@Query()` and `@ResolveField()` decorators are assoc
339
345
}
340
346
```
341
347
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):
343
349
344
350
```graphql
345
351
typeQuery {
346
352
author(id: Int!): Author
347
353
}
348
354
```
349
355
350
-
Conventionally, wewouldprefertodecouplethese, usingnameslike `getAuthor()` or `getPosts()` forourresolvermethods. Wecaneasilydothisbypassingthemappingnamesasargumentsofthedecorator, asshownbelow
356
+
Conventionally, wewouldprefertodecouplethese, usingnameslike `getAuthor()` or `getPosts()` forourresolvermethods. Wecaneasilydothisbypassingthemappingnameasanargumenttothedecorator, asshownbelow:
351
357
352
358
```typescript
353
359
@Resolver('Author')
@@ -372,7 +378,7 @@ export class AuthorResolver {
372
378
373
379
#### Generating types
374
380
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`)
376
382
377
383
```typescript
378
384
exportclassAuthor {
@@ -393,7 +399,7 @@ export abstract class IQuery {
393
399
}
394
400
```
395
401
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:
@@ -405,7 +411,7 @@ export class CreatePostInput {
405
411
}
406
412
```
407
413
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).
409
415
410
416
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.
411
417
@@ -420,9 +426,9 @@ export class CreatePostInput extends Post {
420
426
}
421
427
```
422
428
423
-
#### Decorators
429
+
#### GraphQL resolver argument decorators
424
430
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.
426
432
427
433
<table>
428
434
<tbody>
@@ -456,7 +462,11 @@ These arguments have the following meanings:
456
462
457
463
#### Module
458
464
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).
460
470
461
471
```typescript
462
472
@Module({
@@ -466,11 +476,9 @@ Once we're done with the above steps, we have to provide the `AuthorResolver` so
466
476
exportclassAuthorsModule {}
467
477
```
468
478
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
-
471
479
> info **Hint** Learn more about GraphQL queries [here](http://graphql.org/learn/queries/).
472
480
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.
0 commit comments