Circular Dependencies cannot be split into their respective files

Viewed 53

There are two objects, Users and Company, each user works for a Company, thereby has a companyId which is referred to through GraphQL. Similarly, each Company has a list of users working for them.

Here's the code:

company.js

const UserType = require('./user')

const CompanyType = new GraphQLObjectType({
  name: 'Company',
  fields: () => ({
    id: { type: GraphQLString },
    name: { type: GraphQLString },
    users: {
      type: new GraphQLList(UserType),        --------> Error:Expected {} to be a GraphQL type.
                                                        Expected UserType to be a GraphQL type.
      async resolve(parentValue, args) {
        return await axios(
          `http://localhost:3001/company/${parentValue.id}/users`
        ).then(({ data }) => data)
      },
    },
  }),
})

user.js

const CompanyType = require('./company')

const UserType = new GraphQLObjectType({
  name: 'User',
  fields: () => ({
    id: { type: GraphQLString },
    age: { type: GraphQLInt },
    name: { type: GraphQLString },
    company: {
      type: CompanyType,
      async resolve(parentValue, args) {
        console.log(parentValue)
        return await axios(
          `http://www.localhost:3001/company/${parentValue.companyId}`
        ).then((response) => response.data)
      },
    },
  }),
})

rootquery.js

const UserType = require('./user')
const CompanyType = require('./company')

const RootQuery = new GraphQLObjectType({
  name: 'RootQueryObjectType',
  fields: {
    user: {
      type: UserType,
      args: {
        id: { type: GraphQLString },
      },
      resolve: async (parentValue, args) => {
        return await axios(`http://localhost:3001/users/${args.id}`).then(
          ({ data }) => data
        )
      },
    },
    company: {
      type: CompanyType,
      args: {
        id: { type: GraphQLString },
      },
      resolve: async (parentValue, args) => {
        return await axios(`http://localhost:3001/company/${args.id}`).then(
          ({ data }) => data
        )
      },
    },
  },
})

The error is understandable due to Circular Dependencies. In case I put the code of user.js and company.js into the rootquery.js, there's no error. Is there a way to seperate out these files, without running into an empty object error?

1 Answers

After researching quite a bit, found out that wherever you'd need to use a circular dependency, you've got to require it at that point in your code, instead of requiring it as a variable. E.g.

Previously:

const UserType = require('./user')        ---> This was null/empty as it wasn't yet 
                                               created

const CompanyType = new GraphQLObjectType({
  name: 'Company',
  fields: () => ({
    id: { type: GraphQLString },
    name: { type: GraphQLString },
    users: {
      type: new GraphQLList(UserType),        --------> Error:Expected {} to be a 
                                                              GraphQL type.
                                                        Expected UserType to be a 
                                                              GraphQL type.
      async resolve(parentValue, args) {
        return await axios(
          `http://localhost:3001/company/${parentValue.id}/users`
        ).then(({ data }) => data)
      },
    },
  }),
})

To overcome this issue, I required the neccessary module exactly where it is required

Solution:

const UserType = new GraphQLObjectType({
  name: 'User',
  fields: () => ({
    name: { type: GraphQLString },
    id: { type: GraphQLString },
    age: { type: GraphQLInt },
    company: {
      **type: require('./company'),**            -----> This is where a dynamic 
                                                                 import                                                               
                                                             is being made
      async resolve(parentValue, args) {
        return await axios(
          `http://localhost:3001/users/${parentValue.id}`
        ).then(({ data }) => data)
      },
    },
  }),
})
Related