1
votes

I am very new on graphql, i am playing with a simple case and can not make it work, the case is a simple one to many, a user has many notes and one note belongs to user. My problem is with the "NoteType" I cannot return the "UserType", I can return the username of the User that create the Note but not the UserType

Code (Important remove some fields)

NoteType

When I uncomment de user I have the error Error: Note.user field type must be Output Type but got: [object Object].

import {
  GraphQLObjectType,
  GraphQLInt,
  GraphQLString,
  GraphQLBoolean,
} from 'graphql';

import UserType from '../User/UserType';
import User from '../User/User';

const NoteType = new GraphQLObjectType({
  name: 'Note',
  description: 'This represents a Note',
  fields: () => ({
    id: {
      type: GraphQLInt,
      resolve: (note) => note.id,
    },
    userId: {
      type: GraphQLInt,
      resolve: (note) => note.userId,
    },
    title: {
      type: GraphQLString,
      resolve: (note) => note.note,
    },
    username: {
      type: GraphQLString,
      resolve: (note) => (
        User
          .findOne({
            where: {
              id: note.userId,
            },
          }).then(user => user.username)
      ),
    },
    /* user: {  ***PROBLEM HERE!!***
      type: UserType,
      resolve: (note) => (
        User
          .findOne({
            where: {
              id: note.userId,
            },
          }).then(user => user)
      ),
    },*/
  }),
});

module.exports = NoteType;

UserType

import {
  GraphQLObjectType,
  GraphQLInt,
  GraphQLString,
  GraphQLList,
} from 'graphql';

import NoteType from '../Note/NoteType';
import Note from '../Note/Note';

import LocationType from '../Location/LocationType';
import Location from '../Location/Location';

const UserType = new GraphQLObjectType({
  name: 'User',
  description: 'This represents a User',
  fields: () => ({
    id: {
      type: GraphQLInt,
      resolve: (user) => user.id,
    },
    username: {
      type: GraphQLString,
      resolve: (user) => user.username,
    },
    email: {
      type: GraphQLString,
      resolve: (user) => user.email,
    },
    notes: {
      type: new GraphQLList(NoteType),
      resolve: (user) => (
        Note
          .findAll({
            where: {
              userId: user.id,
            },
          })
      ),
    },
  }),
});

module.exports = UserType;

NoteQuery

import {
  GraphQLInt,
  GraphQLString,
  GraphQLList,
} from 'graphql';

import NoteType from '../../models/Note/NoteType';
import Note from '../../models/Note/Note';

import UserType from '../../models/User/UserType';
import User from '../../models/User/User';

const noteQuery = {
  type: new GraphQLList(NoteType),
  args: {
    id: {
      name: 'id',
      type: GraphQLInt,
    },
    userId: {
      name: 'userId',
      type: GraphQLInt,
    },
    user: {
      name: 'user',
      type: GraphQLString,
    },
    note: {
      name: 'note',
      type: GraphQLString,
    },
    createdAt: {
      name: 'createdAt',
      type: GraphQLString,
    },
    updatedAt: {
      name: 'updatedAt',
      type: GraphQLString,
    },
  },
  resolve: (user, args) => Note.findAll({ where: args }),
};

module.exports = noteQuery;

UserQuery

import {
  GraphQLInt,
  GraphQLString,
  GraphQLList,
} from 'graphql';

import UserType from '../../models/User/UserType';
import User from '../../models/User/User';

const userQuery = {
  users: {
    type: new GraphQLList(UserType),
    args: {
      id: {
        name: 'id',
        type: GraphQLInt,
      },
      username: {
        name: 'username',
        type: GraphQLString,
      },
      email: {
        name: 'email',
        type: GraphQLString,
      },
      createdAt: {
        name: 'createdAt',
        type: GraphQLString,
      },
      updatedAt: {
        name: 'updatedAt',
        type: GraphQLString,
      },
    },
    resolve: (user, args) => User.findAll({ where: args }),
  },
  user: {
    type: UserType,
    args: {
      id: {
        name: 'id',
        type: GraphQLInt,
      },
      username: {
        name: 'username',
        type: GraphQLString,
      },
      email: {
        name: 'email',
        type: GraphQLString,
      },
      createdAt: {
        name: 'createdAt',
        type: GraphQLString,
      },
      updatedAt: {
        name: 'updatedAt',
        type: GraphQLString,
      },
    },
    resolve: (user, args) => User.findOne({ where: args }),
  },
};

module.exports = userQuery;

Any helps or tips thanks in advance!

1

1 Answers

5
votes

Looks like a cyclic dependency issue. You're importing the User module into your Note module, while importing the Note module into your User module. Your resolver for the user field is looking for an instance of GraphQLObjectType, but it's only receiving an unfinished copy of the exported type.

You can look at this question for a more thorough explanation and some workarounds.

However, I would suggest just declaring your schema with a string literal using buildSchema and passing in your resolvers through the root object. Or using graphql-tool's makeExecutableSchema, which is even easier. Either way, you'd be saving yourself the headache of dealing with cyclic dependencies, and make your schema more readable.