All files / src parser.ts

100% Statements 34/34
96.88% Branches 31/32
100% Functions 6/6
100% Lines 32/32

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 90 91 92 93 94 95 96 97 98 99 100 101              28x   28x 28x 28x 28x                 28x     28x 590x 590x                 93x               92x 95x     92x 95x     92x 95x     92x 95x     92x           91x                 89x 89x   89x   89x               89x 89x   89x 75x   14x     89x 89x 89x    
import {
  DocumentNode,
  DefinitionNode,
  VariableDefinitionNode,
  OperationDefinitionNode,
} from 'graphql';
 
const invariant = require('invariant');
 
export enum DocumentType {
  Query,
  Mutation,
  Subscription,
}
 
export interface IDocumentDefinition {
  type: DocumentType;
  name: string;
  variables: VariableDefinitionNode[];
}
 
const cache = new Map();
 
// the parser is mainly a safety check for the HOC
export function parser(document: DocumentNode): IDocumentDefinition {
  const cached = cache.get(document);
  if (cached) return cached;
  // variables
  let variables, type, name;
 
  /*
 
    Saftey checks for proper usage of react-apollo
 
  */
  invariant(
    !!document && !!document.kind,
    // tslint:disable-line
    `Argument of ${document} passed to parser was not a valid GraphQL ` +
      `DocumentNode. You may need to use 'graphql-tag' or another method ` +
      `to convert your operation into a document`,
  );
 
  const fragments = document.definitions.filter(
    (x: DefinitionNode) => x.kind === 'FragmentDefinition',
  );
 
  const queries = document.definitions.filter(
    (x: DefinitionNode) => x.kind === 'OperationDefinition' && x.operation === 'query',
  );
 
  const mutations = document.definitions.filter(
    (x: DefinitionNode) => x.kind === 'OperationDefinition' && x.operation === 'mutation',
  );
 
  const subscriptions = document.definitions.filter(
    (x: DefinitionNode) => x.kind === 'OperationDefinition' && x.operation === 'subscription',
  );
 
  invariant(
    !fragments.length || (queries.length || mutations.length || subscriptions.length),
    `Passing only a fragment to 'graphql' is not yet supported. ` +
      `You must include a query, subscription or mutation as well`,
  );
 
  invariant(
    queries.length + mutations.length + subscriptions.length <= 1,
    // tslint:disable-line
    `react-apollo only supports a query, subscription, or a mutation per HOC. ` +
      `${document} had ${queries.length} queries, ${subscriptions.length} ` +
      `subscriptions and ${mutations.length} mutations. ` +
      `You can use 'compose' to join multiple operation types to a component`,
  );
 
  type = queries.length ? DocumentType.Query : DocumentType.Mutation;
  if (!queries.length && !mutations.length) type = DocumentType.Subscription;
 
  const definitions = queries.length ? queries : mutations.length ? mutations : subscriptions;
 
  invariant(
    definitions.length === 1,
    // tslint:disable-line
    `react-apollo only supports one defintion per HOC. ${document} had ` +
      `${definitions.length} definitions. ` +
      `You can use 'compose' to join multiple operation types to a component`,
  );
 
  const definition = definitions[0] as OperationDefinitionNode;
  variables = definition.variableDefinitions || [];
 
  if (definition.name && definition.name.kind === 'Name') {
    name = definition.name.value;
  } else {
    name = 'data'; // fallback to using data if no name
  }
 
  const payload = { name, type, variables };
  cache.set(document, payload);
  return payload;
}