-
Notifications
You must be signed in to change notification settings - Fork 3
/
DataSourceLoaderPager.ts
83 lines (74 loc) · 3.55 KB
/
DataSourceLoaderPager.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import type { ArgsForward, ArgsBackward, Connection } from "./CursorPagerSpec";
import { DataSourceCursorPager, dataSourcePager, DataSourcePagerConfig } from "./DataSourcePager";
import Dataloader from "dataloader";
export type DataLoaderConfig<ArgsForwardType extends ArgsForward, ArgsBackwardType extends ArgsBackward, NodeType = any> = {
forward?: Dataloader.Options<ArgsForwardType, Connection<NodeType>, string>
backward?: Dataloader.Options<ArgsBackwardType, Connection<NodeType>, string>
count?: Dataloader.Options<ArgsForwardType | ArgsBackwardType, number, string>
};
export type DataSourceLoaderPagerConfig<
NodeType, IdType, ArgsForwardType extends ArgsForward, ArgsBackwardType extends ArgsBackward
> = DataSourcePagerConfig<NodeType, IdType, ArgsForwardType, ArgsBackwardType> & {
dataloader?: DataLoaderConfig<ArgsForwardType, ArgsBackwardType>
}
/**
* Datasource pager wrapped by data loader. Shorthand for `dataloaderPagerWrapper(dataSourcePager(config))`
* @param config pager config & dataloader config
* @returns pager wrapped by dataloader
* @see dataloaderPagerWrapper
*/
export function dataSourceLoaderPager<NodeType,
IdType = string | number | Date,
ArgsForwardType extends ArgsForward = ArgsForward,
ArgsBackwardType extends ArgsBackward = ArgsBackward>
(config?: DataSourceLoaderPagerConfig<NodeType, IdType, ArgsForwardType, ArgsBackwardType>): DataSourceCursorPager<NodeType, IdType, ArgsForwardType, ArgsBackwardType> {
const pager = dataSourcePager<NodeType, IdType, ArgsForwardType, ArgsBackwardType>(config);
const wrapper = dataloaderPagerWrapper(pager, config?.dataloader);
return wrapper;
}
/**
* Pager wrapper by dataloader. Beware of memoization!. Cache key is computed as strintify of args object
* @param pager original pager
* @param config dataloader configuration
* @returns pager with wrapped forwardResolver, backwardResolver, totalCount functions
*/
export function dataloaderPagerWrapper<NodeType,
IdType = string | number | Date,
ArgsForwardType extends ArgsForward = ArgsForward,
ArgsBackwardType extends ArgsBackward = ArgsBackward>(
pager: DataSourceCursorPager<NodeType, IdType, ArgsForwardType, ArgsBackwardType>,
config?: DataLoaderConfig<ArgsForwardType, ArgsBackwardType>
): DataSourceCursorPager<NodeType, IdType, ArgsForwardType, ArgsBackwardType> {
const forwardLoader = new Dataloader<ArgsForwardType, Connection<NodeType>, string>(async (args) => {
return Promise.all(args.map(arg => pager.forwardResolver(arg)));
}, {
...config?.forward,
cacheKeyFn: (key) => JSON.stringify(key)
});
const backwardLoader = new Dataloader<ArgsBackwardType, Connection<NodeType>, string>(async (args) => {
return Promise.all(args.map(arg => pager.backwardResolver(arg)));
}, {
...config?.backward,
cacheKeyFn: (key) => JSON.stringify(key)
});
const countLoader = new Dataloader<ArgsForwardType | ArgsBackwardType, number, string>(async (args) => {
return Promise.all(args.map(arg => pager.totalCount(arg)));
}, {
...config?.count,
cacheKeyFn: (key) => {
return JSON.stringify({
...key,
after: undefined,
before: undefined,
first: undefined,
last: undefined,
})
}
});
return {
...pager,
forwardResolver: (arg) => forwardLoader.load(arg),
backwardResolver: (arg) => backwardLoader.load(arg),
totalCount: (arg) => countLoader.load(arg),
};
}