10
votes

I am new to GraphQL. I am following several guides on Internet in order to "create" a small app that uses Apollo Server + Express + GraphQL + MongoDB.

  • I have tried to replicate this YT guide (he creates root.js file on typeDefs folder).
  • This one for testing purposes.
  • And this one to make sure my folder structure is correct.

I am getting from GraphQL when compiling:

Error: There can be only one type named "User".

Error: There can be only one type named "Query".

I have structured my code like this:

  • config
  • models
  • resolvers
    • index.js
    • user.js
  • typeDefs
    • index.js
    • root.js
    • user.js
  • index.js

Until now, my code looks like this:

typeDefs/user.js:

import { gql } from 'apollo-server-express';

const user = gql`
    type User {
        id: ID!
        name: String
        email: String
        password: String
    }

    type Query {
        getUsers: [User]
    }

    type Mutation {
        addUser(name: String!, email: String!, password: String!): User
    }
`;

export default user;

typeDefs/root.js:

import { gql } from 'apollo-server-express';

export default gql`
    extend type Query {
        _: String
    }

    type User {
        _: String
    }
`;

typeDefs/index.js:

import root from './root';
import user from './user';

export default [
  root,
  user
];

And then in my index.js:

import express  from 'express';
import  { ApolloServer, gql } from 'apollo-server-express';

import typeDefs  from './typeDefs';
import resolvers from './resolvers';

const server = new ApolloServer({ typeDefs, resolvers });
const app = express();
server.applyMiddleware({ app });

app.disable('x-powered-by');

app.listen({ port: 4000 }, () => {
  console.log(`Server running at http://localhost:4000${server.graphqlPath}`)
});

What am I doing wrong?

1
You add two User definition, one in typeDefs/root.js:and the other within typeDefs/user.js:. Just remove the root one, should be enough.Striped
@Striped, okay... I get only one error. Yes, as expected. But what if multiple queries are defined on mutiple files which are being combined in typeDefs/index.js as seen?Maramal
Your typeDefs are fine as long you've got the extend keyword on both types inside root.js. I ran the code locally and it runs fine. Are you still seeing an error about Query being defined more than once? If so, what version of apollo-server-express are you running?Daniel Rearden
@DanielRearden I have added extend type Query & extend type User on typeDefs/user.js and now seems to work. Make your answer.Maramal

1 Answers

23
votes

When following the pattern of deep modularization, where you want to have each type definition in its own file, and each set of resolvers in their own file, you want to use the extend keyword and create "empty" definitions.

Supposing that you have root and user type definitions in separate files, your index file that puts them together should look like this:

const user = require('./user');
const root= require('./root');
const typeDefs = gql`
    type Query{
        _empty: String
    }
    type Mutation {
        _empty: String
    }
    ${user}
    ${root}
`;

module.exports = typeDefs;

You're using

    type Query{
        _empty: String
    }

to make an empty Query. Then you're adding your user and root at the end.

Within your user file, you'd want this:

    extend type Query {
        getUsers: [User]
    }

So the extend keyword is you extending the empty query you created in your index file.

You can read more on modularization here https://blog.apollographql.com/modularizing-your-graphql-schema-code-d7f71d5ed5f2