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 574x 574x                 92x               91x 94x     91x 94x     91x 94x     91x 94x     91x           90x                 88x 88x   88x   88x               88x 88x   88x 75x   13x     88x 88x 88x    
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;
}