Skip to content

Commit 82bf4bd

Browse files
committed
docs: finalize release notes for 9.0.0
1 parent 69b42c8 commit 82bf4bd

File tree

1 file changed

+152
-9
lines changed

1 file changed

+152
-9
lines changed

docs/releases/9.0.0.md

Lines changed: 152 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
<!-- TOC depthFrom:2 -->
44

55
- [What's new?](#whats-new)
6-
- [🛑 resolver creation (factory)](#🛑-resolver-creation-factory)
6+
- [A new way for resolver creation (via factory)](#a-new-way-for-resolver-creation-via-factory)
7+
- [An full example using TypeScript with mongoose, graphql-compose-mongoose, and a new DataLoader resolver.](#an-full-example-using-typescript-with-mongoose-graphql-compose-mongoose-and-a-new-dataloader-resolver)
8+
- [Expose `resolverFactory` for advanced cases of resolver creation](#expose-resolverfactory-for-advanced-cases-of-resolver-creation)
79
- [Mutations got `error: ErrorInterface` field in theirs payload for better error handling](#mutations-got-error-errorinterface-field-in-theirs-payload-for-better-error-handling)
810
- [Added a new `ValidationError`](#added-a-new-validationerror)
9-
- [Improvements](#improvements)
11+
- [Enhancements](#enhancements)
1012
- [Now `_id` field can be of any type (Int, String, Object)](#now-_id-field-can-be-of-any-type-int-string-object)
1113
- [Add nested fields support, new operators `regex`, `exists` for `filter._operators`](#add-nested-fields-support-new-operators-regex-exists-for-filter_operators)
1214
- [Better alias support for nested embedded fields](#better-alias-support-for-nested-embedded-fields)
@@ -27,13 +29,154 @@
2729

2830
## What's new?
2931

30-
### 🛑 resolver creation (factory)
32+
### A new way for resolver creation (via factory)
3133

32-
- Refactor resolver creation #263
33-
- Expose `mongooseResolvers` for manual creation of resolvers #274
34-
- feat: expose `resolverFactory` for manual resolver creation, eg. for cloned types: `resolverFactory.findMany(UserModel, ClonedUserTC, opts)` – it generates Resolver's types according to `ClonedUserTC` type and will use mongoose `UserModel` for making requests to DB
35-
- feat: added new function `composeMongoose` which generates TypeComposer without resolvers. Now Resolvers can be generated on-demand in such way `PostTC.mongooseResolvers.findMany()` (before was `PostTC.getResolver('findMany')`)
36-
- Improve Typescript definitions for resolvers
34+
Before 9.0.0 `graphql-compose-mongoose` generates type & resolvers together on `composeWithMongoose` call. This approach have the following disadvantages:
35+
- no static analysis for resolver names (are you sure that `findById` exists?)
36+
- under the hood generated around 15 resolvers and many graphql types for them (do you really use all of these resolvers?)
37+
- no static analysis for available args when you are crating relations
38+
- quite awkward mechanics of creating new resolvers, cloning, or wrapping them (what if you need to change type before resolvers creation? what if I need several copies of one resolver with a different set of args?)
39+
- no `go-to` support in IDE via ctrl+click for opening resolver definition.
40+
41+
To overcome all these problems was created a new `composeMongoose` method. And I strongly recommend to migrate your codebase from the old `composeWithMongoose` to a new one method for making your code more stable and faster:
42+
43+
```diff
44+
- import { composeWithMongoose } from 'graphql-compose-mongoose';
45+
+ import { composeMongoose } from 'graphql-compose-mongoose';
46+
47+
// generate GraphQL types & resolvers from mongoose model
48+
- const UserTC = composeWithMongoose(UserModel);
49+
+ const UserTC = composeMongoose(UserModel);
50+
51+
// getting generated resolver by name `findById`
52+
- const findByIdResolver = UserTC.getResolver('findById');
53+
+ const findByIdResolver = UserTC.mongooseResolvers.findById();
54+
```
55+
56+
Under the hood new `composeMongoose` method on its call:
57+
- will create just two types `ObjectTypeComposer` & `InputTypeComposer`
58+
- will not generate resolvers automatically, but instead of this, it adds `mongooseResolvers` property with a factory for resolver creation on demand.
59+
60+
It will provide the following advantages:
61+
- You may programmatically modify `TypeComposer` and only after that generate resolvers with their sub-types based on already customized fields in `TypeComposer`.
62+
- Safe memory and time on the bootstrap server phase, because it won't generate unused resolvers.
63+
- You may call one resolver generator several times with different configurations.
64+
- `mongooseResolvers` factory has improved typescript definitions. And you will get not only a list of available resolvers by names but also their customization options. Moreover, all generated Resolvers will know its `source: Model<IDoc>`.
65+
- According to its customization options for every resolver, you may control how your resolvers will be generated. Also, it unlocks the ability in future releases to add more options like `before` & `after` hooks, ACL, additional filters, and sorts params.
66+
67+
[Issue #263](https://github.com/graphql-compose/graphql-compose-mongoose/issues/263)
68+
69+
### An full example using TypeScript with mongoose, graphql-compose-mongoose, and a new DataLoader resolver.
70+
71+
An example of TypeScript usage with a lot of type checks and autosuggestions:
72+
73+
```ts
74+
import { SchemaComposer } from 'graphql-compose';
75+
import { composeMongoose } from 'graphql-compose-mongoose';
76+
import { mongoose } from 'mongoose';
77+
78+
// type for context which is provided by graphql-server
79+
interface TContext {
80+
req: Request;
81+
}
82+
83+
// creating a schema with TContext
84+
const schemaComposer = new SchemaComposer<TContext>();
85+
86+
// describe mongoose schema for User
87+
const UserSchema = new mongoose.Schema({
88+
name: { type: String, required: true },
89+
});
90+
91+
// define interface for your mongoose model IUser
92+
interface IUser extends mongoose.Document {
93+
name: string;
94+
}
95+
96+
// describe mongoose schema for Post
97+
const PostSchema = new mongoose.Schema({
98+
title: { type: String, required: true },
99+
authorId: { type: mongoose.Types.ObjectId },
100+
reviewerIds: { type: [mongoose.Types.ObjectId] },
101+
});
102+
103+
// define interface for your mongoose model IPost
104+
interface IPost extends mongoose.Document {
105+
title: string;
106+
authorId?: mongoose.Types.ObjectId;
107+
reviewerIds?: [mongoose.Types.ObjectId];
108+
}
109+
110+
// Create mongoose models with typescript definitions
111+
// Bored with describing fields two times for Schema and for Interface –
112+
// try typegoose: https://typegoose.github.io/typegoose/
113+
const UserModel = mongoose.model<IUser>('User', UserSchema);
114+
const PostModel = mongoose.model<IPost>('Post', PostSchema);
115+
116+
// create ObjectTypeComposers via the new method
117+
const UserTC = composeMongoose(UserModel);
118+
const PostTC = composeMongoose(PostModel);
119+
120+
// make relations between Post <--> Author
121+
// via adding a new field `author` and using DataLoader
122+
PostTC.addRelation('author', {
123+
resolver: UserTC.mongooseResolvers.dataLoader({ lean: true }),
124+
// ^^^ ^^^
125+
// autosuggestion for available resolvers and available options
126+
prepareArgs: {
127+
// here will be allowed only `_id` key, cause only one this arg is available in `dataLoader` resolver
128+
_id: (s) => s.authorId,
129+
// ^^^ source is typed to IPost interface
130+
},
131+
projection: { authorId: true },
132+
});
133+
134+
// Describe another relation via `dataLoaderMany`
135+
PostTC.addRelation('reviewers', {
136+
resolver: UserTC.mongooseResolvers.dataLoaderMany({ lean: true }),
137+
prepareArgs: {
138+
_ids: (s) => s.reviewerIds,
139+
},
140+
projection: { reviewerIds: true },
141+
});
142+
143+
// defining schema entrypoints for Query
144+
schemaComposer.Query.addFields({
145+
post: PostTC.mongooseResolvers.findById(),
146+
posts: PostTC.mongooseResolvers.findMany(),
147+
user: UserTC.mongooseResolvers.findById(),
148+
users: UserTC.mongooseResolvers.findMany({ sort: false }),
149+
});
150+
151+
// defining schema entrypoints for Mutation
152+
schemaComposer.Query.addFields({
153+
postCreate: PostTC.mongooseResolvers.createOne(),
154+
userCreate: UserTC.mongooseResolvers.createOne(),
155+
});
156+
157+
// generating GraphQL schema instance
158+
const schema = schemaComposer.buildSchema();
159+
```
160+
161+
### Expose `resolverFactory` for advanced cases of resolver creation
162+
163+
`graphql-compose-mongoose` exposes `resolverFactory` variable which contains all available resolver generators, eg. `resolverFactory.createOne(someMongooseModel, someTC, customizationOpts)`. This resolver generation way unlocks the following scenarios:
164+
- you have several mongoose models with different databases connection and one TypeComposer, so you can reuse one GraphQL type for using it with different MongoDBs.
165+
- you have one mongoose model and want to use different GraphQL types (for admins with a full set of fields, and for clients with a reduced set of fields).
166+
167+
The following example demonstrates how to use the second scenario with `ClonedPostTC` type for the reduced set of fields and existing mongoose `PostModel` for making requests to DB:
168+
169+
```ts
170+
import { resolverFactory } from 'graphql-compose-mongoose';
171+
import { PostModel, PostTC } from './the-example-above';
172+
173+
const ClonedPostTC = PostTC.clone('ReducedPost');
174+
ClonedPostTC.getInputTypeComposer().removeField('authorId');
175+
176+
const createPostWithoutAuthor = resolverFactory.createOne(PostModel, ClonedPostTC, { suffix: 'CustomCreate' });
177+
```
178+
179+
[Issue #274](https://github.com/graphql-compose/graphql-compose-mongoose/issues/274)
37180

38181
### Mutations got `error: ErrorInterface` field in theirs payload for better error handling
39182

@@ -228,7 +371,7 @@ You will receive the following response:
228371

229372
[Issue #248](https://github.com/graphql-compose/graphql-compose-mongoose/issues/248)
230373

231-
## Improvements
374+
## Enhancements
232375

233376
### Now `_id` field can be of any type (Int, String, Object)
234377

0 commit comments

Comments
 (0)