UNPKG

11.7 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.buildClientSchema = buildClientSchema;
7
8var _inspect = _interopRequireDefault(require("../jsutils/inspect"));
9
10var _invariant = _interopRequireDefault(require("../jsutils/invariant"));
11
12var _keyMap = _interopRequireDefault(require("../jsutils/keyMap"));
13
14var _keyValMap = _interopRequireDefault(require("../jsutils/keyValMap"));
15
16var _valueFromAST = require("./valueFromAST");
17
18var _parser = require("../language/parser");
19
20var _schema = require("../type/schema");
21
22var _definition = require("../type/definition");
23
24var _directives = require("../type/directives");
25
26var _introspection = require("../type/introspection");
27
28var _scalars = require("../type/scalars");
29
30function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
31
32/**
33 * Copyright (c) 2015-present, Facebook, Inc.
34 *
35 * This source code is licensed under the MIT license found in the
36 * LICENSE file in the root directory of this source tree.
37 *
38 *
39 */
40
41/**
42 * Build a GraphQLSchema for use by client tools.
43 *
44 * Given the result of a client running the introspection query, creates and
45 * returns a GraphQLSchema instance which can be then used with all graphql-js
46 * tools, but cannot be used to execute a query, as introspection does not
47 * represent the "resolver", "parse" or "serialize" functions or any other
48 * server-internal mechanisms.
49 *
50 * This function expects a complete introspection result. Don't forget to check
51 * the "errors" field of a server response before calling this function.
52 */
53function buildClientSchema(introspection, options) {
54 // Get the schema from the introspection result.
55 var schemaIntrospection = introspection.__schema; // Converts the list of types into a keyMap based on the type names.
56
57 var typeIntrospectionMap = (0, _keyMap.default)(schemaIntrospection.types, function (type) {
58 return type.name;
59 }); // A cache to use to store the actual GraphQLType definition objects by name.
60 // Initialize to the GraphQL built in scalars. All functions below are inline
61 // so that this type def cache is within the scope of the closure.
62
63 var typeDefCache = (0, _keyMap.default)(_scalars.specifiedScalarTypes.concat(_introspection.introspectionTypes), function (type) {
64 return type.name;
65 }); // Given a type reference in introspection, return the GraphQLType instance.
66 // preferring cached instances before building new instances.
67
68 function getType(typeRef) {
69 if (typeRef.kind === _introspection.TypeKind.LIST) {
70 var itemRef = typeRef.ofType;
71
72 if (!itemRef) {
73 throw new Error('Decorated type deeper than introspection query.');
74 }
75
76 return (0, _definition.GraphQLList)(getType(itemRef));
77 }
78
79 if (typeRef.kind === _introspection.TypeKind.NON_NULL) {
80 var nullableRef = typeRef.ofType;
81
82 if (!nullableRef) {
83 throw new Error('Decorated type deeper than introspection query.');
84 }
85
86 var nullableType = getType(nullableRef);
87 return (0, _definition.GraphQLNonNull)((0, _definition.assertNullableType)(nullableType));
88 }
89
90 if (!typeRef.name) {
91 throw new Error('Unknown type reference: ' + (0, _inspect.default)(typeRef));
92 }
93
94 return getNamedType(typeRef.name);
95 }
96
97 function getNamedType(typeName) {
98 if (typeDefCache[typeName]) {
99 return typeDefCache[typeName];
100 }
101
102 var typeIntrospection = typeIntrospectionMap[typeName];
103
104 if (!typeIntrospection) {
105 throw new Error("Invalid or incomplete schema, unknown type: ".concat(typeName, ". Ensure ") + 'that a full introspection query is used in order to build a ' + 'client schema.');
106 }
107
108 var typeDef = buildType(typeIntrospection);
109 typeDefCache[typeName] = typeDef;
110 return typeDef;
111 }
112
113 function getInputType(typeRef) {
114 var type = getType(typeRef);
115 !(0, _definition.isInputType)(type) ? (0, _invariant.default)(0, 'Introspection must provide input type for arguments, but received: ' + (0, _inspect.default)(type) + '.') : void 0;
116 return type;
117 }
118
119 function getOutputType(typeRef) {
120 var type = getType(typeRef);
121 !(0, _definition.isOutputType)(type) ? (0, _invariant.default)(0, 'Introspection must provide output type for fields, but received: ' + (0, _inspect.default)(type) + '.') : void 0;
122 return type;
123 }
124
125 function getObjectType(typeRef) {
126 var type = getType(typeRef);
127 return (0, _definition.assertObjectType)(type);
128 }
129
130 function getInterfaceType(typeRef) {
131 var type = getType(typeRef);
132 return (0, _definition.assertInterfaceType)(type);
133 } // Given a type's introspection result, construct the correct
134 // GraphQLType instance.
135
136
137 function buildType(type) {
138 if (type && type.name && type.kind) {
139 switch (type.kind) {
140 case _introspection.TypeKind.SCALAR:
141 return buildScalarDef(type);
142
143 case _introspection.TypeKind.OBJECT:
144 return buildObjectDef(type);
145
146 case _introspection.TypeKind.INTERFACE:
147 return buildInterfaceDef(type);
148
149 case _introspection.TypeKind.UNION:
150 return buildUnionDef(type);
151
152 case _introspection.TypeKind.ENUM:
153 return buildEnumDef(type);
154
155 case _introspection.TypeKind.INPUT_OBJECT:
156 return buildInputObjectDef(type);
157 }
158 }
159
160 throw new Error('Invalid or incomplete introspection result. Ensure that a full ' + 'introspection query is used in order to build a client schema:' + (0, _inspect.default)(type));
161 }
162
163 function buildScalarDef(scalarIntrospection) {
164 return new _definition.GraphQLScalarType({
165 name: scalarIntrospection.name,
166 description: scalarIntrospection.description,
167 serialize: function serialize(value) {
168 return value;
169 }
170 });
171 }
172
173 function buildObjectDef(objectIntrospection) {
174 if (!objectIntrospection.interfaces) {
175 throw new Error('Introspection result missing interfaces: ' + (0, _inspect.default)(objectIntrospection));
176 }
177
178 return new _definition.GraphQLObjectType({
179 name: objectIntrospection.name,
180 description: objectIntrospection.description,
181 interfaces: function interfaces() {
182 return objectIntrospection.interfaces.map(getInterfaceType);
183 },
184 fields: function fields() {
185 return buildFieldDefMap(objectIntrospection);
186 }
187 });
188 }
189
190 function buildInterfaceDef(interfaceIntrospection) {
191 return new _definition.GraphQLInterfaceType({
192 name: interfaceIntrospection.name,
193 description: interfaceIntrospection.description,
194 fields: function fields() {
195 return buildFieldDefMap(interfaceIntrospection);
196 }
197 });
198 }
199
200 function buildUnionDef(unionIntrospection) {
201 if (!unionIntrospection.possibleTypes) {
202 throw new Error('Introspection result missing possibleTypes: ' + (0, _inspect.default)(unionIntrospection));
203 }
204
205 return new _definition.GraphQLUnionType({
206 name: unionIntrospection.name,
207 description: unionIntrospection.description,
208 types: function types() {
209 return unionIntrospection.possibleTypes.map(getObjectType);
210 }
211 });
212 }
213
214 function buildEnumDef(enumIntrospection) {
215 if (!enumIntrospection.enumValues) {
216 throw new Error('Introspection result missing enumValues: ' + (0, _inspect.default)(enumIntrospection));
217 }
218
219 return new _definition.GraphQLEnumType({
220 name: enumIntrospection.name,
221 description: enumIntrospection.description,
222 values: (0, _keyValMap.default)(enumIntrospection.enumValues, function (valueIntrospection) {
223 return valueIntrospection.name;
224 }, function (valueIntrospection) {
225 return {
226 description: valueIntrospection.description,
227 deprecationReason: valueIntrospection.deprecationReason
228 };
229 })
230 });
231 }
232
233 function buildInputObjectDef(inputObjectIntrospection) {
234 if (!inputObjectIntrospection.inputFields) {
235 throw new Error('Introspection result missing inputFields: ' + (0, _inspect.default)(inputObjectIntrospection));
236 }
237
238 return new _definition.GraphQLInputObjectType({
239 name: inputObjectIntrospection.name,
240 description: inputObjectIntrospection.description,
241 fields: function fields() {
242 return buildInputValueDefMap(inputObjectIntrospection.inputFields);
243 }
244 });
245 }
246
247 function buildFieldDefMap(typeIntrospection) {
248 if (!typeIntrospection.fields) {
249 throw new Error('Introspection result missing fields: ' + (0, _inspect.default)(typeIntrospection));
250 }
251
252 return (0, _keyValMap.default)(typeIntrospection.fields, function (fieldIntrospection) {
253 return fieldIntrospection.name;
254 }, function (fieldIntrospection) {
255 if (!fieldIntrospection.args) {
256 throw new Error('Introspection result missing field args: ' + (0, _inspect.default)(fieldIntrospection));
257 }
258
259 return {
260 description: fieldIntrospection.description,
261 deprecationReason: fieldIntrospection.deprecationReason,
262 type: getOutputType(fieldIntrospection.type),
263 args: buildInputValueDefMap(fieldIntrospection.args)
264 };
265 });
266 }
267
268 function buildInputValueDefMap(inputValueIntrospections) {
269 return (0, _keyValMap.default)(inputValueIntrospections, function (inputValue) {
270 return inputValue.name;
271 }, buildInputValue);
272 }
273
274 function buildInputValue(inputValueIntrospection) {
275 var type = getInputType(inputValueIntrospection.type);
276 var defaultValue = inputValueIntrospection.defaultValue ? (0, _valueFromAST.valueFromAST)((0, _parser.parseValue)(inputValueIntrospection.defaultValue), type) : undefined;
277 return {
278 description: inputValueIntrospection.description,
279 type: type,
280 defaultValue: defaultValue
281 };
282 }
283
284 function buildDirective(directiveIntrospection) {
285 if (!directiveIntrospection.args) {
286 throw new Error('Introspection result missing directive args: ' + (0, _inspect.default)(directiveIntrospection));
287 }
288
289 if (!directiveIntrospection.locations) {
290 throw new Error('Introspection result missing directive locations: ' + (0, _inspect.default)(directiveIntrospection));
291 }
292
293 return new _directives.GraphQLDirective({
294 name: directiveIntrospection.name,
295 description: directiveIntrospection.description,
296 locations: directiveIntrospection.locations.slice(),
297 args: buildInputValueDefMap(directiveIntrospection.args)
298 });
299 } // Iterate through all types, getting the type definition for each, ensuring
300 // that any type not directly referenced by a field will get created.
301
302
303 var types = schemaIntrospection.types.map(function (typeIntrospection) {
304 return getNamedType(typeIntrospection.name);
305 }); // Get the root Query, Mutation, and Subscription types.
306
307 var queryType = schemaIntrospection.queryType ? getObjectType(schemaIntrospection.queryType) : null;
308 var mutationType = schemaIntrospection.mutationType ? getObjectType(schemaIntrospection.mutationType) : null;
309 var subscriptionType = schemaIntrospection.subscriptionType ? getObjectType(schemaIntrospection.subscriptionType) : null; // Get the directives supported by Introspection, assuming empty-set if
310 // directives were not queried for.
311
312 var directives = schemaIntrospection.directives ? schemaIntrospection.directives.map(buildDirective) : []; // Then produce and return a Schema with these types.
313
314 return new _schema.GraphQLSchema({
315 query: queryType,
316 mutation: mutationType,
317 subscription: subscriptionType,
318 types: types,
319 directives: directives,
320 assumeValid: options && options.assumeValid,
321 allowedLegacyNames: options && options.allowedLegacyNames
322 });
323}
\No newline at end of file