@graphql-tools/batch-delegate
Version:
A set of utils for faster development of GraphQL tools
138 lines (130 loc) • 4.66 kB
JavaScript
var delegate = require('@graphql-tools/delegate');
var utils = require('@graphql-tools/utils');
var promiseHelpers = require('@whatwg-node/promise-helpers');
var DataLoader = require('dataloader');
var graphql = require('graphql');
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
var DataLoader__default = /*#__PURE__*/_interopDefault(DataLoader);
const DEFAULT_ARGS_FROM_KEYS = (keys) => ({ ids: keys });
function createBatchFn(options) {
const argsFromKeys = options.argsFromKeys ?? DEFAULT_ARGS_FROM_KEYS;
const fieldName = options.fieldName ?? options.info.fieldName;
const { valuesFromResults, lazyOptionsFn } = options;
return function batchFn(keys) {
return promiseHelpers.fakePromise(
promiseHelpers.handleMaybePromise(
() => delegate.delegateToSchema({
returnType: new graphql.GraphQLList(
graphql.getNamedType(options.returnType || options.info.returnType)
),
onLocatedError: (originalError) => {
if (originalError.path == null) {
return originalError;
}
const [pathFieldName, pathNumber, ...rest] = originalError.path;
if (pathFieldName !== fieldName) {
return originalError;
}
const pathNumberType = typeof pathNumber;
if (pathNumberType !== "number") {
return originalError;
}
return utils.relocatedError(originalError, [fieldName, ...rest]);
},
args: argsFromKeys(keys),
...lazyOptionsFn == null ? options : lazyOptionsFn(options, keys)
}),
(results) => {
if (results instanceof Error) {
return keys.map(() => results);
}
const values = valuesFromResults == null ? results : valuesFromResults(results, keys);
return Array.isArray(values) ? values : keys.map(() => values);
}
)
);
};
}
const getLoadersMap = utils.memoize2(function getLoadersMap2(_context, _schema) {
return /* @__PURE__ */ new Map();
});
const GLOBAL_CONTEXT = {};
const memoizedJsonStringify = utils.memoize1(function jsonStringify(value) {
return JSON.stringify(value);
});
const memoizedPrint = utils.memoize1(graphql.print);
function defaultCacheKeyFn(key) {
if (typeof key === "object") {
return memoizedJsonStringify(key);
}
return key;
}
function getLoader(options) {
const {
schema,
context,
info,
fieldName = info.fieldName,
dataLoaderOptions,
fieldNodes = info.fieldNodes[0] && delegate.getActualFieldNodes(info.fieldNodes[0]),
selectionSet = fieldNodes?.[0]?.selectionSet,
returnType = info.returnType,
argsFromKeys = DEFAULT_ARGS_FROM_KEYS,
key
} = options;
const loaders = getLoadersMap(context ?? GLOBAL_CONTEXT, schema);
let cacheKey = fieldName;
if (returnType) {
const namedType = graphql.getNamedType(returnType);
cacheKey += "@" + namedType.name;
}
if (selectionSet != null) {
cacheKey += memoizedPrint(selectionSet);
}
const fieldNode = fieldNodes?.[0];
if (fieldNode?.arguments) {
const args = argsFromKeys([key]);
cacheKey += fieldNode.arguments.filter((arg) => arg.name.value in args).map((arg) => memoizedPrint(arg)).join(",");
}
let loader = loaders.get(cacheKey);
if (loader === void 0) {
const batchFn = createBatchFn(options);
loader = new DataLoader__default.default(batchFn, {
// Prevents the keys to be passed with the same structure
cacheKeyFn: defaultCacheKeyFn,
...dataLoaderOptions
});
loaders.set(cacheKey, loader);
}
return loader;
}
function batchDelegateToSchema(options) {
const key = options.key;
if (key == null) {
return null;
} else if (Array.isArray(key) && !key.length) {
return [];
}
const loader = getLoader(options);
return Array.isArray(key) ? loader.loadMany(key) : loader.load(key);
}
function createBatchDelegateFn(optionsOrArgsFromKeys, lazyOptionsFn, dataLoaderOptions, valuesFromResults) {
return typeof optionsOrArgsFromKeys === "function" ? createBatchDelegateFnImpl({
argsFromKeys: optionsOrArgsFromKeys,
lazyOptionsFn,
dataLoaderOptions,
valuesFromResults
}) : createBatchDelegateFnImpl(optionsOrArgsFromKeys);
}
function createBatchDelegateFnImpl(options) {
return (batchDelegateOptions) => {
const loader = getLoader({
...options,
...batchDelegateOptions
});
return loader.load(batchDelegateOptions.key);
};
}
exports.batchDelegateToSchema = batchDelegateToSchema;
exports.createBatchDelegateFn = createBatchDelegateFn;
;