1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | import objectValues from '../polyfills/objectValues';
|
10 | import invariant from '../jsutils/invariant';
|
11 | import keyMap from '../jsutils/keyMap';
|
12 | import keyValMap from '../jsutils/keyValMap';
|
13 | import { valueFromAST } from './valueFromAST';
|
14 | import { assertValidSDL } from '../validation/validate';
|
15 | import blockStringValue from '../language/blockStringValue';
|
16 | import { TokenKind } from '../language/lexer';
|
17 | import { parse } from '../language/parser';
|
18 | import { getDirectiveValues } from '../execution/values';
|
19 | import { Kind } from '../language/kinds';
|
20 | import { isTypeDefinitionNode } from '../language/predicates';
|
21 | import { GraphQLScalarType, GraphQLObjectType, GraphQLInterfaceType, GraphQLUnionType, GraphQLEnumType, GraphQLInputObjectType, GraphQLList, GraphQLNonNull } from '../type/definition';
|
22 | import { GraphQLDirective, GraphQLSkipDirective, GraphQLIncludeDirective, GraphQLDeprecatedDirective } from '../type/directives';
|
23 | import { introspectionTypes } from '../type/introspection';
|
24 | import { specifiedScalarTypes } from '../type/scalars';
|
25 | import { GraphQLSchema } from '../type/schema';
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 | export function buildASTSchema(documentAST, options) {
|
44 | !(documentAST && documentAST.kind === Kind.DOCUMENT) ? invariant(0, 'Must provide valid Document AST') : void 0;
|
45 |
|
46 | if (!options || !(options.assumeValid || options.assumeValidSDL)) {
|
47 | assertValidSDL(documentAST);
|
48 | }
|
49 |
|
50 | var schemaDef;
|
51 | var nodeMap = Object.create(null);
|
52 | var directiveDefs = [];
|
53 | var _iteratorNormalCompletion = true;
|
54 | var _didIteratorError = false;
|
55 | var _iteratorError = undefined;
|
56 |
|
57 | try {
|
58 | for (var _iterator = documentAST.definitions[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
59 | var def = _step.value;
|
60 |
|
61 | if (def.kind === Kind.SCHEMA_DEFINITION) {
|
62 | schemaDef = def;
|
63 | } else if (isTypeDefinitionNode(def)) {
|
64 | nodeMap[def.name.value] = def;
|
65 | } else if (def.kind === Kind.DIRECTIVE_DEFINITION) {
|
66 | directiveDefs.push(def);
|
67 | }
|
68 | }
|
69 | } catch (err) {
|
70 | _didIteratorError = true;
|
71 | _iteratorError = err;
|
72 | } finally {
|
73 | try {
|
74 | if (!_iteratorNormalCompletion && _iterator.return != null) {
|
75 | _iterator.return();
|
76 | }
|
77 | } finally {
|
78 | if (_didIteratorError) {
|
79 | throw _iteratorError;
|
80 | }
|
81 | }
|
82 | }
|
83 |
|
84 | var operationTypes = schemaDef ? getOperationTypes(schemaDef) : {
|
85 | query: nodeMap.Query,
|
86 | mutation: nodeMap.Mutation,
|
87 | subscription: nodeMap.Subscription
|
88 | };
|
89 | var definitionBuilder = new ASTDefinitionBuilder(nodeMap, options, function (typeName) {
|
90 | throw new Error("Type \"".concat(typeName, "\" not found in document."));
|
91 | });
|
92 | var directives = directiveDefs.map(function (def) {
|
93 | return definitionBuilder.buildDirective(def);
|
94 | });
|
95 |
|
96 | if (!directives.some(function (directive) {
|
97 | return directive.name === 'skip';
|
98 | })) {
|
99 | directives.push(GraphQLSkipDirective);
|
100 | }
|
101 |
|
102 | if (!directives.some(function (directive) {
|
103 | return directive.name === 'include';
|
104 | })) {
|
105 | directives.push(GraphQLIncludeDirective);
|
106 | }
|
107 |
|
108 | if (!directives.some(function (directive) {
|
109 | return directive.name === 'deprecated';
|
110 | })) {
|
111 | directives.push(GraphQLDeprecatedDirective);
|
112 | }
|
113 |
|
114 |
|
115 |
|
116 |
|
117 | return new GraphQLSchema({
|
118 | query: operationTypes.query ? definitionBuilder.buildType(operationTypes.query) : null,
|
119 | mutation: operationTypes.mutation ? definitionBuilder.buildType(operationTypes.mutation) : null,
|
120 | subscription: operationTypes.subscription ? definitionBuilder.buildType(operationTypes.subscription) : null,
|
121 | types: objectValues(nodeMap).map(function (node) {
|
122 | return definitionBuilder.buildType(node);
|
123 | }),
|
124 | directives: directives,
|
125 | astNode: schemaDef,
|
126 | assumeValid: options && options.assumeValid,
|
127 | allowedLegacyNames: options && options.allowedLegacyNames
|
128 | });
|
129 |
|
130 | function getOperationTypes(schema) {
|
131 | var opTypes = {};
|
132 | var _iteratorNormalCompletion2 = true;
|
133 | var _didIteratorError2 = false;
|
134 | var _iteratorError2 = undefined;
|
135 |
|
136 | try {
|
137 | for (var _iterator2 = schema.operationTypes[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
|
138 | var operationType = _step2.value;
|
139 | opTypes[operationType.operation] = operationType.type;
|
140 | }
|
141 | } catch (err) {
|
142 | _didIteratorError2 = true;
|
143 | _iteratorError2 = err;
|
144 | } finally {
|
145 | try {
|
146 | if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
|
147 | _iterator2.return();
|
148 | }
|
149 | } finally {
|
150 | if (_didIteratorError2) {
|
151 | throw _iteratorError2;
|
152 | }
|
153 | }
|
154 | }
|
155 |
|
156 | return opTypes;
|
157 | }
|
158 | }
|
159 | export var ASTDefinitionBuilder =
|
160 |
|
161 | function () {
|
162 | function ASTDefinitionBuilder(typeDefinitionsMap, options, resolveType) {
|
163 | this._typeDefinitionsMap = typeDefinitionsMap;
|
164 | this._options = options;
|
165 | this._resolveType = resolveType;
|
166 |
|
167 | this._cache = keyMap(specifiedScalarTypes.concat(introspectionTypes), function (type) {
|
168 | return type.name;
|
169 | });
|
170 | }
|
171 |
|
172 | var _proto = ASTDefinitionBuilder.prototype;
|
173 |
|
174 | _proto.buildType = function buildType(node) {
|
175 | var typeName = node.name.value;
|
176 |
|
177 | if (!this._cache[typeName]) {
|
178 | if (node.kind === Kind.NAMED_TYPE) {
|
179 | var defNode = this._typeDefinitionsMap[typeName];
|
180 | this._cache[typeName] = defNode ? this._makeSchemaDef(defNode) : this._resolveType(node.name.value);
|
181 | } else {
|
182 | this._cache[typeName] = this._makeSchemaDef(node);
|
183 | }
|
184 | }
|
185 |
|
186 | return this._cache[typeName];
|
187 | };
|
188 |
|
189 | _proto._buildWrappedType = function _buildWrappedType(typeNode) {
|
190 | if (typeNode.kind === Kind.LIST_TYPE) {
|
191 | return GraphQLList(this._buildWrappedType(typeNode.type));
|
192 | }
|
193 |
|
194 | if (typeNode.kind === Kind.NON_NULL_TYPE) {
|
195 | return GraphQLNonNull(
|
196 | this._buildWrappedType(typeNode.type));
|
197 | }
|
198 |
|
199 | return this.buildType(typeNode);
|
200 | };
|
201 |
|
202 | _proto.buildDirective = function buildDirective(directiveNode) {
|
203 | return new GraphQLDirective({
|
204 | name: directiveNode.name.value,
|
205 | description: getDescription(directiveNode, this._options),
|
206 | locations: directiveNode.locations.map(function (node) {
|
207 | return node.value;
|
208 | }),
|
209 | args: directiveNode.arguments && this._makeInputValues(directiveNode.arguments),
|
210 | astNode: directiveNode
|
211 | });
|
212 | };
|
213 |
|
214 | _proto.buildField = function buildField(field) {
|
215 | return {
|
216 |
|
217 |
|
218 |
|
219 | type: this._buildWrappedType(field.type),
|
220 | description: getDescription(field, this._options),
|
221 | args: field.arguments && this._makeInputValues(field.arguments),
|
222 | deprecationReason: getDeprecationReason(field),
|
223 | astNode: field
|
224 | };
|
225 | };
|
226 |
|
227 | _proto.buildInputField = function buildInputField(value) {
|
228 |
|
229 |
|
230 | var type = this._buildWrappedType(value.type);
|
231 |
|
232 | return {
|
233 | name: value.name.value,
|
234 | type: type,
|
235 | description: getDescription(value, this._options),
|
236 | defaultValue: valueFromAST(value.defaultValue, type),
|
237 | astNode: value
|
238 | };
|
239 | };
|
240 |
|
241 | _proto.buildEnumValue = function buildEnumValue(value) {
|
242 | return {
|
243 | description: getDescription(value, this._options),
|
244 | deprecationReason: getDeprecationReason(value),
|
245 | astNode: value
|
246 | };
|
247 | };
|
248 |
|
249 | _proto._makeSchemaDef = function _makeSchemaDef(def) {
|
250 | switch (def.kind) {
|
251 | case Kind.OBJECT_TYPE_DEFINITION:
|
252 | return this._makeTypeDef(def);
|
253 |
|
254 | case Kind.INTERFACE_TYPE_DEFINITION:
|
255 | return this._makeInterfaceDef(def);
|
256 |
|
257 | case Kind.ENUM_TYPE_DEFINITION:
|
258 | return this._makeEnumDef(def);
|
259 |
|
260 | case Kind.UNION_TYPE_DEFINITION:
|
261 | return this._makeUnionDef(def);
|
262 |
|
263 | case Kind.SCALAR_TYPE_DEFINITION:
|
264 | return this._makeScalarDef(def);
|
265 |
|
266 | case Kind.INPUT_OBJECT_TYPE_DEFINITION:
|
267 | return this._makeInputObjectDef(def);
|
268 |
|
269 | default:
|
270 | throw new Error("Type kind \"".concat(def.kind, "\" not supported."));
|
271 | }
|
272 | };
|
273 |
|
274 | _proto._makeTypeDef = function _makeTypeDef(def) {
|
275 | var _this = this;
|
276 |
|
277 | var interfaces = def.interfaces;
|
278 | return new GraphQLObjectType({
|
279 | name: def.name.value,
|
280 | description: getDescription(def, this._options),
|
281 | fields: function fields() {
|
282 | return _this._makeFieldDefMap(def);
|
283 | },
|
284 |
|
285 |
|
286 |
|
287 | interfaces: interfaces ? function () {
|
288 | return interfaces.map(function (ref) {
|
289 | return _this.buildType(ref);
|
290 | });
|
291 | } : [],
|
292 | astNode: def
|
293 | });
|
294 | };
|
295 |
|
296 | _proto._makeFieldDefMap = function _makeFieldDefMap(def) {
|
297 | var _this2 = this;
|
298 |
|
299 | return def.fields ? keyValMap(def.fields, function (field) {
|
300 | return field.name.value;
|
301 | }, function (field) {
|
302 | return _this2.buildField(field);
|
303 | }) : {};
|
304 | };
|
305 |
|
306 | _proto._makeInputValues = function _makeInputValues(values) {
|
307 | var _this3 = this;
|
308 |
|
309 | return keyValMap(values, function (value) {
|
310 | return value.name.value;
|
311 | }, function (value) {
|
312 | return _this3.buildInputField(value);
|
313 | });
|
314 | };
|
315 |
|
316 | _proto._makeInterfaceDef = function _makeInterfaceDef(def) {
|
317 | var _this4 = this;
|
318 |
|
319 | return new GraphQLInterfaceType({
|
320 | name: def.name.value,
|
321 | description: getDescription(def, this._options),
|
322 | fields: function fields() {
|
323 | return _this4._makeFieldDefMap(def);
|
324 | },
|
325 | astNode: def
|
326 | });
|
327 | };
|
328 |
|
329 | _proto._makeEnumDef = function _makeEnumDef(def) {
|
330 | return new GraphQLEnumType({
|
331 | name: def.name.value,
|
332 | description: getDescription(def, this._options),
|
333 | values: this._makeValueDefMap(def),
|
334 | astNode: def
|
335 | });
|
336 | };
|
337 |
|
338 | _proto._makeValueDefMap = function _makeValueDefMap(def) {
|
339 | var _this5 = this;
|
340 |
|
341 | return def.values ? keyValMap(def.values, function (enumValue) {
|
342 | return enumValue.name.value;
|
343 | }, function (enumValue) {
|
344 | return _this5.buildEnumValue(enumValue);
|
345 | }) : {};
|
346 | };
|
347 |
|
348 | _proto._makeUnionDef = function _makeUnionDef(def) {
|
349 | var _this6 = this;
|
350 |
|
351 | var types = def.types;
|
352 | return new GraphQLUnionType({
|
353 | name: def.name.value,
|
354 | description: getDescription(def, this._options),
|
355 |
|
356 |
|
357 |
|
358 | types: types ? function () {
|
359 | return types.map(function (ref) {
|
360 | return _this6.buildType(ref);
|
361 | });
|
362 | } : [],
|
363 | astNode: def
|
364 | });
|
365 | };
|
366 |
|
367 | _proto._makeScalarDef = function _makeScalarDef(def) {
|
368 | return new GraphQLScalarType({
|
369 | name: def.name.value,
|
370 | description: getDescription(def, this._options),
|
371 | astNode: def,
|
372 | serialize: function serialize(value) {
|
373 | return value;
|
374 | }
|
375 | });
|
376 | };
|
377 |
|
378 | _proto._makeInputObjectDef = function _makeInputObjectDef(def) {
|
379 | var _this7 = this;
|
380 |
|
381 | return new GraphQLInputObjectType({
|
382 | name: def.name.value,
|
383 | description: getDescription(def, this._options),
|
384 | fields: function fields() {
|
385 | return def.fields ? _this7._makeInputValues(def.fields) : {};
|
386 | },
|
387 | astNode: def
|
388 | });
|
389 | };
|
390 |
|
391 | return ASTDefinitionBuilder;
|
392 | }();
|
393 |
|
394 |
|
395 |
|
396 |
|
397 |
|
398 | function getDeprecationReason(node) {
|
399 | var deprecated = getDirectiveValues(GraphQLDeprecatedDirective, node);
|
400 | return deprecated && deprecated.reason;
|
401 | }
|
402 |
|
403 |
|
404 |
|
405 |
|
406 |
|
407 |
|
408 |
|
409 |
|
410 |
|
411 |
|
412 |
|
413 |
|
414 | export function getDescription(node, options) {
|
415 | if (node.description) {
|
416 | return node.description.value;
|
417 | }
|
418 |
|
419 | if (options && options.commentDescriptions) {
|
420 | var rawValue = getLeadingCommentBlock(node);
|
421 |
|
422 | if (rawValue !== undefined) {
|
423 | return blockStringValue('\n' + rawValue);
|
424 | }
|
425 | }
|
426 | }
|
427 |
|
428 | function getLeadingCommentBlock(node) {
|
429 | var loc = node.loc;
|
430 |
|
431 | if (!loc) {
|
432 | return;
|
433 | }
|
434 |
|
435 | var comments = [];
|
436 | var token = loc.startToken.prev;
|
437 |
|
438 | while (token && token.kind === TokenKind.COMMENT && token.next && token.prev && token.line + 1 === token.next.line && token.line !== token.prev.line) {
|
439 | var value = String(token.value);
|
440 | comments.push(value);
|
441 | token = token.prev;
|
442 | }
|
443 |
|
444 | return comments.reverse().join('\n');
|
445 | }
|
446 |
|
447 |
|
448 |
|
449 |
|
450 |
|
451 |
|
452 | export function buildSchema(source, options) {
|
453 | return buildASTSchema(parse(source, options), options);
|
454 | } |
\ | No newline at end of file |