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 84 85 | 1x 1x 1x 1x 1x 1x 1x 1x 21x 69x 100x 80x 100x 32x 12x 10x 16x 25x | import { push } from 'object-path' import deepEqual from 'deep-equal' import { nextTick, skip } from './utils' import { allResolvers } from './allResolvers' import { pipeResolvers } from './pipeResolvers' import { combineResolvers } from './combineResolvers' import { contextMustBeObject } from './miscResolvers' /** * Piping resolver to save current value and reference to dependees cache. */ const saveDependee = combineResolvers( contextMustBeObject, (value, args, context, info) => (( push(context, '_dependees', { path: info.path, value }), value )), ) /** * Identify a resolver as being a dependee, so other sibling * field resolvers might depend on the value resolved by this one. * * Basically, it will polute "info" during resolving * to insert the resolved value and path to this resolver. * * @param {Function} resolver Resolver implementation. * @return {Promise}. */ export const isDependee = resolver => (root, ...args) => saveDependee(resolver(root, ...args), ...args) /** * Make sure the field name exists on the parent type. * * @param {String} dependeeName The name of the dependee to check the parent against * @return {Function} Resolver to error when no dependee is found. */ const dependeeExists = dependeeName => (root, args, context, { fieldName, parentType: { _fields, name: parent } }) => !_fields[dependeeName] ? new Error(`Cannot get dependee "${dependeeName}" from field "${fieldName}" on type "${parent}"`) : skip /** * Resolver implementation to retrieve the resolved value of a dependee sibling field. * * @param {String} dependeeName The name of the dependee this resolver depends on. * @param {Function} resolver Resolver implemenatation. * @return {Function} dependee resolver. */ export const resolveDependee = dependeeName => combineResolvers( contextMustBeObject, dependeeExists(dependeeName), pipeResolvers( // Make sure dependent resolvers occur after // dependees have been initialized. nextTick, // Find any currently resolved dependee. (root, args, { _dependees = [] }, info) => _dependees .filter(({ path: { prev } }) => deepEqual(prev, info.path.prev)) .find(({ path: { key } }) => key === dependeeName), // Run field resolution, if resolved value was not found. (resolved, args, context, info) => resolved === skip ? info.parentType._fields[dependeeName].resolve(info.rootValue, args, context, info) : resolved.value, ), ) /** * Resolver implementation to retrieve the resolved value of multiple dependee sibling fields. * * @param {[String]} dependeeNames Array of names of the dependees this resolver depends on. * @param {Function} resolver Resolver implemenatation. * @return {Function} dependee resolver. */ export const resolveDependees = dependeeNames => combineResolvers( contextMustBeObject, allResolvers(dependeeNames.map(resolveDependee)), ) |