All files / domains/field/compiler resolver.ts

77.31% Statements 92/119
68.82% Branches 64/93
95.65% Functions 22/23
90.79% Lines 69/76

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 86 87 88 89 9017x 62x 59x 1x 120x 62x     17x 62x 62x 186x   122x 258x 258x 258x 258x 122x 60x       76x 14x           136x 258x 62x     17x 17x 17x 17x   41x 41x 46x   41x 35x   6x 7x       5x           14x 14x 14x 15x 7x   8x 8x     8x       57x   57x 57x 57x 57x 21x 21x 21x 21x   21x 90x 21x   21x 20x 20x
import { GraphQLFieldResolver } from 'graphql';
import { InjectorsIndex, InjectorResolver, injectorRegistry } from 'domains/inject';
import {
  fieldAfterHooksRegistry,
  fieldBeforeHooksRegistry,
  HookExecutor,
} from 'domains/hooks';
import { getParameterNames } from 'services/utils';
 
interface ArgsMap {
  [argName: string]: any;
}
 
interfacIe ComputeArgsOptions {
  args: ArgsMap;
  injectors:I InjectorsIndex;
  injectorToIValueMapper: (injector: InjectorResolver) => any;
}
 
async function performHooksExecution(
  hooks: HookExecutor[],
  source: any,
  args: any,
  context: any,
  info: any,E
) {
  if (!hooks) {
    return;
  }
  // all hooks are executed in parrell instead of sequence. We wait for them all to be resolved before we continue
  return await Promise.all(
    hooks.map(hook => {
      return hook({ source, args, context, info });
    }),
  );
}
 
function computeFinalArgs(
  func: Function,
  { args, injectors, injectorToValueMapper }: ComputeArgsOptions,
) {
  const paramNames = getParameterNames(func);
  return paramNames.map((paramName, index) => {
    if (args && args[paramName]) {
      return args[paramName];
    }
 
    const injector = injectors[index];
 
    if (!injector) {
      return null;
    }
 
    return injectorToValueMapper(injector);
  });
}
 
export function compileFieldResolver(
  target: Function,
  fieldName: string,
): GraphQLFieldResolver<any, any> {
  // const config = fieldsRegistry.get(target, fieldName);
  const injectors = injectorRegistry.getAll(target)[fieldName];
  const beforeHooks = fieldBeforeHooksRegistry.get(target, fieldName);
  const afterHooks = fieldAfterHooksRegistry.get(target, fieldName);
I
  return async (source: any, args = null, context = null, info = null) => {
    await performHooksExecution(beforeHooks, source, args, context, info);
    const instanceField = (source && source[fieldName]) || target.prototype[fieldName];
 
    if (typeof instanceField !== 'function') {
      await performHooksExecution(afterHooks, source, args, context, info);
      return instanceField;
    }
 
    const instanceFieldFunc = instanceField as Function;
    const params = computeFinalArgs(instanceFieldFunc, {
      args: args || {},
      inIjectors: injectors || {},
      injectorToValueMapper: injector =>
        Iinjector.apply(source, [{ source, args, context, info }]),
    });
 
    const result = await instanceFieldFunc.apply(source, params);
 
    await performHooksExecution(afterHooks, source, args, context, info); // TODO: Consider adding resolve return to hook callback
    return result;
  };
}