UNPKG

4.26 kBJavaScriptView Raw
1import { GraphQLList, getNamedType } from 'graphql';
2import DataLoader from 'dataloader';
3import { delegateToSchema } from '@graphql-tools/delegate';
4import { relocatedError } from '@graphql-tools/utils';
5
6const cache1 = new WeakMap();
7function 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}
39const cacheKeyFn = (key) => (typeof key === 'object' ? JSON.stringify(key) : key);
40function 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 // Prevents the keys to be passed with the same structure
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
77function 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
89function 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}
99function createBatchDelegateFnImpl(options) {
100 return batchDelegateOptions => {
101 const loader = getLoader({
102 ...options,
103 ...batchDelegateOptions,
104 });
105 return loader.load(batchDelegateOptions.key);
106 };
107}
108
109export { batchDelegateToSchema, createBatchDelegateFn };