I am fairly new to javascript and am currently learning to implement a graphQL API with a MongoDB backend using Node.js. I am running into a problem with a circular dependency between two types.
Basically, I have a classic blog post/blog author situation. A post only has one author and therefore the mongoose schema holds a reference to that author.
In my graphQL type "Author" I want to add a field "posts" which allows me to navigate from authors to all the posts they have written. The reference is not coded in the database models but retrieved through the controllers. Here's my blog post code.
var graphql = require("graphql");
var AuthorResolvers = require("../resolvers/author");
var PostResolvers = require("../resolvers/post");
var AuthorType = require("./author").AuthorType;
var PostType = new graphql.GraphQLObjectType({
name: "PostType",
fields: {
_id: {
type: graphql.GraphQLID
},
title: {
type: graphql.GraphQLString
},
author: {
type: AuthorType,
description: "Author of this post",
resolve: (post) => AuthorResolvers.retwArgs(post)
}
}
});
module.exports = {PostType};
The resolvers.js file only exports functions to address the controllers.
My authors type is defined as follows:
var graphql = require ("graphql");
var AuthorResolvers = require("../resolvers/author");
var PostResolvers = require("../resolvers/post");
var AuthorType = new graphql.GraphQLObjectType({
name: "AuthorType",
fields: () => {
var PostType = require("./post");
return {
_id: {
type: graphql.GraphQLID
},
name: {
type: graphql.GraphQLString
},
posts: {
type: new graphql.GraphQLList(PostType),
description: "Posts written by this author",
resolve: (author) => PostResolvers.retwArgs(author)
}
}
}
});
There're two things in here which I already tried:
- I used a function to return the fields field. I think this is called a thunk or a closure.
- I require the PostType in the function returning the fields. When i required the file ./post together with the other requires, the error was already thrown at the top of the file.
when i try to run this server example, i recieve the error:
Can only create List of a GraphQLType but got: [object Object].
which points to the line
type: new graphql.GraphQLList(PostType)
in authors.
The files containing the type definitions posted above also export queries like this:
var PostQuery = {
posts: {
type: new graphql.GraphQLList(PostType),
description: "Posts of this Blog",
resolve: PostResolvers.ret
}
};
for the post and like this
var AuthorQuery = {
authors: {
type: new graphql.GraphQLList(AuthorType),
description: "The authors working on this Blog",
resolve: AuthorResolvers.ret
}
};
for the author respectively. Everything is brought together in a Schema file like this:
var graphql = require("graphql");
var Author = require("./types/author").AuthorQuery;
var Post = require("./types/post").PostQuery;
var root_query = new graphql.GraphQLObjectType({
name: "root_query",
fields: {
posts: Post.posts,
authors: Author.authors
}
});
module.exports = new graphql.GraphQLSchema({
query: root_query
});
and finally the server:
var graphql = require ('graphql').graphql
var express = require('express')
var graphQLHTTP = require('express-graphql')
var Schema = require('./api/schema')
var app = express()
.use("/", graphQLHTTP(
{
schema: Schema,
pretty: true,
graphiql: true,
}
))
.listen(4000, function(err) {
console.log('Running a GraphQL API server at localhost:4000');
})
I really don't see any way to resolve this circular dependency. If i simply comment out the references to the PostType in the AuthorType definitions, The server starts without problems. Any help here would be greatly appreciated.
Maybe for better understanding. The directory structure looks like this:
│ package.json
│ server.js
│
├───api
│ │ schema.js
│ │
│ ├───controllers
│ │ author.js
│ │ post.js
│ │
│ ├───models
│ │ author.js
│ │ post.js
│ │
│ ├───resolvers
│ │ author.js
│ │ post.js
│ │
│ └───types
│ author.js
│ post.js
│
└───config
db.js
fields: () => ({ _id: ..., author: ... })
? – Kreagervar PostType = require("./post");
at the top of the file and instead get the error in a different class. The output is thenPostType.author field type must be Output Type but got: undefined.
and strangely points to the generation of the GraphQL schema. – Indisposed