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