Skip to content

Commit a2f4b96

Browse files
authored
Merge pull request #9 from 0b10/major-v2.0.0
v2.0.0 - update dataloader to v2.0.0
2 parents eefb297 + fb1d8cb commit a2f4b96

File tree

4 files changed

+71
-62
lines changed

4 files changed

+71
-62
lines changed

README.md

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,29 @@
11
# NestJS Dataloader
2+
23
NestJS dataloader simplifies adding [graphql/dataloader](https://github.com/graphql/dataloader) to your NestJS project. DataLoader aims to solve the common N+1 loading problem.
34

45
## Installation
56

67
Install with yarn
7-
``` bash
8+
9+
```bash
810
yarn add nestjs-dataloader
911
```
1012

1113
Install with npm
12-
``` bash
14+
15+
```bash
1316
npm install --save nestjs-dataloader
14-
```
17+
```
1518

1619
## Usage
20+
1721
### NestDataLoader Creation
18-
We start by implementing the ```NestDataLoader``` interface. This tells ```DataLoader``` how to load our objects.
1922

20-
``` typescript
21-
import * as DataLoader from 'dataloader';
23+
We start by implementing the `NestDataLoader` interface. This tells `DataLoader` how to load our objects.
24+
25+
```typescript
26+
import DataLoader from 'dataloader';
2227
import { Injectable } from '@nestjs/common';
2328
import { NestDataLoader } from 'nestjs-dataloader';
2429
...
@@ -27,18 +32,19 @@ import { NestDataLoader } from 'nestjs-dataloader';
2732
export class AccountLoader implements NestDataLoader<string, Account> {
2833
constructor(private readonly accountService: AccountService) { }
2934

30-
generateDataLoader(): DataLoader<string, Account> {
35+
generateDataLoader(): DataLoader<string, Account> {
3136
return new DataLoader<string, Account>(keys => this.accountService.findByIds(keys));
3237
}
3338
}
3439
```
3540

36-
The first generic of the interface is the type of ID the datastore uses. The second generic is the type of object that will be returned. In the above instance, we want ```DataLoader``` to return instances of the ```Account``` class.
41+
The first generic of the interface is the type of ID the datastore uses. The second generic is the type of object that will be returned. In the above instance, we want `DataLoader` to return instances of the `Account` class.
3742

3843
### Providing the NestDataLoader
44+
3945
For each NestDataLoader we create, we need to provide it to our module.
4046

41-
``` typescript
47+
```typescript
4248
import { Module } from '@nestjs/common';
4349
import { APP_INTERCEPTOR } from '@nestjs/core';
4450
import {DataLoaderInterceptor} from 'nestjs-dataloader'
@@ -59,9 +65,11 @@ export class ResolversModule { }
5965
```
6066

6167
### Using the NestDataLoader
68+
6269
Now that we have a dataloader and our module is aware of it, we need to pass it as a parameter to an endpoint in our graphQL resolver.
63-
``` typescript
64-
import * as DataLoader from 'dataloader';
70+
71+
```typescript
72+
import DataLoader from 'dataloader';
6573
import { Loader } from 'nestjs-dataloader';
6674
...
6775

@@ -76,6 +84,9 @@ export class AccountResolver {
7684
}
7785
}
7886
```
79-
The important thing to note is that the parameter of the ```@Loader``` decorator is the name of the ```NestDataLoader``` class we want to be injected to the method. The DataLoader library will handle bulk retrieval and caching of our requests. Note that the caching is stored on a per-request basis.
87+
88+
The important thing to note is that the parameter of the `@Loader` decorator is the name of the `NestDataLoader` class we want to be injected to the method. The DataLoader library will handle bulk retrieval and caching of our requests. Note that the caching is stored on a per-request basis.
89+
8090
## Contributing
91+
8192
Pull requests are always welcome. For major changes, please open an issue first to discuss what you would like to change.

index.ts

Lines changed: 42 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
1-
import * as DataLoader from 'dataloader';
2-
import { NestInterceptor, ExecutionContext, CallHandler, InternalServerErrorException, createParamDecorator } from '@nestjs/common';
3-
import { Injectable } from '@nestjs/common';
4-
import { ModuleRef, APP_INTERCEPTOR } from '@nestjs/core';
1+
import {
2+
CallHandler,
3+
createParamDecorator,
4+
ExecutionContext,
5+
Injectable,
6+
InternalServerErrorException,
7+
NestInterceptor,
8+
} from '@nestjs/common';
9+
import { APP_INTERCEPTOR, ModuleRef } from '@nestjs/core';
510
import { GqlExecutionContext } from '@nestjs/graphql';
11+
import DataLoader from 'dataloader';
612
import { Observable } from 'rxjs';
713

814
/**
915
* This interface will be used to generate the initial data loader.
1016
* The concrete implementation should be added as a provider to your module.
1117
*/
1218
export interface NestDataLoader<ID, Type> {
13-
/**
14-
* Should return a new instance of dataloader each time
15-
*/
16-
generateDataLoader(): DataLoader<ID, Type>;
19+
/**
20+
* Should return a new instance of dataloader each time
21+
*/
22+
generateDataLoader(): DataLoader<ID, Type>;
1723
}
1824

1925
/**
@@ -28,51 +34,43 @@ const NEST_LOADER_CONTEXT_KEY: string = 'NEST_LOADER_CONTEXT_KEY';
2834

2935
@Injectable()
3036
export class DataLoaderInterceptor implements NestInterceptor {
37+
constructor(private readonly moduleRef: ModuleRef) {}
3138

32-
constructor(
33-
private readonly moduleRef: ModuleRef,
34-
) { }
39+
/**
40+
* @inheritdoc
41+
*/
42+
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
43+
const graphqlExecutionContext = GqlExecutionContext.create(context);
44+
const ctx: any = graphqlExecutionContext.getContext();
3545

36-
/**
37-
* @inheritdoc
38-
*/
39-
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
40-
const graphqlExecutionContext = GqlExecutionContext.create(context);
41-
const ctx: any = graphqlExecutionContext.getContext();
42-
43-
if (ctx[NEST_LOADER_CONTEXT_KEY] === undefined) {
44-
45-
ctx[NEST_LOADER_CONTEXT_KEY] = (type: string): NestDataLoader<any, any> => {
46-
47-
if (ctx[type] === undefined) {
48-
try {
49-
ctx[type] = this.moduleRef
50-
.get<NestDataLoader<any, any>>(type, { strict: false })
51-
.generateDataLoader();
52-
} catch (e) {
53-
throw new InternalServerErrorException(`The loader ${type} is not provided`);
54-
}
55-
}
56-
57-
return ctx[type];
58-
};
46+
if (ctx[NEST_LOADER_CONTEXT_KEY] === undefined) {
47+
ctx[NEST_LOADER_CONTEXT_KEY] = (type: string): NestDataLoader<any, any> => {
48+
if (ctx[type] === undefined) {
49+
try {
50+
ctx[type] = this.moduleRef
51+
.get<NestDataLoader<any, any>>(type, { strict: false })
52+
.generateDataLoader();
53+
} catch (e) {
54+
throw new InternalServerErrorException(`The loader ${type} is not provided`);
55+
}
5956
}
60-
return next.handle();
57+
58+
return ctx[type];
59+
};
6160
}
61+
return next.handle();
62+
}
6263
}
6364

