UNPKG

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