-
Notifications
You must be signed in to change notification settings - Fork 2.6k
/
index.ts
118 lines (98 loc) · 3.25 KB
/
index.ts
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import { checkDEV } from "../../utilities";
checkDEV();
import {
DocumentNode,
DefinitionNode,
VariableDefinitionNode,
OperationDefinitionNode
} from 'graphql';
import { invariant } from 'ts-invariant';
export enum DocumentType {
Query,
Mutation,
Subscription
}
export interface IDocumentDefinition {
type: DocumentType;
name: string;
variables: ReadonlyArray<VariableDefinitionNode>;
}
const cache = new Map();
export function operationName(type: DocumentType) {
let name;
switch (type) {
case DocumentType.Query:
name = 'Query';
break;
case DocumentType.Mutation:
name = 'Mutation';
break;
case DocumentType.Subscription:
name = 'Subscription';
break;
}
return name;
}
// This parser is mostly used to saftey check incoming documents.
export function parser(document: DocumentNode): IDocumentDefinition {
const cached = cache.get(document);
if (cached) return cached;
let variables, type, name;
invariant(
!!document && !!document.kind,
`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,
`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,
`react-apollo only supports one definition 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;
}