0

EDIT

added my solution as an answer


ORIGINAL QUESTION

i believe this issue has to do with circular dependencies. i spent the better half of last night and today trying everything i could find online but nothing seems to work.

what i have tried:

  • convert the fields prop to a function that returns a field object
  • convert the relating fields (within the fields prop) into functions that return the type
  • combining the two approaches above
  • finally ending with require statements in place of the fields that use the reference type (does not seem correct and the linter had a stroke over this one)

here is the file structure:

File Structure

here is the code:

userType.js

const graphql = require('graphql');
const Connection = require('../../db/connection');
const ConnectionType = require('../connection/connectionType');

const { GraphQLObjectType, GraphQLList, GraphQLString, GraphQLID } = graphql;

const UserType = new GraphQLObjectType({
  name: 'User',
  fields: () => ({
    id: { type: GraphQLID },
    username: { type: GraphQLString },
    email: { type: GraphQLString },
    created: {
      type: GraphQLList(ConnectionType),
      resolve: ({ id }) => Connection.find({ owner: id }),
    },
    joined: {
      type: GraphQLList(ConnectionType),
      resolve: ({ id }) => Connection.find({ partner: id }),
    },
  }),
});

module.exports = UserType;

connectionType.js

const graphql = require('graphql');
const User = require('../../db/user');
const UserType = require('../user/userType');

const { GraphQLObjectType, GraphQLString, GraphQLID, GraphQLInt } = graphql;

const ConnectionType = new GraphQLObjectType({
  name: 'Connection',
  fields: () => ({
    id: { type: GraphQLID },
    owner: {
      type: UserType,
      resolve: ({ owner }) => User.findById(owner),
    },
    partner: {
      type: UserType,
      resolve: ({ partner }) => User.findById(partner),
    },
    title: { type: GraphQLString },
    description: { type: GraphQLString },
    timestamp: { type: GraphQLString },
    lifespan: { type: GraphQLInt },
  }),
});

module.exports = ConnectionType;
vampiire
  • 1,111
  • 2
  • 15
  • 27
  • Your types look fine, except that `GraphQLList(ConnectionType)` should be `new GraphQLList(ConnectionType)` since that is a class – zoran404 May 03 '18 at 21:47
  • thanks i tried that a little after i posted this. none of it works but it looks correct to me. i dont get it – vampiire May 03 '18 at 21:48
  • Where exactly do you get that error from the question title? – zoran404 May 03 '18 at 21:53
  • the graphiql client on load – vampiire May 03 '18 at 21:58
  • Honestly can't tell what the problem might be. Can you reproduce this on a smaller standalone example? – zoran404 May 03 '18 at 22:13
  • i cant do it in a standalone (if you mean a single script). the problem has to do with circular dependencies with several scripts – vampiire May 03 '18 at 22:14
  • Do you mean to say that this only happens if not all types are in the same file? – zoran404 May 03 '18 at 22:15
  • hey man just wanted to let you know i went into a hole for several hours nd figured it out myself. updated the question with my solution if you want to look @zoran404 – vampiire May 04 '18 at 03:55

2 Answers2

2

i couldnt get any help on this anywhere. in case anyone runs into this error message here are the steps i took to fix it:

  1. switched from graphql-express to apollo-server-express (this was not necessary but i found apollo to be a more robust library)
  2. used the following packages: graphql graphql-import graphql-tools
  3. switched from javascript based Type defs to using the GraphQL SDL (.graphql) file type
  4. step 3 is what corrected the circular import issue associated with one-to-many (and m2m) relationships

i committed every step of the refactor from dumping the old code to creating the new. i added plenty of notes and explicit naming so that it should be usable as a guide.

you can see the commit history diffs through the links below. all of the work until the last few commits was done within the graphql/ directory. if you click the title of the commit it will show you the diff so you can follow the refactor

after the refactor i now have cleaner resolvers, a better directory pattern, and, most importantly, fully functioning one-to-many relationships between User and Connection! ...only took my entire goddamn day.

the relationship in this case is: Connection belongs to an owner (User through owner_id) and partner (User through partner_id).

we will be moving forward from here with the codebase but i locked the branch and its commits for anyone who needs a guide.

vampiire
  • 1,111
  • 2
  • 15
  • 27
  • Yeah, switching to sdl type defs was probably the easiest solution. I really like your app structure now. – zoran404 May 04 '18 at 10:34
1

I had a similar issue using Typescript, and I kinda like the javascript based Type definition better so didn't change to GraphQL SDL.

I got it to work just by specifying the type of const to GraphQLObjectType.

Something like:

export const UserType: GraphQLObjectType = new GraphQLObjectType({
  name: 'UserType',
  fields: () => ({
    .....
  })
}

Now it works without a problem.

Marco Daniel
  • 5,467
  • 5
  • 28
  • 36