makeExecutableSchema.js 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import { buildASTSchema, buildSchema, isSchema } from 'graphql';
  2. import { applyExtensions, mergeExtensions, mergeResolvers, mergeTypeDefs, } from '@graphql-tools/merge';
  3. import { asArray } from '@graphql-tools/utils';
  4. import { addResolversToSchema } from './addResolversToSchema.js';
  5. import { assertResolversPresent } from './assertResolversPresent.js';
  6. /**
  7. * Builds a schema from the provided type definitions and resolvers.
  8. *
  9. * The type definitions are written using Schema Definition Language (SDL). They
  10. * can be provided as a string, a `DocumentNode`, a function, or an array of any
  11. * of these. If a function is provided, it will be passed no arguments and
  12. * should return an array of strings or `DocumentNode`s.
  13. *
  14. * Note: You can use GraphQL magic comment provide additional syntax
  15. * highlighting in your editor (with the appropriate editor plugin).
  16. *
  17. * ```js
  18. * const typeDefs = /* GraphQL *\/ `
  19. * type Query {
  20. * posts: [Post]
  21. * author(id: Int!): Author
  22. * }
  23. * `;
  24. * ```
  25. *
  26. * The `resolvers` object should be a map of type names to nested object, which
  27. * themselves map the type's fields to their appropriate resolvers.
  28. * See the [Resolvers](/docs/resolvers) section of the documentation for more details.
  29. *
  30. * ```js
  31. * const resolvers = {
  32. * Query: {
  33. * posts: (obj, args, ctx, info) => getAllPosts(),
  34. * author: (obj, args, ctx, info) => getAuthorById(args.id)
  35. * }
  36. * };
  37. * ```
  38. *
  39. * Once you've defined both the `typeDefs` and `resolvers`, you can create your
  40. * schema:
  41. *
  42. * ```js
  43. * const schema = makeExecutableSchema({
  44. * typeDefs,
  45. * resolvers,
  46. * })
  47. * ```
  48. */
  49. export function makeExecutableSchema({ typeDefs, resolvers = {}, resolverValidationOptions = {}, inheritResolversFromInterfaces = false, updateResolversInPlace = false, schemaExtensions, defaultFieldResolver, ...otherOptions }) {
  50. // Validate and clean up arguments
  51. if (typeof resolverValidationOptions !== 'object') {
  52. throw new Error('Expected `resolverValidationOptions` to be an object');
  53. }
  54. if (!typeDefs) {
  55. throw new Error('Must provide typeDefs');
  56. }
  57. let schema;
  58. if (isSchema(typeDefs)) {
  59. schema = typeDefs;
  60. }
  61. else if (otherOptions?.commentDescriptions) {
  62. const mergedTypeDefs = mergeTypeDefs(typeDefs, {
  63. ...otherOptions,
  64. commentDescriptions: true,
  65. });
  66. schema = buildSchema(mergedTypeDefs, otherOptions);
  67. }
  68. else {
  69. const mergedTypeDefs = mergeTypeDefs(typeDefs, otherOptions);
  70. schema = buildASTSchema(mergedTypeDefs, otherOptions);
  71. }
  72. // We allow passing in an array of resolver maps, in which case we merge them
  73. schema = addResolversToSchema({
  74. schema,
  75. resolvers: mergeResolvers(resolvers),
  76. resolverValidationOptions,
  77. inheritResolversFromInterfaces,
  78. updateResolversInPlace,
  79. defaultFieldResolver,
  80. });
  81. if (Object.keys(resolverValidationOptions).length > 0) {
  82. assertResolversPresent(schema, resolverValidationOptions);
  83. }
  84. if (schemaExtensions) {
  85. schemaExtensions = mergeExtensions(asArray(schemaExtensions));
  86. applyExtensions(schema, schemaExtensions);
  87. }
  88. return schema;
  89. }