Apollo-server: Regarding circular dependencies

Created on 8 Sep 2016  路  4Comments  路  Source: apollographql/apollo-server

This how I understood how to handle circular dependencies, wrap in function & return array. Reference: http://dev.apollodata.com/tools/graphql-tools/generate-schema.html

So if I do this:

// file: Author.js
const Book = require('./Book');

const Author = `
  type Author {
    name: String
    books: [Book]
  }
`;

module.exports = () => [Author, Book];

// -----------------------------------

// file: Book.js
const Author = require('./Author');

const Book = `
  type Book {
    title: String
    author: Author
  }
`;

module.exports = () => [Book, Author];

// -----------------------------------

// file: schema.js
const Author = require('./Author');

const RootQuery = `
  type RootQuery {
    author(name: String): Author
  }
`;
const SchemaDefinition = `
  schema {
    query: RootQuery
  }
`;

const schema = makeExecutableSchema({
  typeDefs: [SchemaDefinition, RootQuery, Author],
  resolvers: {}
});

It will result in the following error:

Error: typeDef array must contain only strings and functions, got object

I'm sure I misunderstood something and any help pointing me in the right direction is highly appreciated.

Most helpful comment

Thanks for the replies it turns out that all it need was some rubber ducking to realise the issue. All I needed to do is handle circular dependencies node style, export before require.

Like this:

// file: Author.js
module.exports = () => [Author, Book];

const Book = require('./Book');

const Author = `
  type Author {
    name: String
    books: [Book]
  }
`;
// -----------------------------------

// file: Book.js
module.exports = () => [Book, Author];

const Author = require('./Author');

const Book = `
  type Book {
    title: String
    author: Author
  }
`;
// -----------------------------------

// file: schema.js
const Author = require('./Author');

const RootQuery = `
  type RootQuery {
    author(name: String): Author
  }
`;
const SchemaDefinition = `
  schema {
    query: RootQuery
  }
`;

const schema = makeExecutableSchema({
  typeDefs: [SchemaDefinition, RootQuery, Author],
  resolvers: {}
});

All 4 comments

There is no need to import Book to where Author is, just combine them at schema.js. Since the order of graphQL file is unaffected with it.

I think the error you're getting because require('./Author') actually gives you an object, which contains more stuff than what you exported. Other than that, it all looks correct.

Thanks for the replies it turns out that all it need was some rubber ducking to realise the issue. All I needed to do is handle circular dependencies node style, export before require.

Like this:

// file: Author.js
module.exports = () => [Author, Book];

const Book = require('./Book');

const Author = `
  type Author {
    name: String
    books: [Book]
  }
`;
// -----------------------------------

// file: Book.js
module.exports = () => [Book, Author];

const Author = require('./Author');

const Book = `
  type Book {
    title: String
    author: Author
  }
`;
// -----------------------------------

// file: schema.js
const Author = require('./Author');

const RootQuery = `
  type RootQuery {
    author(name: String): Author
  }
`;
const SchemaDefinition = `
  schema {
    query: RootQuery
  }
`;

const schema = makeExecutableSchema({
  typeDefs: [SchemaDefinition, RootQuery, Author],
  resolvers: {}
});

If anyone wants to see this in a working project - https://github.com/eddyerburgh/express-graphql-boilerplate

Was this page helpful?
0 / 5 - 0 ratings