mergeSchemas.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. var __assign = (this && this.__assign) || function () {
  2. __assign = Object.assign || function(t) {
  3. for (var s, i = 1, n = arguments.length; i < n; i++) {
  4. s = arguments[i];
  5. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
  6. t[p] = s[p];
  7. }
  8. return t;
  9. };
  10. return __assign.apply(this, arguments);
  11. };
  12. var __spreadArrays = (this && this.__spreadArrays) || function () {
  13. for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
  14. for (var r = Array(s), k = 0, i = 0; i < il; i++)
  15. for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
  16. r[k] = a[j];
  17. return r;
  18. };
  19. Object.defineProperty(exports, "__esModule", { value: true });
  20. var graphql_1 = require("graphql");
  21. var makeExecutableSchema_1 = require("../makeExecutableSchema");
  22. var schemaRecreation_1 = require("./schemaRecreation");
  23. var delegateToSchema_1 = require("./delegateToSchema");
  24. var typeFromAST_1 = require("./typeFromAST");
  25. var transforms_1 = require("../transforms");
  26. var mergeDeep_1 = require("../mergeDeep");
  27. var schemaVisitor_1 = require("../schemaVisitor");
  28. function mergeSchemas(_a) {
  29. var schemas = _a.schemas, onTypeConflict = _a.onTypeConflict, resolvers = _a.resolvers, schemaDirectives = _a.schemaDirectives, inheritResolversFromInterfaces = _a.inheritResolversFromInterfaces, mergeDirectives = _a.mergeDirectives;
  30. return mergeSchemasImplementation({
  31. schemas: schemas,
  32. resolvers: resolvers,
  33. schemaDirectives: schemaDirectives,
  34. inheritResolversFromInterfaces: inheritResolversFromInterfaces,
  35. mergeDirectives: mergeDirectives,
  36. });
  37. }
  38. exports.default = mergeSchemas;
  39. function mergeSchemasImplementation(_a) {
  40. var schemas = _a.schemas, resolvers = _a.resolvers, schemaDirectives = _a.schemaDirectives, inheritResolversFromInterfaces = _a.inheritResolversFromInterfaces, mergeDirectives = _a.mergeDirectives;
  41. var allSchemas = [];
  42. var typeCandidates = {};
  43. var types = {};
  44. var extensions = [];
  45. var directives = [];
  46. var fragments = [];
  47. var resolveType = schemaRecreation_1.createResolveType(function (name) {
  48. if (types[name] === undefined) {
  49. throw new Error("Can't find type " + name + ".");
  50. }
  51. return types[name];
  52. });
  53. schemas.forEach(function (schema) {
  54. if (schema instanceof graphql_1.GraphQLSchema) {
  55. allSchemas.push(schema);
  56. var queryType_1 = schema.getQueryType();
  57. var mutationType_1 = schema.getMutationType();
  58. var subscriptionType_1 = schema.getSubscriptionType();
  59. if (queryType_1) {
  60. addTypeCandidate(typeCandidates, 'Query', {
  61. schema: schema,
  62. type: queryType_1,
  63. });
  64. }
  65. if (mutationType_1) {
  66. addTypeCandidate(typeCandidates, 'Mutation', {
  67. schema: schema,
  68. type: mutationType_1,
  69. });
  70. }
  71. if (subscriptionType_1) {
  72. addTypeCandidate(typeCandidates, 'Subscription', {
  73. schema: schema,
  74. type: subscriptionType_1,
  75. });
  76. }
  77. if (mergeDirectives) {
  78. var directiveInstances = schema.getDirectives();
  79. directiveInstances.forEach(function (directive) {
  80. directives.push(directive);
  81. });
  82. }
  83. var typeMap_1 = schema.getTypeMap();
  84. Object.keys(typeMap_1).forEach(function (typeName) {
  85. var type = typeMap_1[typeName];
  86. if (graphql_1.isNamedType(type) &&
  87. graphql_1.getNamedType(type).name.slice(0, 2) !== '__' &&
  88. type !== queryType_1 &&
  89. type !== mutationType_1 &&
  90. type !== subscriptionType_1) {
  91. addTypeCandidate(typeCandidates, type.name, {
  92. schema: schema,
  93. type: type,
  94. });
  95. }
  96. });
  97. }
  98. else if (typeof schema === 'string' ||
  99. (schema && schema.kind === graphql_1.Kind.DOCUMENT)) {
  100. var parsedSchemaDocument = typeof schema === 'string' ? graphql_1.parse(schema) : schema;
  101. parsedSchemaDocument.definitions.forEach(function (def) {
  102. var type = typeFromAST_1.default(def);
  103. if (type instanceof graphql_1.GraphQLDirective && mergeDirectives) {
  104. directives.push(type);
  105. }
  106. else if (type && !(type instanceof graphql_1.GraphQLDirective)) {
  107. addTypeCandidate(typeCandidates, type.name, {
  108. type: type,
  109. });
  110. }
  111. });
  112. var extensionsDocument = makeExecutableSchema_1.extractExtensionDefinitions(parsedSchemaDocument);
  113. if (extensionsDocument.definitions.length > 0) {
  114. extensions.push(extensionsDocument);
  115. }
  116. }
  117. else if (Array.isArray(schema)) {
  118. schema.forEach(function (type) {
  119. addTypeCandidate(typeCandidates, type.name, {
  120. type: type,
  121. });
  122. });
  123. }
  124. else {
  125. throw new Error("Invalid schema passed");
  126. }
  127. });
  128. var mergeInfo = createMergeInfo(allSchemas, fragments);
  129. if (!resolvers) {
  130. resolvers = {};
  131. }
  132. else if (typeof resolvers === 'function') {
  133. console.warn('Passing functions as resolver parameter is deprecated. Use `info.mergeInfo` instead.');
  134. resolvers = resolvers(mergeInfo);
  135. }
  136. else if (Array.isArray(resolvers)) {
  137. resolvers = resolvers.reduce(function (left, right) {
  138. if (typeof right === 'function') {
  139. console.warn('Passing functions as resolver parameter is deprecated. Use `info.mergeInfo` instead.');
  140. right = right(mergeInfo);
  141. }
  142. return mergeDeep_1.default(left, right);
  143. }, {});
  144. }
  145. var generatedResolvers = {};
  146. Object.keys(typeCandidates).forEach(function (typeName) {
  147. var resultType = defaultVisitType(typeName, typeCandidates[typeName]);
  148. if (resultType === null) {
  149. types[typeName] = null;
  150. }
  151. else {
  152. var type = void 0;
  153. var typeResolvers = void 0;
  154. if (graphql_1.isNamedType(resultType)) {
  155. type = resultType;
  156. }
  157. else if (resultType.type) {
  158. type = resultType.type;
  159. typeResolvers = resultType.resolvers;
  160. }
  161. else {
  162. throw new Error("Invalid visitType result for type " + typeName);
  163. }
  164. types[typeName] = schemaRecreation_1.recreateType(type, resolveType, false);
  165. if (typeResolvers) {
  166. generatedResolvers[typeName] = typeResolvers;
  167. }
  168. }
  169. });
  170. var mergedSchema = new graphql_1.GraphQLSchema({
  171. query: types.Query,
  172. mutation: types.Mutation,
  173. subscription: types.Subscription,
  174. types: Object.keys(types).map(function (key) { return types[key]; }),
  175. directives: directives.map(function (directive) { return schemaRecreation_1.recreateDirective(directive, resolveType); })
  176. });
  177. extensions.forEach(function (extension) {
  178. mergedSchema = graphql_1.extendSchema(mergedSchema, extension, {
  179. commentDescriptions: true,
  180. });
  181. });
  182. if (!resolvers) {
  183. resolvers = {};
  184. }
  185. else if (Array.isArray(resolvers)) {
  186. resolvers = resolvers.reduce(mergeDeep_1.default, {});
  187. }
  188. Object.keys(resolvers).forEach(function (typeName) {
  189. var type = resolvers[typeName];
  190. if (type instanceof graphql_1.GraphQLScalarType) {
  191. return;
  192. }
  193. Object.keys(type).forEach(function (fieldName) {
  194. var field = type[fieldName];
  195. if (field.fragment) {
  196. fragments.push({
  197. field: fieldName,
  198. fragment: field.fragment,
  199. });
  200. }
  201. });
  202. });
  203. mergedSchema = makeExecutableSchema_1.addResolveFunctionsToSchema({
  204. schema: mergedSchema,
  205. resolvers: mergeDeep_1.default(generatedResolvers, resolvers),
  206. inheritResolversFromInterfaces: inheritResolversFromInterfaces
  207. });
  208. forEachField(mergedSchema, function (field) {
  209. if (field.resolve) {
  210. var fieldResolver_1 = field.resolve;
  211. field.resolve = function (parent, args, context, info) {
  212. var newInfo = __assign(__assign({}, info), { mergeInfo: mergeInfo });
  213. return fieldResolver_1(parent, args, context, newInfo);
  214. };
  215. }
  216. if (field.subscribe) {
  217. var fieldResolver_2 = field.subscribe;
  218. field.subscribe = function (parent, args, context, info) {
  219. var newInfo = __assign(__assign({}, info), { mergeInfo: mergeInfo });
  220. return fieldResolver_2(parent, args, context, newInfo);
  221. };
  222. }
  223. });
  224. if (schemaDirectives) {
  225. schemaVisitor_1.SchemaDirectiveVisitor.visitSchemaDirectives(mergedSchema, schemaDirectives);
  226. }
  227. return mergedSchema;
  228. }
  229. function createMergeInfo(allSchemas, fragments) {
  230. return {
  231. delegate: function (operation, fieldName, args, context, info, transforms) {
  232. console.warn('`mergeInfo.delegate` is deprecated. ' +
  233. 'Use `mergeInfo.delegateToSchema and pass explicit schema instances.');
  234. var schema = guessSchemaByRootField(allSchemas, operation, fieldName);
  235. var expandTransforms = new transforms_1.ExpandAbstractTypes(info.schema, schema);
  236. var fragmentTransform = new transforms_1.ReplaceFieldWithFragment(schema, fragments);
  237. return delegateToSchema_1.default({
  238. schema: schema,
  239. operation: operation,
  240. fieldName: fieldName,
  241. args: args,
  242. context: context,
  243. info: info,
  244. transforms: __spreadArrays((transforms || []), [
  245. expandTransforms,
  246. fragmentTransform,
  247. ]),
  248. });
  249. },
  250. delegateToSchema: function (options) {
  251. return delegateToSchema_1.default(__assign(__assign({}, options), { transforms: options.transforms }));
  252. },
  253. fragments: fragments
  254. };
  255. }
  256. function guessSchemaByRootField(schemas, operation, fieldName) {
  257. for (var _i = 0, schemas_1 = schemas; _i < schemas_1.length; _i++) {
  258. var schema = schemas_1[_i];
  259. var rootObject = void 0;
  260. if (operation === 'subscription') {
  261. rootObject = schema.getSubscriptionType();
  262. }
  263. else if (operation === 'mutation') {
  264. rootObject = schema.getMutationType();
  265. }
  266. else {
  267. rootObject = schema.getQueryType();
  268. }
  269. if (rootObject) {
  270. var fields = rootObject.getFields();
  271. if (fields[fieldName]) {
  272. return schema;
  273. }
  274. }
  275. }
  276. throw new Error("Could not find subschema with field `" + operation + "." + fieldName + "`");
  277. }
  278. function createDelegatingResolver(schema, operation, fieldName) {
  279. return function (root, args, context, info) {
  280. return info.mergeInfo.delegateToSchema({
  281. schema: schema,
  282. operation: operation,
  283. fieldName: fieldName,
  284. args: args,
  285. context: context,
  286. info: info,
  287. });
  288. };
  289. }
  290. function forEachField(schema, fn) {
  291. var typeMap = schema.getTypeMap();
  292. Object.keys(typeMap).forEach(function (typeName) {
  293. var type = typeMap[typeName];
  294. if (!graphql_1.getNamedType(type).name.startsWith('__') &&
  295. type instanceof graphql_1.GraphQLObjectType) {
  296. var fields_1 = type.getFields();
  297. Object.keys(fields_1).forEach(function (fieldName) {
  298. var field = fields_1[fieldName];
  299. fn(field, typeName, fieldName);
  300. });
  301. }
  302. });
  303. }
  304. function addTypeCandidate(typeCandidates, name, typeCandidate) {
  305. if (!typeCandidates[name]) {
  306. typeCandidates[name] = [];
  307. }
  308. typeCandidates[name].push(typeCandidate);
  309. }
  310. function defaultVisitType(name, candidates, candidateSelector) {
  311. if (!candidateSelector) {
  312. candidateSelector = function (cands) { return cands[cands.length - 1]; };
  313. }
  314. var resolveType = schemaRecreation_1.createResolveType(function (_, type) { return type; });
  315. if (name === 'Query' || name === 'Mutation' || name === 'Subscription') {
  316. var fields_2 = {};
  317. var operationName_1;
  318. switch (name) {
  319. case 'Query':
  320. operationName_1 = 'query';
  321. break;
  322. case 'Mutation':
  323. operationName_1 = 'mutation';
  324. break;
  325. case 'Subscription':
  326. operationName_1 = 'subscription';
  327. break;
  328. default:
  329. break;
  330. }
  331. var resolvers_1 = {};
  332. var resolverKey_1 = operationName_1 === 'subscription' ? 'subscribe' : 'resolve';
  333. candidates.forEach(function (_a) {
  334. var candidateType = _a.type, schema = _a.schema;
  335. var candidateFields = candidateType.getFields();
  336. fields_2 = __assign(__assign({}, fields_2), candidateFields);
  337. Object.keys(candidateFields).forEach(function (fieldName) {
  338. var _a;
  339. resolvers_1[fieldName] = (_a = {},
  340. _a[resolverKey_1] = createDelegatingResolver(schema, operationName_1, fieldName),
  341. _a);
  342. });
  343. });
  344. var type = new graphql_1.GraphQLObjectType({
  345. name: name,
  346. fields: schemaRecreation_1.fieldMapToFieldConfigMap(fields_2, resolveType, false),
  347. });
  348. return {
  349. type: type,
  350. resolvers: resolvers_1,
  351. };
  352. }
  353. else {
  354. var candidate = candidateSelector(candidates);
  355. return candidate.type;
  356. }
  357. }
  358. //# sourceMappingURL=mergeSchemas.js.map