1 | import { GraphQLList, getNamedType } from 'graphql';
|
2 | import DataLoader from 'dataloader';
|
3 | import { delegateToSchema } from '@graphql-tools/delegate';
|
4 | import { relocatedError } from '@graphql-tools/utils';
|
5 |
|
6 | const cache1 = new WeakMap();
|
7 | function createBatchFn(options) {
|
8 | var _a, _b;
|
9 | const argsFromKeys = (_a = options.argsFromKeys) !== null && _a !== void 0 ? _a : ((keys) => ({ ids: keys }));
|
10 | const fieldName = (_b = options.fieldName) !== null && _b !== void 0 ? _b : options.info.fieldName;
|
11 | const { valuesFromResults, lazyOptionsFn } = options;
|
12 | return async (keys) => {
|
13 | const results = await delegateToSchema({
|
14 | returnType: new GraphQLList(getNamedType(options.info.returnType)),
|
15 | onLocatedError: originalError => {
|
16 | if (originalError.path == null) {
|
17 | return originalError;
|
18 | }
|
19 | const [pathFieldName, pathNumber] = originalError.path;
|
20 | if (pathFieldName !== fieldName) {
|
21 | return originalError;
|
22 | }
|
23 | const pathNumberType = typeof pathNumber;
|
24 | if (pathNumberType !== 'number') {
|
25 | return originalError;
|
26 | }
|
27 | return relocatedError(originalError, originalError.path.slice(0, 0).concat(originalError.path.slice(2)));
|
28 | },
|
29 | args: argsFromKeys(keys),
|
30 | ...(lazyOptionsFn == null ? options : lazyOptionsFn(options)),
|
31 | });
|
32 | if (results instanceof Error) {
|
33 | return keys.map(() => results);
|
34 | }
|
35 | const values = valuesFromResults == null ? results : valuesFromResults(results, keys);
|
36 | return Array.isArray(values) ? values : keys.map(() => values);
|
37 | };
|
38 | }
|
39 | const cacheKeyFn = (key) => (typeof key === 'object' ? JSON.stringify(key) : key);
|
40 | function getLoader(options) {
|
41 | var _a;
|
42 | const fieldName = (_a = options.fieldName) !== null && _a !== void 0 ? _a : options.info.fieldName;
|
43 | let cache2 = cache1.get(options.info.fieldNodes);
|
44 |
|
45 | const dataLoaderOptions = {
|
46 | cacheKeyFn,
|
47 | ...options.dataLoaderOptions,
|
48 | };
|
49 | if (cache2 === undefined) {
|
50 | cache2 = new WeakMap();
|
51 | cache1.set(options.info.fieldNodes, cache2);
|
52 | const loaders = Object.create(null);
|
53 | cache2.set(options.schema, loaders);
|
54 | const batchFn = createBatchFn(options);
|
55 | const loader = new DataLoader(keys => batchFn(keys), dataLoaderOptions);
|
56 | loaders[fieldName] = loader;
|
57 | return loader;
|
58 | }
|
59 | let loaders = cache2.get(options.schema);
|
60 | if (loaders === undefined) {
|
61 | loaders = Object.create(null);
|
62 | cache2.set(options.schema, loaders);
|
63 | const batchFn = createBatchFn(options);
|
64 | const loader = new DataLoader(keys => batchFn(keys), dataLoaderOptions);
|
65 | loaders[fieldName] = loader;
|
66 | return loader;
|
67 | }
|
68 | let loader = loaders[fieldName];
|
69 | if (loader === undefined) {
|
70 | const batchFn = createBatchFn(options);
|
71 | loader = new DataLoader(keys => batchFn(keys), dataLoaderOptions);
|
72 | loaders[fieldName] = loader;
|
73 | }
|
74 | return loader;
|
75 | }
|
76 |
|
77 | function batchDelegateToSchema(options) {
|
78 | const key = options.key;
|
79 | if (key == null) {
|
80 | return null;
|
81 | }
|
82 | else if (Array.isArray(key) && !key.length) {
|
83 | return [];
|
84 | }
|
85 | const loader = getLoader(options);
|
86 | return Array.isArray(key) ? loader.loadMany(key) : loader.load(key);
|
87 | }
|
88 |
|
89 | function createBatchDelegateFn(optionsOrArgsFromKeys, lazyOptionsFn, dataLoaderOptions, valuesFromResults) {
|
90 | return typeof optionsOrArgsFromKeys === 'function'
|
91 | ? createBatchDelegateFnImpl({
|
92 | argsFromKeys: optionsOrArgsFromKeys,
|
93 | lazyOptionsFn,
|
94 | dataLoaderOptions,
|
95 | valuesFromResults,
|
96 | })
|
97 | : createBatchDelegateFnImpl(optionsOrArgsFromKeys);
|
98 | }
|
99 | function createBatchDelegateFnImpl(options) {
|
100 | return batchDelegateOptions => {
|
101 | const loader = getLoader({
|
102 | ...options,
|
103 | ...batchDelegateOptions,
|
104 | });
|
105 | return loader.load(batchDelegateOptions.key);
|
106 | };
|
107 | }
|
108 |
|
109 | export { batchDelegateToSchema, createBatchDelegateFn };
|