type-graphql-dataloader
Version:
A utility to use DataLoader with TypeGraphQL without fuss
117 lines (90 loc) • 3.52 kB
Markdown
# TypeGraphQL-DataLoader
TypeGraphQL-DataLoader is an utility to use DataLoader with TypeGraphQL without fuss.
## Install
```
npm install type-graphql-dataloader
```
The latest build is tested with the following packages:
- type-graphql 1.1.1
- apollo-server-express 3.4.0
- (optional) typeorm 0.2.38
## Getting Started
Apollo Server is the first-class supported server. If your application uses Apollo Server, pass `ApolloServerLoaderPlugin()` as a plugin when instantiating the server. This plugin is for set-up and clean-up against each request.
```ts
import { ApolloServerLoaderPlugin } from "type-graphql-dataloader";
import { getConnection } from "typeorm";
...
const apollo = new ApolloServer({
schema,
plugins: [
ApolloServerLoaderPlugin({
typeormGetConnection: getConnection, // for use with TypeORM
}),
],
});
...
```
### With TypeORM
TypeORM is the first-class supported ORM. If your application uses TypeORM with TypeGraphQL, adding ` ` decorator to relation properties will solve N + 1 problem. When the fields are accessed by graphQL, batch loading will be performed using DataLoader under the hood.
```ts
import { ObjectType, Field, ID } from "type-graphql";
import { TypeormLoader } from "type-graphql-dataloader";
import { Entity, PrimaryGeneratedColumn, ManyToOne, RelationId } from "typeorm";
import { User } from "./User";
export class Photo {
id: number;
user: User;
}
```
```ts
import { ObjectType, Field, ID } from "type-graphql";
import { TypeormLoader } from "type-graphql-dataloader";
import { Entity, PrimaryGeneratedColumn, OneToMany, RelationId } from "typeorm";
import { Photo } from "./Photo";
export class User {
id: number;
photos: Photo[];
}
```
` ` does not need arguments since `v0.4.0`. In order to pass foeign key explicitly, arguments are still supported. Take a look at previous [README](https://github.com/slaypni/type-graphql-dataloader/blob/v0.3.7/README.md#with-typeorm) for details.
### With Custom DataLoader
It is possible to assign custom DataLoader to a field by adding ` ` decorator to the corresponding method with ` `. ` ` takes a batch load function which is passed to the DataLoader constructor. The decorated method should return a function which takes a DataLoader instance and returns Promise of loaded value(s).
```ts
import DataLoader from "dataloader";
import { groupBy } from "lodash";
import { Resolver, Query, FieldResolver, Root } from "type-graphql";
import { Loader } from "type-graphql-dataloader";
import { getRepository, In } from "typeorm";
import { Photo } from "./Photo";
import { User } from "./User";
export default class UserResolver {
...
<number, Photo[]>(async (ids, { context }) => { // batchLoadFn
const photos = await getRepository(Photo).find({
where: { user: { id: In([...ids]) } },
});
const photosById = groupBy(photos, "userId");
return ids.map((id) => photosById[id] ?? []);
})
photos( root: User) {
return (dataloader: DataLoader<number, Photo[]>) =>
dataloader.load(root.id);
}
}
```