Skip to content

Commit

Permalink
WIP: release notes for 9.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
nodkz committed Sep 23, 2020
1 parent 43259ac commit 2f18e93
Show file tree
Hide file tree
Showing 4 changed files with 248 additions and 5 deletions.
12 changes: 12 additions & 0 deletions .github/FUNDING.yml
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']
3 changes: 2 additions & 1 deletion .markdownlint.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
"ol-prefix": false,
"first-line-h1": false,
"first-heading-h1": false,
"no-bare-urls": false
"no-bare-urls": false,
"blanks-around-lists": false
}
9 changes: 5 additions & 4 deletions .vscode/settings.json
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
}
},
}
229 changes: 229 additions & 0 deletions docs/releases/9.0.0.md
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

0 comments on commit 2f18e93

Please sign in to comment.