All files / domains/union compiler.ts

93.55% Statements 29/31
80% Branches 8/10
100% Functions 6/6
93.1% Lines 27/29

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 8517x 17x 17x 17x 17x   1x 2x 3x 3x 2x                 1x 1x 1x       2x 4x 4x       2x     3x 1x   2x 2x 2x     2x     2x         2x 2x   17x                                                              
import {
  GraphQLUnionType,
  GraphQLObjectType,
  GraphQLResolveInfo,
  GraphQLType,
} from 'graphql';
 
import { resolveTypesList, isObjectType, resolveType } from 'services/utils';
import { Thunk } from 'services/types';
import { UnionError } from './error';
 
export interface UnionTypeResolver {
  (value: any, context: any, info: GraphQLResolveInfo): any;
}
 
export interface UnionOptions {
  types: Thunk<any[]>;
  name: string;
  resolveTypes?: UnionTypeResolver;
}
 
const compileUnionCache = new WeakMap<Function, GraphQLUnionType>();
 
function getDefaultResolver(types: GraphQLObjectType[]): UnionTypeResolver {
  return (value: any, context: any, info: any) => {
    for (let type of types) {
      if (type.isTypeOf(value, context, info)) {
        Ireturn type;
      }
    }
  };
}
 
/**
 * Resolves type, and if needed, tries to resolve it using typegql-aware types
 */
function enhanceTypeResolver(originalResolver: UnionTypeResolver): UnionTypeResolver {
  return (value, context, info) => {
    const rawResolvedType = originalResolver(value, context, info);
    Ireturn resolveType(rawResolvedType);
  };
}
 
function validateResolvedTypes(
  target: Function,
  types: GraphQLType[],
): types is GraphQLObjectType[] {
  for (let type of types) {
    if (!isObjectType(type)) {
      throw new UnionError(
        target,
        `Every union type must be of type GraphQLObjectType. '${type}' is not.`,
      );
    }
  }
  return true;
}
 
export function compileUnionType(target: Function, config: UnionOptions) {
  if (compileUnionCache.has(target)) {
    return compileUnionCache.get(target);
  }
 
  const { types, resolveTypes, name } = config;
 
  const resolvedTypes = resolveTypesList(types);
 
  if (!validateResolvedTypes(target, resolvedTypes)) {
    return;
  }
 
  const typeResolver = resolveTypes
    ? enhanceTypeResolver(resolveTypes)
    : getDefaultResolver(resolvedTypes);
 
  const compiled = new GraphQLUnionType({
    name,
    resolveType: typeResolver,
    types: resolvedTypes as GraphQLObjectType[],
  });
 
  compileUnionCache.set(target, compiled);
  return compiled;
}