6465
/**
6566
* The decorator to be used within your graphql method.
6667
*/
67-
export const Loader = createParamDecorator(
68-
(data: string, [_, __, ctx]) => {
69-
70-
if (ctx[NEST_LOADER_CONTEXT_KEY] === undefined) {
71-
throw new InternalServerErrorException(`
68+
export const Loader = createParamDecorator((data: string, [_, __, ctx]) => {
69+
if (ctx[NEST_LOADER_CONTEXT_KEY] === undefined) {
70+
throw new InternalServerErrorException(`
7271
You should provide interceptor ${DataLoaderInterceptor.name} globaly with ${APP_INTERCEPTOR}
7372
`);
74-
}
73+
}
7574

76-
return ctx[NEST_LOADER_CONTEXT_KEY](data);
77-
},
78-
);
75+
return ctx[NEST_LOADER_CONTEXT_KEY](data);
76+
});

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "nestjs-dataloader",
3-
"version": "1.0.13",
3+
"version": "2.0.0",
44
"description": "A NestJS decorator for dataloader",
55
"author": "Kris Lefeber <[email protected]>",
66
"license": "MIT",
@@ -14,7 +14,7 @@
1414
"@nestjs/common": "^6.4.0",
1515
"@nestjs/core": "^6.4.0",
1616
"@nestjs/graphql": "^6.5.3",
17-
"dataloader": "^1.4.0",
17+
"dataloader": "^2.0.0",
1818
"rxjs": "^6.5.4"
1919
},
2020
"peerDependencies": {

yarn.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -802,10 +802,10 @@ d@1, d@^1.0.1:
802802
es5-ext "^0.10.50"
803803
type "^1.0.1"
804804

805-
dataloader@^1.4.0:
806-
version "1.4.0"
807-
resolved "https://registry.yarnpkg.com/dataloader/-/dataloader-1.4.0.tgz#bca11d867f5d3f1b9ed9f737bd15970c65dff5c8"
808-
integrity sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==
805+
dataloader@^2.0.0:
806+
version "2.0.0"
807+
resolved "https://registry.yarnpkg.com/dataloader/-/dataloader-2.0.0.tgz#41eaf123db115987e21ca93c005cd7753c55fe6f"
808+
integrity sha512-YzhyDAwA4TaQIhM5go+vCLmU0UikghC/t9DTQYZR2M/UvZ1MdOhPezSDZcjj9uqQJOMqjLcpWtyW2iNINdlatQ==
809809

810810
811811
version "2.6.9"

0 commit comments

Comments
 (0)