1
- /* @noflow */
1
+ /* @flow */
2
2
/**
3
3
* Copyright (c) 2015, Facebook, Inc.
4
4
* All rights reserved.
8
8
* of patent rights can be found in the PATENTS file in the same directory.
9
9
*/
10
10
11
- import isNullish from '../jsutils/isNullish ' ;
11
+ import invariant from '../jsutils/invariant ' ;
12
12
import keyMap from '../jsutils/keyMap' ;
13
13
import keyValMap from '../jsutils/keyValMap' ;
14
14
import { valueFromAST } from './valueFromAST' ;
@@ -29,6 +29,9 @@ import {
29
29
30
30
import type {
31
31
Document ,
32
+ Type ,
33
+ NamedType ,
34
+ TypeDefinition ,
32
35
ObjectTypeDefinition ,
33
36
InputValueDefinition ,
34
37
InterfaceTypeDefinition ,
@@ -55,27 +58,38 @@ import {
55
58
GraphQLNonNull ,
56
59
} from '../type' ;
57
60
61
+ import type {
62
+ GraphQLType ,
63
+ GraphQLNamedType
64
+ } from '../type/definition' ;
65
+
58
66
59
67
type CompositeDefinition =
60
68
ObjectTypeDefinition |
61
69
InterfaceTypeDefinition |
62
70
UnionTypeDefinition ;
63
71
64
- function buildWrappedType ( innerType , inputTypeAST ) {
72
+ function buildWrappedType (
73
+ innerType : GraphQLType ,
74
+ inputTypeAST : Type
75
+ ) : GraphQLType {
65
76
if ( inputTypeAST . kind === LIST_TYPE ) {
66
77
return new GraphQLList ( buildWrappedType ( innerType , inputTypeAST . type ) ) ;
67
78
}
68
79
if ( inputTypeAST . kind === NON_NULL_TYPE ) {
69
- return new GraphQLNonNull ( buildWrappedType ( innerType , inputTypeAST . type ) ) ;
80
+ const wrappedType = buildWrappedType ( innerType , inputTypeAST . type ) ;
81
+ invariant ( ! ( wrappedType instanceof GraphQLNonNull ) , 'No nesting nonnull.' ) ;
82
+ return new GraphQLNonNull ( wrappedType ) ;
70
83
}
71
84
return innerType ;
72
85
}
73
86
74
- function getInnerTypeName ( typeAST ) {
75
- if ( typeAST . kind === LIST_TYPE || typeAST . kind === NON_NULL_TYPE ) {
76
- return getInnerTypeName ( typeAST . type ) ;
87
+ function getNamedTypeAST ( typeAST : Type ) : NamedType {
88
+ let namedType = typeAST ;
89
+ while ( namedType . kind === LIST_TYPE || namedType . kind === NON_NULL_TYPE ) {
90
+ namedType = namedType . type ;
77
91
}
78
- return typeAST . name . value ;
92
+ return namedType ;
79
93
}
80
94
81
95
/**
@@ -92,100 +106,97 @@ export function buildASTSchema(
92
106
mutationTypeName : ?string ,
93
107
subscriptionTypeName : ?string
94
108
) : GraphQLSchema {
95
-
96
- if ( isNullish ( ast ) ) {
109
+ if ( ! ast ) {
97
110
throw new Error ( 'must pass in ast' ) ;
98
111
}
99
- if ( isNullish ( queryTypeName ) ) {
112
+
113
+ if ( ! queryTypeName ) {
100
114
throw new Error ( 'must pass in query type' ) ;
101
115
}
102
116
103
- const typeDefs = ast . definitions . filter ( d => {
117
+ const typeDefs : Array < TypeDefinition > = [];
118
+ for (let i = 0; i < ast . definitions . length ; i ++ ) {
119
+ const d = ast . definitions [ i ] ;
104
120
switch ( d . kind ) {
105
121
case OBJECT_TYPE_DEFINITION :
106
122
case INTERFACE_TYPE_DEFINITION :
107
123
case ENUM_TYPE_DEFINITION :
108
124
case UNION_TYPE_DEFINITION :
109
125
case SCALAR_TYPE_DEFINITION :
110
- case INPUT_OBJECT_TYPE_DEFINITION : return true ;
126
+ case INPUT_OBJECT_TYPE_DEFINITION :
127
+ typeDefs . push ( d ) ;
111
128
}
112
- } ) ;
129
+ }
113
130
114
- const astMap = keyMap ( typeDefs , d => d . name . value ) ;
131
+ const astMap : { [ name : string ] : TypeDefinition } =
132
+ keyMap ( typeDefs , d => d . name . value ) ;
115
133
116
- if ( isNullish ( astMap [ queryTypeName ] ) ) {
134
+ if ( ! astMap [ queryTypeName ] ) {
117
135
throw new Error ( 'Specified query type ' + queryTypeName +
118
136
' not found in document.' ) ;
119
137
}
120
138
121
- if ( ! isNullish ( mutationTypeName ) && isNullish ( astMap [ mutationTypeName ] ) ) {
139
+ if ( mutationTypeName && ! astMap [ mutationTypeName ] ) {
122
140
throw new Error ( 'Specified mutation type ' + mutationTypeName +
123
141
' not found in document.' ) ;
124
142
}
125
143
126
- if ( ! isNullish ( subscriptionTypeName ) &&
127
- isNullish ( astMap [ subscriptionTypeName ] ) ) {
144
+ if ( subscriptionTypeName && ! astMap [ subscriptionTypeName ] ) {
128
145
throw new Error ( 'Specified subscription type ' + subscriptionTypeName +
129
146
' not found in document.' ) ;
130
147
}
131
148
132
- /**
133
- * This generates a function that allows you to produce
134
- * type definitions on demand. We produce the function
135
- * in order to close over the memoization dictionaries
136
- * that need to be retained over multiple functions calls.
137
- **/
138
- function getTypeDefProducer ( ) {
139
-
140
- const innerTypeMap = {
141
- String : GraphQLString ,
142
- Int : GraphQLInt ,
143
- Float : GraphQLFloat ,
144
- Boolean : GraphQLBoolean ,
145
- ID : GraphQLID ,
146
- } ;
149
+ const innerTypeMap = {
150
+ String : GraphQLString ,
151
+ Int : GraphQLInt ,
152
+ Float : GraphQLFloat ,
153
+ Boolean : GraphQLBoolean ,
154
+ ID : GraphQLID ,
155
+ } ;
147
156
148
- return typeAST => {
149
- const typeName = getInnerTypeName ( typeAST ) ;
150
- if ( ! isNullish ( innerTypeMap [ typeName ] ) ) {
151
- return buildWrappedType ( innerTypeMap [ typeName ] , typeAST ) ;
152
- }
157
+ typeDefs . forEach ( def => typeDefNamed ( def . name . value ) ) ;
153
158
154
- if ( isNullish ( astMap [ typeName ] ) ) {
155
- throw new Error ( `Type ${ typeName } not found in document` ) ;
156
- }
159
+ return new GraphQLSchema ( {
160
+ query : getObjectType ( astMap [ queryTypeName ] ) ,
161
+ mutation : mutationTypeName ? getObjectType ( astMap [ mutationTypeName ] ) : null ,
162
+ subscription :
163
+ subscriptionTypeName ? getObjectType ( astMap [ subscriptionTypeName ] ) : null ,
164
+ } ) ;
157
165
158
- const innerTypeDef = makeSchemaDef ( astMap [ typeName ] ) ;
159
- if ( isNullish ( innerTypeDef ) ) {
160
- throw new Error ( 'Nothing constructed for ' + typeName ) ;
161
- }
162
- innerTypeMap [ typeName ] = innerTypeDef ;
163
- return buildWrappedType ( innerTypeDef , typeAST ) ;
164
- } ;
166
+ function getObjectType ( typeAST : TypeDefinition ) : GraphQLObjectType {
167
+ const type = typeDefNamed ( typeAST . name . value ) ;
168
+ invariant (
169
+ type instanceof GraphQLObjectType ,
170
+ `AST must provide object type.`
171
+ ) ;
172
+ return ( type : any ) ;
165
173
}
166
174
167
- const produceTypeDef = getTypeDefProducer ( ast ) ;
168
-
169
- ast . definitions . forEach ( produceTypeDef ) ;
170
-
171
- const queryType = produceTypeDef ( astMap [ queryTypeName ] ) ;
175
+ function produceTypeDef ( typeAST : Type ) : GraphQLType {
176
+ const typeName = getNamedTypeAST ( typeAST ) . name . value ;
177
+ const typeDef = typeDefNamed ( typeName ) ;
178
+ return buildWrappedType ( typeDef , typeAST ) ;
179
+ }
172
180
173
- const schemaBody = {
174
- query : queryType
175
- } ;
181
+ function typeDefNamed ( typeName : string ) : GraphQLNamedType {
182
+ if ( innerTypeMap [ typeName ] ) {
183
+ return innerTypeMap [ typeName ] ;
184
+ }
176
185
177
- if ( ! isNullish ( mutationTypeName ) ) {
178
- schemaBody . mutation = produceTypeDef ( astMap [ mutationTypeName ] ) ;
179
- }
186
+ if ( ! astMap [ typeName ] ) {
187
+ throw new Error ( `Type ${ typeName } not found in document` ) ;
188
+ }
180
189
181
- if ( ! isNullish ( subscriptionTypeName ) ) {
182
- schemaBody . subscription = produceTypeDef ( astMap [ subscriptionTypeName ] ) ;
190
+ const innerTypeDef = makeSchemaDef ( astMap [ typeName ] ) ;
191
+ if ( ! innerTypeDef ) {
192
+ throw new Error ( 'Nothing constructed for ' + typeName ) ;
193
+ }
194
+ innerTypeMap [ typeName ] = innerTypeDef ;
195
+ return innerTypeDef ;
183
196
}
184
197
185
- return new GraphQLSchema ( schemaBody ) ;
186
-
187
198
function makeSchemaDef ( def ) {
188
- if ( isNullish ( def ) ) {
199
+ if ( ! def ) {
189
200
throw new Error ( 'def must be defined' ) ;
190
201
}
191
202
switch ( def . kind ) {
0 commit comments