buildServiceDefinition.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.buildServiceDefinition = void 0;
  4. const graphql_1 = require("graphql");
  5. const graphql_2 = require("./utilities/graphql");
  6. const predicates_1 = require("./utilities/predicates");
  7. function flattened(arr) {
  8. return new Array().concat(...arr);
  9. }
  10. function buildServiceDefinition(modules) {
  11. const errors = [];
  12. const typeDefinitionsMap = Object.create(null);
  13. const typeExtensionsMap = Object.create(null);
  14. const directivesMap = Object.create(null);
  15. const schemaDefinitions = [];
  16. const schemaExtensions = [];
  17. for (let module of modules) {
  18. if ((0, graphql_2.isNode)(module) && (0, graphql_2.isDocumentNode)(module)) {
  19. module = { typeDefs: module };
  20. }
  21. for (const definition of module.typeDefs.definitions) {
  22. if ((0, graphql_1.isTypeDefinitionNode)(definition)) {
  23. const typeName = definition.name.value;
  24. if (typeDefinitionsMap[typeName]) {
  25. typeDefinitionsMap[typeName].push(definition);
  26. }
  27. else {
  28. typeDefinitionsMap[typeName] = [definition];
  29. }
  30. }
  31. else if ((0, graphql_1.isTypeExtensionNode)(definition)) {
  32. const typeName = definition.name.value;
  33. if (typeExtensionsMap[typeName]) {
  34. typeExtensionsMap[typeName].push(definition);
  35. }
  36. else {
  37. typeExtensionsMap[typeName] = [definition];
  38. }
  39. }
  40. else if (definition.kind === graphql_1.Kind.DIRECTIVE_DEFINITION) {
  41. const directiveName = definition.name.value;
  42. if (directivesMap[directiveName]) {
  43. directivesMap[directiveName].push(definition);
  44. }
  45. else {
  46. directivesMap[directiveName] = [definition];
  47. }
  48. }
  49. else if (definition.kind === graphql_1.Kind.SCHEMA_DEFINITION) {
  50. schemaDefinitions.push(definition);
  51. }
  52. else if (definition.kind === graphql_1.Kind.SCHEMA_EXTENSION) {
  53. schemaExtensions.push(definition);
  54. }
  55. }
  56. }
  57. for (const [typeName, typeDefinitions] of Object.entries(typeDefinitionsMap)) {
  58. if (typeDefinitions.length > 1) {
  59. errors.push(new graphql_1.GraphQLError(`Type "${typeName}" was defined more than once.`, typeDefinitions));
  60. }
  61. }
  62. for (const [directiveName, directives] of Object.entries(directivesMap)) {
  63. if (directives.length > 1) {
  64. errors.push(new graphql_1.GraphQLError(`Directive "${directiveName}" was defined more than once.`, directives));
  65. }
  66. }
  67. let operationTypeMap;
  68. if (schemaDefinitions.length > 0 || schemaExtensions.length > 0) {
  69. operationTypeMap = {};
  70. const schemaDefinition = schemaDefinitions[schemaDefinitions.length - 1];
  71. const operationTypes = flattened([schemaDefinition, ...schemaExtensions]
  72. .map((node) => node.operationTypes)
  73. .filter(predicates_1.isNotNullOrUndefined));
  74. for (const operationType of operationTypes) {
  75. const typeName = operationType.type.name.value;
  76. const operation = operationType.operation;
  77. if (operationTypeMap[operation]) {
  78. throw new graphql_1.GraphQLError(`Must provide only one ${operation} type in schema.`, [schemaDefinition]);
  79. }
  80. if (!(typeDefinitionsMap[typeName] || typeExtensionsMap[typeName])) {
  81. throw new graphql_1.GraphQLError(`Specified ${operation} type "${typeName}" not found in document.`, [schemaDefinition]);
  82. }
  83. operationTypeMap[operation] = typeName;
  84. }
  85. }
  86. else {
  87. operationTypeMap = {
  88. query: "Query",
  89. mutation: "Mutation",
  90. subscription: "Subscription",
  91. };
  92. }
  93. for (const [typeName, typeExtensions] of Object.entries(typeExtensionsMap)) {
  94. if (!typeDefinitionsMap[typeName]) {
  95. if (Object.values(operationTypeMap).includes(typeName)) {
  96. typeDefinitionsMap[typeName] = [
  97. {
  98. kind: graphql_1.Kind.OBJECT_TYPE_DEFINITION,
  99. name: {
  100. kind: graphql_1.Kind.NAME,
  101. value: typeName,
  102. },
  103. },
  104. ];
  105. }
  106. else {
  107. errors.push(new graphql_1.GraphQLError(`Cannot extend type "${typeName}" because it does not exist in the existing schema.`, typeExtensions));
  108. }
  109. }
  110. }
  111. if (errors.length > 0) {
  112. return { errors };
  113. }
  114. try {
  115. const typeDefinitions = flattened(Object.values(typeDefinitionsMap));
  116. const directives = flattened(Object.values(directivesMap));
  117. let schema = (0, graphql_1.buildASTSchema)({
  118. kind: graphql_1.Kind.DOCUMENT,
  119. definitions: [...typeDefinitions, ...directives],
  120. });
  121. const typeExtensions = flattened(Object.values(typeExtensionsMap));
  122. if (typeExtensions.length > 0) {
  123. schema = (0, graphql_1.extendSchema)(schema, {
  124. kind: graphql_1.Kind.DOCUMENT,
  125. definitions: typeExtensions,
  126. });
  127. }
  128. for (const module of modules) {
  129. if ("kind" in module || !module.resolvers)
  130. continue;
  131. addResolversToSchema(schema, module.resolvers);
  132. }
  133. return { schema };
  134. }
  135. catch (error) {
  136. return { errors: [error] };
  137. }
  138. }
  139. exports.buildServiceDefinition = buildServiceDefinition;
  140. function addResolversToSchema(schema, resolvers) {
  141. for (const [typeName, fieldConfigs] of Object.entries(resolvers)) {
  142. const type = schema.getType(typeName);
  143. if (!(0, graphql_1.isObjectType)(type))
  144. continue;
  145. const fieldMap = type.getFields();
  146. for (const [fieldName, fieldConfig] of Object.entries(fieldConfigs)) {
  147. if (fieldName.startsWith("__")) {
  148. type[fieldName.substring(2)] = fieldConfig;
  149. continue;
  150. }
  151. const field = fieldMap[fieldName];
  152. if (!field)
  153. continue;
  154. if (typeof fieldConfig === "function") {
  155. field.resolve = fieldConfig;
  156. }
  157. else {
  158. if (fieldConfig.resolve) {
  159. field.resolve = fieldConfig.resolve;
  160. }
  161. if (fieldConfig.subscribe) {
  162. field.subscribe = fieldConfig.subscribe;
  163. }
  164. }
  165. }
  166. }
  167. }
  168. //# sourceMappingURL=buildServiceDefinition.js.map