UNPKG

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