buildASTSchema.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.buildASTSchema = buildASTSchema;
  6. exports.getDescription = getDescription;
  7. exports.buildSchema = buildSchema;
  8. exports.ASTDefinitionBuilder = void 0;
  9. var _objectValues = _interopRequireDefault(require("../polyfills/objectValues"));
  10. var _keyMap = _interopRequireDefault(require("../jsutils/keyMap"));
  11. var _inspect = _interopRequireDefault(require("../jsutils/inspect"));
  12. var _invariant = _interopRequireDefault(require("../jsutils/invariant"));
  13. var _devAssert = _interopRequireDefault(require("../jsutils/devAssert"));
  14. var _keyValMap = _interopRequireDefault(require("../jsutils/keyValMap"));
  15. var _kinds = require("../language/kinds");
  16. var _tokenKind = require("../language/tokenKind");
  17. var _parser = require("../language/parser");
  18. var _predicates = require("../language/predicates");
  19. var _blockString = require("../language/blockString");
  20. var _validate = require("../validation/validate");
  21. var _values = require("../execution/values");
  22. var _scalars = require("../type/scalars");
  23. var _introspection = require("../type/introspection");
  24. var _schema = require("../type/schema");
  25. var _directives = require("../type/directives");
  26. var _definition = require("../type/definition");
  27. var _valueFromAST = require("./valueFromAST");
  28. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  29. /**
  30. * This takes the ast of a schema document produced by the parse function in
  31. * src/language/parser.js.
  32. *
  33. * If no schema definition is provided, then it will look for types named Query
  34. * and Mutation.
  35. *
  36. * Given that AST it constructs a GraphQLSchema. The resulting schema
  37. * has no resolve methods, so execution will use default resolvers.
  38. *
  39. * Accepts options as a second argument:
  40. *
  41. * - commentDescriptions:
  42. * Provide true to use preceding comments as the description.
  43. *
  44. */
  45. function buildASTSchema(documentAST, options) {
  46. documentAST && documentAST.kind === _kinds.Kind.DOCUMENT || (0, _devAssert.default)(0, 'Must provide valid Document AST');
  47. if (!options || !(options.assumeValid || options.assumeValidSDL)) {
  48. (0, _validate.assertValidSDL)(documentAST);
  49. }
  50. var schemaDef;
  51. var typeDefs = [];
  52. var directiveDefs = [];
  53. for (var _i2 = 0, _documentAST$definiti2 = documentAST.definitions; _i2 < _documentAST$definiti2.length; _i2++) {
  54. var def = _documentAST$definiti2[_i2];
  55. if (def.kind === _kinds.Kind.SCHEMA_DEFINITION) {
  56. schemaDef = def;
  57. } else if ((0, _predicates.isTypeDefinitionNode)(def)) {
  58. typeDefs.push(def);
  59. } else if (def.kind === _kinds.Kind.DIRECTIVE_DEFINITION) {
  60. directiveDefs.push(def);
  61. }
  62. }
  63. var astBuilder = new ASTDefinitionBuilder(options, function (typeName) {
  64. var type = typeMap[typeName];
  65. if (type === undefined) {
  66. throw new Error("Type \"".concat(typeName, "\" not found in document."));
  67. }
  68. return type;
  69. });
  70. var typeMap = keyByNameNode(typeDefs, function (node) {
  71. return astBuilder.buildType(node);
  72. });
  73. var operationTypes = schemaDef ? getOperationTypes(schemaDef) : {
  74. query: 'Query',
  75. mutation: 'Mutation',
  76. subscription: 'Subscription'
  77. };
  78. var directives = directiveDefs.map(function (def) {
  79. return astBuilder.buildDirective(def);
  80. }); // If specified directives were not explicitly declared, add them.
  81. if (!directives.some(function (directive) {
  82. return directive.name === 'skip';
  83. })) {
  84. directives.push(_directives.GraphQLSkipDirective);
  85. }
  86. if (!directives.some(function (directive) {
  87. return directive.name === 'include';
  88. })) {
  89. directives.push(_directives.GraphQLIncludeDirective);
  90. }
  91. if (!directives.some(function (directive) {
  92. return directive.name === 'deprecated';
  93. })) {
  94. directives.push(_directives.GraphQLDeprecatedDirective);
  95. }
  96. return new _schema.GraphQLSchema({
  97. // Note: While this could make early assertions to get the correctly
  98. // typed values below, that would throw immediately while type system
  99. // validation with validateSchema() will produce more actionable results.
  100. query: operationTypes.query ? typeMap[operationTypes.query] : null,
  101. mutation: operationTypes.mutation ? typeMap[operationTypes.mutation] : null,
  102. subscription: operationTypes.subscription ? typeMap[operationTypes.subscription] : null,
  103. types: (0, _objectValues.default)(typeMap),
  104. directives: directives,
  105. astNode: schemaDef,
  106. assumeValid: options && options.assumeValid,
  107. allowedLegacyNames: options && options.allowedLegacyNames
  108. });
  109. function getOperationTypes(schema) {
  110. var opTypes = {};
  111. for (var _i4 = 0, _schema$operationType2 = schema.operationTypes; _i4 < _schema$operationType2.length; _i4++) {
  112. var operationType = _schema$operationType2[_i4];
  113. opTypes[operationType.operation] = operationType.type.name.value;
  114. }
  115. return opTypes;
  116. }
  117. }
  118. var stdTypeMap = (0, _keyMap.default)(_scalars.specifiedScalarTypes.concat(_introspection.introspectionTypes), function (type) {
  119. return type.name;
  120. });
  121. var ASTDefinitionBuilder =
  122. /*#__PURE__*/
  123. function () {
  124. function ASTDefinitionBuilder(options, resolveType) {
  125. this._options = options;
  126. this._resolveType = resolveType;
  127. }
  128. var _proto = ASTDefinitionBuilder.prototype;
  129. _proto.getNamedType = function getNamedType(node) {
  130. var name = node.name.value;
  131. return stdTypeMap[name] || this._resolveType(name);
  132. };
  133. _proto.getWrappedType = function getWrappedType(node) {
  134. if (node.kind === _kinds.Kind.LIST_TYPE) {
  135. return new _definition.GraphQLList(this.getWrappedType(node.type));
  136. }
  137. if (node.kind === _kinds.Kind.NON_NULL_TYPE) {
  138. return new _definition.GraphQLNonNull(this.getWrappedType(node.type));
  139. }
  140. return this.getNamedType(node);
  141. };
  142. _proto.buildDirective = function buildDirective(directive) {
  143. var _this = this;
  144. var locations = directive.locations.map(function (_ref) {
  145. var value = _ref.value;
  146. return value;
  147. });
  148. return new _directives.GraphQLDirective({
  149. name: directive.name.value,
  150. description: getDescription(directive, this._options),
  151. locations: locations,
  152. isRepeatable: directive.repeatable,
  153. args: keyByNameNode(directive.arguments || [], function (arg) {
  154. return _this.buildArg(arg);
  155. }),
  156. astNode: directive
  157. });
  158. };
  159. _proto.buildField = function buildField(field) {
  160. var _this2 = this;
  161. return {
  162. // Note: While this could make assertions to get the correctly typed
  163. // value, that would throw immediately while type system validation
  164. // with validateSchema() will produce more actionable results.
  165. type: this.getWrappedType(field.type),
  166. description: getDescription(field, this._options),
  167. args: keyByNameNode(field.arguments || [], function (arg) {
  168. return _this2.buildArg(arg);
  169. }),
  170. deprecationReason: getDeprecationReason(field),
  171. astNode: field
  172. };
  173. };
  174. _proto.buildArg = function buildArg(value) {
  175. // Note: While this could make assertions to get the correctly typed
  176. // value, that would throw immediately while type system validation
  177. // with validateSchema() will produce more actionable results.
  178. var type = this.getWrappedType(value.type);
  179. return {
  180. type: type,
  181. description: getDescription(value, this._options),
  182. defaultValue: (0, _valueFromAST.valueFromAST)(value.defaultValue, type),
  183. astNode: value
  184. };
  185. };
  186. _proto.buildInputField = function buildInputField(value) {
  187. // Note: While this could make assertions to get the correctly typed
  188. // value, that would throw immediately while type system validation
  189. // with validateSchema() will produce more actionable results.
  190. var type = this.getWrappedType(value.type);
  191. return {
  192. type: type,
  193. description: getDescription(value, this._options),
  194. defaultValue: (0, _valueFromAST.valueFromAST)(value.defaultValue, type),
  195. astNode: value
  196. };
  197. };
  198. _proto.buildEnumValue = function buildEnumValue(value) {
  199. return {
  200. description: getDescription(value, this._options),
  201. deprecationReason: getDeprecationReason(value),
  202. astNode: value
  203. };
  204. };
  205. _proto.buildType = function buildType(astNode) {
  206. var name = astNode.name.value;
  207. if (stdTypeMap[name]) {
  208. return stdTypeMap[name];
  209. }
  210. switch (astNode.kind) {
  211. case _kinds.Kind.OBJECT_TYPE_DEFINITION:
  212. return this._makeTypeDef(astNode);
  213. case _kinds.Kind.INTERFACE_TYPE_DEFINITION:
  214. return this._makeInterfaceDef(astNode);
  215. case _kinds.Kind.ENUM_TYPE_DEFINITION:
  216. return this._makeEnumDef(astNode);
  217. case _kinds.Kind.UNION_TYPE_DEFINITION:
  218. return this._makeUnionDef(astNode);
  219. case _kinds.Kind.SCALAR_TYPE_DEFINITION:
  220. return this._makeScalarDef(astNode);
  221. case _kinds.Kind.INPUT_OBJECT_TYPE_DEFINITION:
  222. return this._makeInputObjectDef(astNode);
  223. } // Not reachable. All possible type definition nodes have been considered.
  224. /* istanbul ignore next */
  225. (0, _invariant.default)(false, 'Unexpected type definition node: ' + (0, _inspect.default)(astNode));
  226. };
  227. _proto._makeTypeDef = function _makeTypeDef(astNode) {
  228. var _this3 = this;
  229. var interfaceNodes = astNode.interfaces;
  230. var fieldNodes = astNode.fields; // Note: While this could make assertions to get the correctly typed
  231. // values below, that would throw immediately while type system
  232. // validation with validateSchema() will produce more actionable results.
  233. var interfaces = interfaceNodes && interfaceNodes.length > 0 ? function () {
  234. return interfaceNodes.map(function (ref) {
  235. return _this3.getNamedType(ref);
  236. });
  237. } : [];
  238. var fields = fieldNodes && fieldNodes.length > 0 ? function () {
  239. return keyByNameNode(fieldNodes, function (field) {
  240. return _this3.buildField(field);
  241. });
  242. } : Object.create(null);
  243. return new _definition.GraphQLObjectType({
  244. name: astNode.name.value,
  245. description: getDescription(astNode, this._options),
  246. interfaces: interfaces,
  247. fields: fields,
  248. astNode: astNode
  249. });
  250. };
  251. _proto._makeInterfaceDef = function _makeInterfaceDef(astNode) {
  252. var _this4 = this;
  253. var fieldNodes = astNode.fields;
  254. var fields = fieldNodes && fieldNodes.length > 0 ? function () {
  255. return keyByNameNode(fieldNodes, function (field) {
  256. return _this4.buildField(field);
  257. });
  258. } : Object.create(null);
  259. return new _definition.GraphQLInterfaceType({
  260. name: astNode.name.value,
  261. description: getDescription(astNode, this._options),
  262. fields: fields,
  263. astNode: astNode
  264. });
  265. };
  266. _proto._makeEnumDef = function _makeEnumDef(astNode) {
  267. var _this5 = this;
  268. var valueNodes = astNode.values || [];
  269. return new _definition.GraphQLEnumType({
  270. name: astNode.name.value,
  271. description: getDescription(astNode, this._options),
  272. values: keyByNameNode(valueNodes, function (value) {
  273. return _this5.buildEnumValue(value);
  274. }),
  275. astNode: astNode
  276. });
  277. };
  278. _proto._makeUnionDef = function _makeUnionDef(astNode) {
  279. var _this6 = this;
  280. var typeNodes = astNode.types; // Note: While this could make assertions to get the correctly typed
  281. // values below, that would throw immediately while type system
  282. // validation with validateSchema() will produce more actionable results.
  283. var types = typeNodes && typeNodes.length > 0 ? function () {
  284. return typeNodes.map(function (ref) {
  285. return _this6.getNamedType(ref);
  286. });
  287. } : [];
  288. return new _definition.GraphQLUnionType({
  289. name: astNode.name.value,
  290. description: getDescription(astNode, this._options),
  291. types: types,
  292. astNode: astNode
  293. });
  294. };
  295. _proto._makeScalarDef = function _makeScalarDef(astNode) {
  296. return new _definition.GraphQLScalarType({
  297. name: astNode.name.value,
  298. description: getDescription(astNode, this._options),
  299. astNode: astNode
  300. });
  301. };
  302. _proto._makeInputObjectDef = function _makeInputObjectDef(def) {
  303. var _this7 = this;
  304. var fields = def.fields;
  305. return new _definition.GraphQLInputObjectType({
  306. name: def.name.value,
  307. description: getDescription(def, this._options),
  308. fields: fields ? function () {
  309. return keyByNameNode(fields, function (field) {
  310. return _this7.buildInputField(field);
  311. });
  312. } : Object.create(null),
  313. astNode: def
  314. });
  315. };
  316. return ASTDefinitionBuilder;
  317. }();
  318. exports.ASTDefinitionBuilder = ASTDefinitionBuilder;
  319. function keyByNameNode(list, valFn) {
  320. return (0, _keyValMap.default)(list, function (_ref2) {
  321. var name = _ref2.name;
  322. return name.value;
  323. }, valFn);
  324. }
  325. /**
  326. * Given a field or enum value node, returns the string value for the
  327. * deprecation reason.
  328. */
  329. function getDeprecationReason(node) {
  330. var deprecated = (0, _values.getDirectiveValues)(_directives.GraphQLDeprecatedDirective, node);
  331. return deprecated && deprecated.reason;
  332. }
  333. /**
  334. * Given an ast node, returns its string description.
  335. * @deprecated: provided to ease adoption and will be removed in v16.
  336. *
  337. * Accepts options as a second argument:
  338. *
  339. * - commentDescriptions:
  340. * Provide true to use preceding comments as the description.
  341. *
  342. */
  343. function getDescription(node, options) {
  344. if (node.description) {
  345. return node.description.value;
  346. }
  347. if (options && options.commentDescriptions) {
  348. var rawValue = getLeadingCommentBlock(node);
  349. if (rawValue !== undefined) {
  350. return (0, _blockString.dedentBlockStringValue)('\n' + rawValue);
  351. }
  352. }
  353. }
  354. function getLeadingCommentBlock(node) {
  355. var loc = node.loc;
  356. if (!loc) {
  357. return;
  358. }
  359. var comments = [];
  360. var token = loc.startToken.prev;
  361. while (token && token.kind === _tokenKind.TokenKind.COMMENT && token.next && token.prev && token.line + 1 === token.next.line && token.line !== token.prev.line) {
  362. var value = String(token.value);
  363. comments.push(value);
  364. token = token.prev;
  365. }
  366. return comments.reverse().join('\n');
  367. }
  368. /**
  369. * A helper function to build a GraphQLSchema directly from a source
  370. * document.
  371. */
  372. function buildSchema(source, options) {
  373. return buildASTSchema((0, _parser.parse)(source, options), options);
  374. }