buildSchemaFromSDL.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. Object.defineProperty(exports, "__esModule", { value: true });
  6. exports.addResolversToSchema = exports.buildSchemaFromSDL = exports.modulesFromSDL = void 0;
  7. const graphql_1 = require("graphql");
  8. const validate_1 = require("graphql/validation/validate");
  9. const graphql_2 = require("../utilities/graphql");
  10. const GraphQLSchemaValidationError_1 = require("./GraphQLSchemaValidationError");
  11. const specifiedRules_1 = require("graphql/validation/specifiedRules");
  12. const flat_1 = __importDefault(require("core-js-pure/features/array/flat"));
  13. const validation_1 = require("graphql/validation");
  14. const mapValues_1 = require("../utilities/mapValues");
  15. const skippedSDLRules = [
  16. validation_1.KnownTypeNamesRule,
  17. validation_1.UniqueDirectivesPerLocationRule,
  18. ];
  19. try {
  20. const PossibleTypeExtensions = require("graphql/validation/rules/PossibleTypeExtensions").PossibleTypeExtensions;
  21. if (PossibleTypeExtensions) {
  22. skippedSDLRules.push(PossibleTypeExtensions);
  23. }
  24. }
  25. catch (e) {
  26. }
  27. const sdlRules = specifiedRules_1.specifiedSDLRules.filter((rule) => !skippedSDLRules.includes(rule));
  28. function modulesFromSDL(modulesOrSDL) {
  29. if (Array.isArray(modulesOrSDL)) {
  30. return modulesOrSDL.map((moduleOrSDL) => {
  31. if ((0, graphql_2.isNode)(moduleOrSDL) && (0, graphql_2.isDocumentNode)(moduleOrSDL)) {
  32. return { typeDefs: moduleOrSDL };
  33. }
  34. else {
  35. return moduleOrSDL;
  36. }
  37. });
  38. }
  39. else {
  40. return [{ typeDefs: modulesOrSDL }];
  41. }
  42. }
  43. exports.modulesFromSDL = modulesFromSDL;
  44. function buildSchemaFromSDL(modulesOrSDL, schemaToExtend) {
  45. const modules = modulesFromSDL(modulesOrSDL);
  46. const documentAST = (0, graphql_1.concatAST)(modules.map((module) => module.typeDefs));
  47. const errors = (0, validate_1.validateSDL)(documentAST, schemaToExtend, sdlRules);
  48. if (errors.length > 0) {
  49. throw new GraphQLSchemaValidationError_1.GraphQLSchemaValidationError(errors);
  50. }
  51. const definitionsMap = Object.create(null);
  52. const extensionsMap = Object.create(null);
  53. const directiveDefinitions = [];
  54. const schemaDefinitions = [];
  55. const schemaExtensions = [];
  56. const schemaDirectives = [];
  57. for (const definition of documentAST.definitions) {
  58. if ((0, graphql_1.isTypeDefinitionNode)(definition)) {
  59. const typeName = definition.name.value;
  60. if (definitionsMap[typeName]) {
  61. definitionsMap[typeName].push(definition);
  62. }
  63. else {
  64. definitionsMap[typeName] = [definition];
  65. }
  66. }
  67. else if ((0, graphql_1.isTypeExtensionNode)(definition)) {
  68. const typeName = definition.name.value;
  69. if (extensionsMap[typeName]) {
  70. extensionsMap[typeName].push(definition);
  71. }
  72. else {
  73. extensionsMap[typeName] = [definition];
  74. }
  75. }
  76. else if (definition.kind === graphql_1.Kind.DIRECTIVE_DEFINITION) {
  77. directiveDefinitions.push(definition);
  78. }
  79. else if (definition.kind === graphql_1.Kind.SCHEMA_DEFINITION) {
  80. schemaDefinitions.push(definition);
  81. schemaDirectives.push(...(definition.directives ? definition.directives : []));
  82. }
  83. else if (definition.kind === graphql_1.Kind.SCHEMA_EXTENSION) {
  84. schemaExtensions.push(definition);
  85. }
  86. }
  87. let schema = schemaToExtend
  88. ? schemaToExtend
  89. : new graphql_1.GraphQLSchema({
  90. query: undefined,
  91. });
  92. const missingTypeDefinitions = [];
  93. for (const [extendedTypeName, extensions] of Object.entries(extensionsMap)) {
  94. if (!definitionsMap[extendedTypeName]) {
  95. const extension = extensions[0];
  96. const kind = extension.kind;
  97. const definition = {
  98. kind: extKindToDefKind[kind],
  99. name: extension.name,
  100. };
  101. missingTypeDefinitions.push(definition);
  102. }
  103. }
  104. schema = (0, graphql_1.extendSchema)(schema, {
  105. kind: graphql_1.Kind.DOCUMENT,
  106. definitions: [
  107. ...(0, flat_1.default)(Object.values(definitionsMap)),
  108. ...missingTypeDefinitions,
  109. ...directiveDefinitions,
  110. ],
  111. }, {
  112. assumeValidSDL: true,
  113. });
  114. schema = (0, graphql_1.extendSchema)(schema, {
  115. kind: graphql_1.Kind.DOCUMENT,
  116. definitions: (0, flat_1.default)(Object.values(extensionsMap)),
  117. }, {
  118. assumeValidSDL: true,
  119. });
  120. let operationTypeMap;
  121. if (schemaDefinitions.length > 0 || schemaExtensions.length > 0) {
  122. operationTypeMap = {};
  123. const operationTypes = (0, flat_1.default)([...schemaDefinitions, ...schemaExtensions]
  124. .map((node) => node.operationTypes)
  125. .filter(isNotNullOrUndefined));
  126. for (const { operation, type } of operationTypes) {
  127. operationTypeMap[operation] = type.name.value;
  128. }
  129. }
  130. else {
  131. operationTypeMap = {
  132. query: "Query",
  133. mutation: "Mutation",
  134. subscription: "Subscription",
  135. };
  136. }
  137. schema = new graphql_1.GraphQLSchema(Object.assign(Object.assign(Object.assign({}, schema.toConfig()), (0, mapValues_1.mapValues)(operationTypeMap, (typeName) => typeName
  138. ? schema.getType(typeName)
  139. : undefined)), { astNode: {
  140. kind: graphql_1.Kind.SCHEMA_DEFINITION,
  141. directives: schemaDirectives,
  142. operationTypes: [],
  143. } }));
  144. for (const module of modules) {
  145. if (!module.resolvers)
  146. continue;
  147. addResolversToSchema(schema, module.resolvers);
  148. }
  149. return schema;
  150. }
  151. exports.buildSchemaFromSDL = buildSchemaFromSDL;
  152. const extKindToDefKind = {
  153. [graphql_1.Kind.SCALAR_TYPE_EXTENSION]: graphql_1.Kind.SCALAR_TYPE_DEFINITION,
  154. [graphql_1.Kind.OBJECT_TYPE_EXTENSION]: graphql_1.Kind.OBJECT_TYPE_DEFINITION,
  155. [graphql_1.Kind.INTERFACE_TYPE_EXTENSION]: graphql_1.Kind.INTERFACE_TYPE_DEFINITION,
  156. [graphql_1.Kind.UNION_TYPE_EXTENSION]: graphql_1.Kind.UNION_TYPE_DEFINITION,
  157. [graphql_1.Kind.ENUM_TYPE_EXTENSION]: graphql_1.Kind.ENUM_TYPE_DEFINITION,
  158. [graphql_1.Kind.INPUT_OBJECT_TYPE_EXTENSION]: graphql_1.Kind.INPUT_OBJECT_TYPE_DEFINITION,
  159. };
  160. function addResolversToSchema(schema, resolvers) {
  161. for (const [typeName, fieldConfigs] of Object.entries(resolvers)) {
  162. const type = schema.getType(typeName);
  163. if ((0, graphql_1.isAbstractType)(type)) {
  164. for (const [fieldName, fieldConfig] of Object.entries(fieldConfigs)) {
  165. if (fieldName.startsWith("__")) {
  166. type[fieldName.substring(2)] = fieldConfig;
  167. }
  168. }
  169. }
  170. if ((0, graphql_1.isScalarType)(type)) {
  171. for (const fn in fieldConfigs) {
  172. type[fn] = fieldConfigs[fn];
  173. }
  174. }
  175. if ((0, graphql_1.isEnumType)(type)) {
  176. const values = type.getValues();
  177. const newValues = {};
  178. values.forEach((value) => {
  179. let newValue = fieldConfigs[value.name];
  180. if (newValue === undefined) {
  181. newValue = value.name;
  182. }
  183. newValues[value.name] = {
  184. value: newValue,
  185. deprecationReason: value.deprecationReason,
  186. description: value.description,
  187. astNode: value.astNode,
  188. extensions: undefined,
  189. };
  190. });
  191. Object.assign(type, new graphql_1.GraphQLEnumType(Object.assign(Object.assign({}, type.toConfig()), { values: newValues })));
  192. }
  193. if (!(0, graphql_1.isObjectType)(type))
  194. continue;
  195. const fieldMap = type.getFields();
  196. for (const [fieldName, fieldConfig] of Object.entries(fieldConfigs)) {
  197. if (fieldName.startsWith("__")) {
  198. type[fieldName.substring(2)] = fieldConfig;
  199. continue;
  200. }
  201. const field = fieldMap[fieldName];
  202. if (!field)
  203. continue;
  204. if (typeof fieldConfig === "function") {
  205. field.resolve = fieldConfig;
  206. }
  207. else {
  208. field.resolve = fieldConfig.resolve;
  209. }
  210. }
  211. }
  212. }
  213. exports.addResolversToSchema = addResolversToSchema;
  214. function isNotNullOrUndefined(value) {
  215. return value !== null && typeof value !== "undefined";
  216. }
  217. //# sourceMappingURL=buildSchemaFromSDL.js.map