4

I am using Apollo-server-express and Graphql-tools. I have been all over the Graphql-tools documentation and I can't get this to work. I'm trying to get my schema.graphql file to import as my typeDefs. It seems like Graphql-tools should be making this easy, but something isn't falling into place.

index.js

const { ApolloServer } = require("apollo-server-express");
const { makeExecutableSchema } = require('@graphql-tools/schema');
const express = require("express");
const { join } = require("path");
const { loadSchema } = require("@graphql-tools/load");
const { GraphQLFileLoader } = require("@graphql-tools/graphql-file-loader");
const { addResolversToSchema } = require("@graphql-tools/schema");
const app = express();

const resolvers = {
  Query: {
    items: (parent, args, ctx, info) => {
      return ctx.prisma.item.findMany();
    },
  },
  Mutation: {
    makeItem: (parent, args, context, info) => {
      const newItem = context.prisma.item.create({
        data: {
          ...args,
          price: parseInt(Math.ceil(args.price * 100)),
        },
      });
      return newItem;
    },
    deleteItem: (parent, args, context, info) => {
      return context.prisma.item.delete({
        where: {
          id: args.id,
        },
      });
    },
  },
};

const schemaSource = loadSchemaSync(join(__dirname, "schema.graphql"), {
  loaders: [new GraphQLFileLoader()],
});

const schema = makeExecutableSchema({
  typeDefs: schemaSource,
  resolvers,
});

const server = new ApolloServer({
  schema,
  resolvers,
});

server.applyMiddleware({ app });

app.listen(
  { port: 4000 },
  () =>
    console.log(
      ` => Backend server is now running on port http://localhost:4000`
    )
);

schema.graphql

type Query {
  items: [Item!]!
}

type Mutation {
  makeItem(
    piece: String!
    image: String!
    identifier: String!
    price: Float!
    itemNumber: Int!
  ): Item!
  deleteItem(id: ID!): Item!
}

type Item {
  id: ID!
  piece: String!
  image: String!
  identifier: String!
  price: Int!
  itemNumber: Int!
}

In its current state I am getting an error that says: "Error: typeDefs must be a string, array or schema AST, got object"

As I understand it makeExecutableSchema should be doing all the necessary steps, like changing the schema into a string. I can't seem to figure out what is going on here and any help would be greatly appreciated.

BWayne
  • 161
  • 1
  • 2
  • 10
  • 1
    If you are using babel to transpile your code, I think you can import directly your schema file like: `import yourSchema from "./path/to/yourSchema.graphql";` by the support of the plugin `babel-plugin-import-graphql` – tmhao2005 Jul 27 '20 at 14:49

1 Answers1

8

loadSchemaSync will load a GraphQLSchema object using the provided pointer. You should use loadTypedefsSync instead.

const sources = loadTypedefsSync(join(__dirname, "schema.graphql"), {
  loaders: [new GraphQLFileLoader()],
});
const typeDefs = sources.map(source => source.document)
const server = new ApolloServer({ typeDefs, resolvers })

If you want to use loadSchema, you don't need to use makeExecutableSchema because your schema has already been created. So you would do this instead as shown in the docs:

const schema = loadSchemaSync(join(__dirname, "schema.graphql"), {
  loaders: [new GraphQLFileLoader()],
});

const resolvers = {...};
const schemaWithResolvers = addResolversToSchema({
    schema,
    resolvers,
});
const server = new ApolloServer({ schema: schemaWithResolvers })
Daniel Rearden
  • 80,636
  • 11
  • 185
  • 183
  • Just to be clear: are you saying use loadTypedefsSync and then pass schemaSource to the new ApolloServer? I have tried that as well without success. I tried loadSchema and loadSchemaSync. I tried addResolversToSchema and passing that to the server. No luck. I keep getting the typeDefs must be a string error. – BWayne Jul 27 '20 at 16:13
  • 1
    If you use loadSchema and addResolversToSchema, you should pass the schema like this: `new ApolloServer({ schema: schemaWithResolvers })`. Please see the edit for additional details. – Daniel Rearden Jul 27 '20 at 16:55
  • I must have a typo or something that I'm not seeing. I commented out all of my code and copied and pasted yours in and it works. But for the life of me I can't see the difference in the code... ha must be something though. Thank you very much for the help! – BWayne Jul 27 '20 at 17:21
  • It is worth noting here that addResolversToSchema() requires you to pass "schema". I was passing "sources". It was my understanding that variable names were irrelevant, but that seems to not be the case. That is where part of my problem was coming from. – BWayne Jul 27 '20 at 17:31
  • 1
    Variable names are irrelevant, but in this case you are passing in an object literal, not a variable, and using [shorthand notation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer). – Daniel Rearden Jul 27 '20 at 17:45
  • 1
    Ahhh right, of course. Thanks for pointing that out. – BWayne Jul 27 '20 at 18:06