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
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 67x 64x 4x 131x 67x     17x 68x 67x 201x   135x 286x 286x 286x 286x 135x 68x       83x 16x           151x 286x 67x     17x 17x 17x 17x   44x 44x 52x   44x 36x   8x 8x       8x           16x 16x 16x 17x 9x   8x 8x     8x       57x   57x 57x 57x 57x 23x 23x 23x 23x   23x 99x 23x   23x 21x 21x
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;
  };
}