forked from graphql-compose/graphql-compose-mongoose
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
248 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# These are supported funding model platforms | ||
|
||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] | ||
patreon: # Replace with a single Patreon username | ||
open_collective: graphql-compose | ||
ko_fi: # Replace with a single Ko-fi username | ||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel | ||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry | ||
liberapay: # Replace with a single Liberapay username | ||
issuehunt: # Replace with a single IssueHunt username | ||
otechie: # Replace with a single Otechie username | ||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,10 @@ | ||
{ | ||
"eslint.validate": ["javascript"], | ||
"javascript.validate.enable": false, | ||
"javascript.autoClosingTags": false, | ||
"eslint.autoFixOnSave": true, | ||
"typescript.tsdk": "node_modules/typescript/lib", | ||
"editor.formatOnSave": false, | ||
"javascript.format.enable": false, | ||
"typescript.format.enable": false, | ||
"editor.codeActionsOnSave": { | ||
"source.fixAll.eslint": true | ||
} | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,229 @@ | ||
# Release notes graphql-compose-mongoose v9.0.0 | ||
|
||
<!-- TOC depthFrom:2 --> | ||
|
||
- [What's new?](#whats-new) | ||
- [🛑 resolver creation (factory)](#🛑-resolver-creation-factory) | ||
- [🛑 error handling (payload.error, mongoose validation)](#🛑-error-handling-payloaderror-mongoose-validation) | ||
- [Improvements](#improvements) | ||
- [Now `_id` field can be of any type (Int, String, Object)](#now-_id-field-can-be-of-any-type-int-string-object) | ||
- [🛑 recursive `filter._operators`](#🛑-recursive-filter_operators) | ||
- [🛑 better alias & projection support for nested embedded documents](#🛑-better-alias--projection-support-for-nested-embedded-documents) | ||
- [🛑 typescript improvements for resolvers](#🛑-typescript-improvements-for-resolvers) | ||
- [Performance improvements](#performance-improvements) | ||
- [Added new `dataLoader` & `dataLoaderMany` resolvers](#added-new-dataloader--dataloadermany-resolvers) | ||
- [Add `lean: boolean` option to query resolvers](#add-lean-boolean-option-to-query-resolvers) | ||
- [Breaking changes](#breaking-changes) | ||
- [In resolver `updateById` was changed its input args](#in-resolver-updatebyid-was-changed-its-input-args) | ||
- [Some generated types were renamed](#some-generated-types-were-renamed) | ||
- [Misc](#misc) | ||
- [Thanks](#thanks) | ||
- [Thanks to contributors](#thanks-to-contributors) | ||
- [Thanks to sponsors](#thanks-to-sponsors) | ||
|
||
<!-- /TOC --> | ||
|
||
## What's new? | ||
|
||
### 🛑 resolver creation (factory) | ||
|
||
- Refactor resolver creation #263 | ||
- Expose `mongooseResolvers` for manual creation of resolvers #274 | ||
- 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 | ||
- 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')`) | ||
- Improve Typescript definitions for resolvers | ||
|
||
### 🛑 error handling (payload.error, mongoose validation) | ||
|
||
- Add `error` field & handler for mutations' payload #248 | ||
- Resolvers createOne createMany now returns validation errors | ||
|
||
## Improvements | ||
|
||
### Now `_id` field can be of any type (Int, String, Object) | ||
|
||
Before v9.0.0 was supported only `MongoID` type for `_id` field. Now it can be of any type – Int, String, Object. For using this feature you need to add `_id` field to mongoose schema with desired type and graphql-compose-mongoose will do the rest: | ||
|
||
```ts | ||
const BookSchema = new mongoose.Schema({ | ||
_id: { type: Number }, | ||
title: { type: String }, | ||
}); | ||
|
||
interface IBook extends Document { | ||
_id: number; | ||
title?: string; | ||
} | ||
|
||
const BookModel = mongoose.model<IBook>('Book', BookSchema); | ||
const BookTC = composeMongoose(BookModel); | ||
``` | ||
|
||
Notes: | ||
|
||
- If you choose type `Number` for `_id` field then `graphql-compose-mongoose` will cast it to `Int` GraphQL type. For other fields `Number` is casted to `Float` by default. Anyway you able change type manually – `BookTC.extendField('_id', { type: 'Float!' })`. | ||
- Be careful: Mongoose will refuse to save a document that doesn't have an `_id`. So you're responsible for setting `_id` if you define your own `_id` path. For automatic numeric id creation you can use the following plugins [mongoose-plugin-autoinc](https://www.npmjs.com/package/mongoose-plugin-autoinc) or [@typegoose/auto-increment](https://www.npmjs.com/package/@typegoose/auto-increment). | ||
|
||
[Issue #141](https://github.com/graphql-compose/graphql-compose-mongoose/issues/141) | ||
|
||
### 🛑 recursive `filter._operators` | ||
|
||
- Adds support for recursive `filter._operators` (rename its type names ) #250 | ||
|
||
### 🛑 better alias & projection support for nested embedded documents | ||
|
||
- Nested projections for embedded documents #273 | ||
- feat: nested aliases are now supported for `filter`, `projection` & `lean` | ||
|
||
### 🛑 typescript improvements for resolvers | ||
|
||
- source is now typed, and first level of available args | ||
|
||
## Performance improvements | ||
|
||
### Added new `dataLoader` & `dataLoaderMany` resolvers | ||
|
||
These resolvers are helpful for relations construction between Entities for avoiding the N+1 Problem via [DataLoader](https://github.com/graphql/dataloader). This problem occurs when a client requests an array of records with some relation data: | ||
- GraphQL call first resolve method with 1 query for getting a list of records | ||
- and for every record will call nested resolve methods which make separate DB requests | ||
|
||
As you can expect, doing N+1 queries will flood your database with queries, which is something we can and should avoid. So `dataLoader`, `dataLoaderMany` resolvers make one batch request for getting all related records by id. | ||
|
||
```ts | ||
import { schemaComposer } from 'graphql-compose'; | ||
import { composeMongoose } from 'graphql-compose-mongoose'; | ||
import { mongoose, Document } from 'mongoose'; | ||
|
||
mongoose.set('debug', true); // <-- show mongoose queries in console | ||
|
||
const UserSchema = new mongoose.Schema({ | ||
name: { type: String, required: true }, | ||
}); | ||
const PostSchema = new mongoose.Schema({ | ||
title: { type: String, required: true }, | ||
authorId: { type: mongoose.Types.ObjectId }, | ||
reviewerIds: { type: [mongoose.Types.ObjectId] }, | ||
}); | ||
|
||
interface IUser extends Document { | ||
name: string; | ||
} | ||
|
||
interface IPost extends Document { | ||
title: string; | ||
authorId?: mongoose.Types.ObjectId; | ||
reviewerIds?: [mongoose.Types.ObjectId]; | ||
} | ||
|
||
const UserModel = mongoose.model<IUser>('User', UserSchema); | ||
const PostModel = mongoose.model<IPost>('Post', PostSchema); | ||
|
||
const UserTC = composeMongoose(UserModel); | ||
const PostTC = composeMongoose(PostModel); | ||
|
||
PostTC.addRelation('author', { | ||
// resolver: () => UserTC.mongooseResolvers.findById({ lean: true }), | ||
resolver: () => UserTC.mongooseResolvers.dataLoader({ lean: true }), | ||
prepareArgs: { | ||
_id: (s) => s.authorId, | ||
}, | ||
projection: { authorId: true }, | ||
}); | ||
|
||
PostTC.addRelation('reviewers', { | ||
// resolver: () => UserTC.mongooseResolvers.findByIds({ lean: true }), | ||
resolver: () => UserTC.mongooseResolvers.dataLoaderMany({ lean: true }), | ||
prepareArgs: { | ||
_ids: (s) => s.reviewerIds, | ||
}, | ||
projection: { reviewerIds: true }, | ||
}); | ||
|
||
schemaComposer.Query.addFields({ | ||
posts: PostTC.mongooseResolvers.findMany(), | ||
}); | ||
|
||
// console.log(schemaComposer.toSDL()); | ||
export const schema = schemaComposer.buildSchema(); | ||
``` | ||
|
||
Test suite for this example can be found [here](https://github.com/graphql-compose/graphql-compose-mongoose/blob/master/src/__tests__/github_issues/260-test.ts). | ||
|
||
### Add `lean: boolean` option to query resolvers | ||
|
||
Resolvers with `lean: true` is significantly faster than without it (anywhere from 3 - 10 times faster). If you need just `raw` data from DB then use this option. By default queries return fully instantiated Mongoose documents for supporting mongoose's `virtuals` fields, plugins and model methods (but it consume much more CPU & RAM). | ||
|
||
`lean` option available in the following resolvers `findById`, `findByIds`, `findMany`, `findOne`, `dataLoader`, `dataLoaderMany`. | ||
|
||
BTW mongoose `aliases` are supported with `lean: true` option. graphql-compose-mongoose takes care about their proper conversion in filters, projection and output results: | ||
|
||
```ts | ||
// With aliases in MongoDB you will have such records | ||
// { _id: '...', n: 'John', a: 26 } | ||
const AuthorSchema = new mongoose.Schema({ | ||
name: { type: String, alias: 'n' }, | ||
score: { type: Number, alias: 's' }, | ||
}); | ||
const AuthorModel = mongoose.model<IAuthor>('Author', AuthorSchema); | ||
|
||
// Will be generate graphql type with full field names | ||
// type Author { name: String, score: Float } | ||
const AuthorTC = composeMongoose(AuthorModel, { schemaComposer }); | ||
|
||
// Resolver will send queries something like that: | ||
// db.author.find({ n: 'John' }) | ||
// And convert shortened raw records to full form | ||
// { _id: '...', n: 'John', s: 26 } | ||
const userFindManyResolver = AuthorTC.mongooseResolvers.findMany({ lean: true }); | ||
``` | ||
|
||
- feat add `lean: true` option #259, #266 [commit](https://github.com/graphql-compose/graphql-compose-mongoose/commit/321dded4e2b346e5ab3d549a6bc5b31458478fd1) | ||
|
||
## Breaking changes | ||
|
||
### In resolver `updateById` was changed its input args | ||
|
||
From `UpdateByIdRecord` input type was extracted `_id` field on top level. | ||
|
||
```diff | ||
- updateById(record: UpdateByIdRecord!) | ||
+ updateById(_id: MongoID!, record: UpdateByIdRecord!) | ||
``` | ||
|
||
[Issue #257](https://github.com/graphql-compose/graphql-compose-mongoose/issues/257) | ||
|
||
### Some generated types were renamed | ||
|
||
- type for `filter._operators` field. Was `OperatorsXXXFilterInput` became `XXXFilterOperatorsInput`. It helps to keep all generated types with the same prefix for `XXX` entity. | ||
- in resolver `count` was changed `filter` type name from `Filter` to `FilterCount`. All rest resolvers already had `FilterFindMany`, `FilterFinOne`, etc. names, and only `count` resolver does not follow this pattern. | ||
|
||
## Misc | ||
|
||
- Refactor `pagination` & `connection` resolvers (now they are as dependencies) [#272](https://github.com/graphql-compose/graphql-compose-mongoose/issues/272) | ||
- Allow to provide `suffixes` for resolvers configs [#268](https://github.com/graphql-compose/graphql-compose-mongoose/issues/268) | ||
- Remove `getRecordIdFn()` [#262](https://github.com/graphql-compose/graphql-compose-mongoose/issues/262) | ||
|
||
## Thanks | ||
|
||
### Thanks to contributors | ||
|
||
It will not be possible to provide such great improvements in v9.0.0 without the following amazing peoples: | ||
|
||
- [Robert Lowe](@RobertLowe) – new improved error payload for Mutations and better validation Errors on document creating/updating. | ||
- [Sean Campbell](natac13) – nested projection for reducing the amount of transmitted data from DB. | ||
- [Morgan Touverey Quilling](@toverux) – non-nullability for fields with default values, help in lean resolvers. | ||
|
||
Thank you very much for your help 🙏 | ||
|
||
### Thanks to sponsors | ||
|
||
Special thanks to our sponsors which joined recently: | ||
|
||
- **Bruce agency ($250)** – Investing in JAMstack, headless and touchless experiences since 2007, with over 250+ projects built. <https://bruce.agency/> | ||
- **Robert Lowe ($200)** – freelancer with great experience in Realtime web, mobile and desktop apps <http://robertlowe.ca> | ||
|
||
And thanks a lot to regular backers – [ScrapeHero](https://www.scrapehero.com/marketplace/) $5,[Woorke](https://woorke.com) $2, [420 Coupon Codes](https://420couponcodes.com/) $2,[ScrapingBee](https://www.scrapingbee.com/) $2, [Adapt.js](https://adaptjs.org/) $2. | ||
|
||
Your donations inspire me to improve `graphql-compose` packages. And allow to spend more time on it. Thank you very much for your support! | ||
|
||
You may consider to join with sponsoring `graphql-compose` and all its plugins via OpenCollective – https://opencollective.com/graphql-compose |