Skip to content

Commit 892c085

Browse files
committed
updates
1 parent a1eb1d9 commit 892c085

File tree

1 file changed

+21
-17
lines changed

1 file changed

+21
-17
lines changed

content/graphql/resolvers-map.md

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ Resolvers provide the instructions for turning a [GraphQL](https://graphql.org/)
66

77
In the code first approach, we don't write GraphQL SDL by hand. Instead we use TypeScript decorators. The `@nestjs/graphql` package will then read the metadata defined through these decorators and automatically generate the schema for you.
88

9-
Most of the definitions in a GraphQL schema are **object types**. Each object type you define should represent an object that an application client might need to interact with. For example, our sample API needs to be able to fetch a list of authors and their posts, so we should define the `Author` type and `Post` type to support this functionality.
9+
Most of the definitions in a GraphQL schema are **object types**. Each object type you define should represent a domain object that an application client might need to interact with. For example, our sample API needs to be able to fetch a list of authors and their posts, so we should define the `Author` type and `Post` type to support this functionality.
1010

11-
In the schema first approach, we'd define such a schema with SDL like this:
11+
If we were using the schema first approach, we'd define such a schema with SDL like this:
1212

1313
```graphql
1414
type Author {
@@ -19,7 +19,7 @@ type Author {
1919
}
2020
```
2121

22-
In the code first approach, on the other hand, we start by defining TypeScript classes and using TypeScript decorators to annotate the fields of those classes. The equivalent of the above SDL in the code first approach is:
22+
In this case, using the code first approach, we define schemas using TypeScript classes and using TypeScript decorators to annotate the fields of those classes. The equivalent of the above SDL in the code first approach is:
2323

2424
```typescript
2525
import { Field, Int, ObjectType } from '@nestjs/graphql';
@@ -41,19 +41,21 @@ export class Author {
4141
}
4242
```
4343

44-
> info **Hint** TypeScript's metadata reflection system has several limitations which make it impossible to, for instance, determine what properties a class consists of or recognize whether a given property is optional or required. Thus, we must either use the `@Field` decorator or use a [CLI plugin](/graphql/resolvers#cli-plugin).
44+
> info **Hint** TypeScript's metadata reflection system has several limitations which make it impossible to, for instance, determine what properties a class consists of or recognize whether a given property is optional or required. Because of these limitations, we must either explicitly use the `@Field` decorator in our schema definition classes, or use a [CLI plugin](/graphql/resolvers#cli-plugin) to generate these for us.
4545
46-
The `Author` object type has a collection of fields. Each field has a type. A field's type can be either an object type or a scalar type. A scalar type is a primitive (like `ID`, `String`, `Boolean`, or `Int`) that resolves to a single value. In addition to GraphQL's built-in scalar types, you can define custom scalar types.
46+
The `Author` object type, like any class, is made of a collection of fields, with each field declaring a type. The types correspond to [GraphQL types](https://graphql.org/learn/schema/). A field's GraphQL type can be either an object type or a scalar type. A scalar type is a primitive (like `ID`, `String`, `Boolean`, or `Int`) that resolves to a single value.
47+
48+
> info **Hint** In addition to GraphQL's built-in scalar types, you can define custom scalar types.
4749
4850
The above `Author` object type definition will generate the SDL we showed above.
4951

50-
The `@Field()` decorator accepts an optional function returning a type (e.g., `type => Int`), and optionally an object with the following keys:
52+
The `@Field()` decorator accepts a type function (e.g., `type => Int`), and optionally an object with the following keys:
5153

52-
- `nullable`: for specifying whether a field is nullable (in SDL, each field is non-nullable by default)
53-
- `description`: for setting a field description
54-
- `deprecationReason`: for marking a field as deprecated
54+
- `nullable`: for specifying whether a field is nullable (in SDL, each field is non-nullable by default); `boolean`
55+
- `description`: for setting a field description; `string`
56+
- `deprecationReason`: for marking a field as deprecated; `string`
5557

56-
It also accepts a type function. For example:
58+
For example:
5759

5860
```typescript
5961
@Field({ description: `Book title`, deprecationReason: 'Not useful in v2 schema' })
@@ -71,7 +73,7 @@ posts: Post[];
7173

7274
> info **Hint** With `[ ]`, we can determine the depth of the array. For example, using `[[Int]]` would represent an integer matrix.
7375
74-
To declare that the array's items (not the array itself) are nullable, set the `nullable` property to `'items'` as shown below:
76+
To declare that an array's items (not the array itself) are nullable, set the `nullable` property to `'items'` as shown below:
7577

7678
```typescript
7779
@Field(type => [Post], { nullable: 'items' })
@@ -137,12 +139,14 @@ export class AuthorResolver {
137139
138140
> 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.
139141
140-
In the example above, we created the `AuthorResolver` which defines one query and one field resolver function. To create a resolver, we annotate the class with the `@Resolver()` decorator. The argument passed in to the `@Resolver()` decorator is optional, but in our case, since we have also defined a **field resolver** (for the `posts` property of the `Author` object type), it becomes required; in that case, the value is used to indicate which class is the parent (type) for any field resolver defined within this class.
142+
In the example above, we created the `AuthorResolver` which defines one query and one field resolver function. To create a resolver, we create a class with resolver functions as methods, and we annotate the class with the `@Resolver()` decorator.
141143

142-
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 and the appropriate entries in the resolver map. This allows you to create queries close to the models and services that they use, and to keep them well organized in modules.
144+
The argument passed to the `@Resolver()` decorator is optional. However, in our case, since we have also defined a **field resolver** (for the `posts` property of the `Author` object type), it becomes required; in that case, the value is used to indicate which class is the parent type (i.e., the corresponding `ObjectType` class name) for any field resolver defined within this class.
143145

144146
In this example, we defined a query handler to get the author object based on the `id` sent in the request. To specify that the method is a query handler, use the `@Query()` decorator.
145147

148+
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.
149+
146150
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:
147151

148152
```typescript
@@ -160,7 +164,7 @@ type Query {
160164
}
161165
```
162166

163-
Conventionally, we prefer to decouple these names; for example, using a name like `getAuthor()` for our query handler method, but still using `author` for our query type name. The same applies to our field resolvers. We can easily do this by passing the mapping names as arguments of the `@Query()` and `@ResolveField()` decorators, as shown below:
167+
Conventionally, we prefer to decouple these names; for example, we prefer to use a name like `getAuthor()` for our query handler method, but still use `author` for our query type name. The same applies to our field resolvers. We can easily do this by passing the mapping names as arguments of the `@Query()` and `@ResolveField()` decorators, as shown below:
164168

165169
```typescript
166170
@Resolver(of => Author)
@@ -183,15 +187,15 @@ export class AuthorResolver {
183187
}
184188
```
185189

186-
The `AuthorResolver` resolver above will result in generating the following part of the GraphQL schema in SDL:
190+
The `getAuthor` handler method above will result in generating the following part of the GraphQL schema in SDL:
187191

188192
```graphql
189193
type Query {
190194
author(id: Int!): Author
191195
}
192196
```
193197

194-
The options object (where we pass `{{ '{' }}name: 'author'{{ '}' }}` above) accepted by the `@Query()` decorator accepts a number of keys:
198+
The `@Query()` decorator's options object (where we pass `{{ '{' }}name: 'author'{{ '}' }}` above) accepts a number of keys:
195199

196200
- name: name of the query; a `string`
197201
- description: a description that will be used to generate GraphQL schema documentation (e.g. in GraphQL playground); a `string`
@@ -204,7 +208,7 @@ Usually you won't have to pass an object into the `@Args()` decorator as seen wi
204208
@Args('id') id: string
205209
```
206210

207-
However, in this case, the `number` type is used, and it presents a challenge. The `number` type doesn't give us enough information about the expected GraphQL representation (e.g., `Int` vs. `Float`). Thus we have to **explicitly** pass the type reference.
211+
However, in this case, the `number` type is used, and it presents a challenge. The `number` TypeScript type doesn't give us enough information about the expected GraphQL representation (e.g., `Int` vs. `Float`). Thus we have to **explicitly** pass the type reference.
208212

209213
Query handler methods can take multiple arguments. Let's imagine that we want to fetch an author based on its `firstName` and `lastName`. In this case, we can call `@Args` twice:
210214

0 commit comments

Comments
 (0)