react-apollo
Version:
React data container for Apollo Client
81 lines (61 loc) • 2.8 kB
text/typescript
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[];
}
// the parser is mainly a safety check for the HOC
export function parser(document: DocumentNode): IDocumentDefinition {
// 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 || [];
let hasName = definition.name && definition.name.kind === 'Name';
name = hasName ? definition.name.value : 'data'; // fallback to using data if no name
return { name, type, variables };
}