6

By using graphql-js, I need to create graphql schema dynamically by iterating over array of some data, for example:

[{
    name: 'author',
    fields: [{
        field: 'name'
    }, {
        field: 'books',
        reference: 'book'
    }]
}, {
    name: 'book',
    fields: [{
        field: 'title'
    }, {
        field: 'author',
        reference: 'author'
    }]
}]

The problem is circular references. When I'm creating AuthorType I need BookType to be already created and vise versa.

So resulting schema should look like:

type Author : Object {  
  id: ID!
  name: String,
  books: [Book]
}

type Book : Object {  
  id: ID!
  title: String
  author: Author
}

How can I solve this?

User Created Image
  • 1,182
  • 2
  • 17
  • 33

2 Answers2

15

Quoted from official documentation

http://graphql.org/docs/api-reference-type-system/

When two types need to refer to each other, or a type needs to refer to itself in a field, you can use a function expression (aka a closure or a thunk) to supply the fields lazily.

var AddressType = new GraphQLObjectType({
  name: 'Address',
  fields: {
    street: { type: GraphQLString },
    number: { type: GraphQLInt },
    formatted: {
      type: GraphQLString,
      resolve(obj) {
        return obj.number + ' ' + obj.street
      }
    }
  }
});

var PersonType = new GraphQLObjectType({
  name: 'Person',
  fields: () => ({
    name: { type: GraphQLString },
    bestFriend: { type: PersonType },
  })
});

Also look at this related answer of circular Category-Subcategory types

Community
  • 1
  • 1
LordDave
  • 1,118
  • 1
  • 11
  • 22
  • This answer is almost correct, it is true that you have to use function expression. In addition you have to iterate over your data twice. In first iteration you are creating all the types but fields function returns links on empty objects. And in second literation you need to fill these empty objects with actual data – User Created Image Oct 26 '16 at 17:25
0

I solved this problem by using a thunk for the fields field.

const User = new GraphQLObjectType({
  name: 'User',
  fields: () => ({
    id: { type: GraphQLID }
  })
});

When you make your fields a thunk rather than an object literal you can use types that are defined later in the file.

Please see this post for more info Is there a way to avoid circular type dependencies in GraqhQL?

Based on that post I think this is the correct way to do it.

Benjamin Conant
  • 1,684
  • 1
  • 14
  • 17