Reputation: 174
I'm learning GraphQL so I got a strange issue
I have this code on one file Schema.js:
const graphQL = require('graphql');
const lodash = require('lodash')
const { GraphQLObjectType, GraphQLString, GraphQLInt, GraphQLID, GraphQLSchema, GraphQLList } = graphQL;
const StatusType = new GraphQLObjectType({
name: 'Status',
fields: () => ({
id: { type: GraphQLInt },
statusName: { type: GraphQLString },
user: {
type: new GraphQLList(UserType),
resolve(parentValue, args){
}
}
})
});
const UserType = new GraphQLObjectType({
name: 'User',
fields: () => ({
id: { type: GraphQLString },
username: { type: GraphQLString },
mail: { type: GraphQLString },
password: { type: GraphQLString },
status: {
type: StatusType,
resolve(parentValue, args){
}
},
})
});
const RouteQuery = new GraphQLObjectType({
name: 'RouteQuery',
user: {
type: UserType,
args: { id: { type: GraphQLString } },
resolve(parentValue, args){
//return lodash.find(users, { id: args.id })
}
},
userSome: {
type: new GraphQLList(UserType),
args: { id: { type: GraphQLString } },
resolve(parentValue, args){
if (args.id) {
//return users.filter(user => user.id === args.id);
}
//return users;
}
},
userAll: {
type: new GraphQLList(UserType),
resolve(parentValue){
//return users
}
},
status:{
type: StatusType,
args: { id: { type: GraphQLInt } },
resolve(parentValue, args){
//return lodash.find(status, { id: args.id })
}
},
statusAll: {
type: new GraphQLList(StatusType),
resolve(parentValue){
//return users
}
}
}
});
module.exports = new GraphQLSchema({
query: RouteQuery
})
This code run succesfully but when i try to separate these into multiple files: the const StatusType & UserType
like the following case:
the StatusType is on StatusType.js file and the UserType is on UserType.js file
StatuType.js file:
const graphQL = require('graphql');
const { GraphQLObjectType, GraphQLString, GraphQLInt, GraphQLID, GraphQLSchema, GraphQLList } = graphQL;
const UserType = require('./UserType')
const StatusType = new GraphQLObjectType({
name: 'Status',
fields: () => ({
id: { type: GraphQLInt },
statusName: { type: GraphQLString },
user: {
type: new GraphQLList(UserType),
resolve(parentValue, args){
//return users.filter(user => user.status === parentValue.id);
}
}
})
});
module.exports = StatusType;
UserType.js file:
const graphQL = require('graphql');
const { GraphQLObjectType, GraphQLString, GraphQLInt, GraphQLID, GraphQLSchema, GraphQLList } = graphQL;
const StatusType = require('./StatusType')
const UserType = new GraphQLObjectType({
name: 'User',
fields: () => ({
id: { type: GraphQLString },
username: { type: GraphQLString },
mail: { type: GraphQLString },
password: { type: GraphQLString },
status: {
type: StatusType,
resolve(parentValue, args){
//return lodash.find(status, { id: parentValue.status })
}
},
})
});
module.exports = UserType;
And on the Schema.js file i include these 2 like that:
const StatusType = require('./StatusType');
const UserType = require('./UserType');
so instead of putting the all code on the same file, i putted the StatusType and UserType on respective files.
but when i run this code, i got this error:
So i don't know what the problem here :/
But when i'm tring to console.log the const UserType = require('./UserType')
i got User
as response :o like when it was on the same code on Schema.js
Upvotes: 4
Views: 4089
Reputation: 1
https://i.sstatic.net/ORvCG.png
Please see the above Image and code line: 5. I was inserting data into my client collection using Mutation GraphQL and used a single quote for ClientType ('ClientType') and got the same error. I have just removed a single quote as the type wants the client GraphQLObjectType and I was providing ClientType as String.
I searched for it for 2 days. Hope it will help anyone.
Upvotes: 0
Reputation: 559
Injection solves this error
// StatusType.js
const StatusType = (types) => new GraphQLObjectType({
name: 'Status',
fields: () => {
console.log(types.UserType);
return ({
id: { type: GraphQLInt },
statusName: { type: GraphQLString },
user: {
type: new GraphQLList(types.UserType),
resolve(parentValue, args) {
}
}
});
}
});
module.exports = StatusType;
Create a types.js file in your directory. Here you can add all your types that integrate with other types and inject the required types.
const UserTypeInject = require("./UserType");
const StatusTypeInject = require("./Author");
const types = {};
types.UserType = UserTypeInject(types);
types.StatusType = StatusTypeInject(types);
const UserType = types.UserType;
const StatusType = types.StatusType;
module.exports = { UserType, StatusType };
Whenever you need the type either in Mutations or Queries, you import it from the types.js files as such;
const { UserType } = require("../types");
Upvotes: 0
Reputation: 12092
You could do with some cleaning up here and here's how I'd resolve these situations:
[..]
// import GraphQLNonNull from the graphql lib
// In your case, I'd use GraphQLID instead of GraphQLString
userSome: {
type: new GraphQLList(require('../path/to/UserType')),
args: { id: { type: new GraphQLNonNull(GraphQLID) } },
resolve: async (parentValue, args) => {
// No need for the if statement as we'd sure to have an id.
// return await filter users by id.
}
},
[..]
And as always, keep your fields
as functions: fields: () => ({})
Upvotes: 2
Reputation: 11693
You are facing a problem in the way nodeJs handle require
. See http://nodejs.org/api/modules.html#modules_cycles for how require
is handled in node.
Specifically in your case, when you do:
const StatusType = require('./StatusType');
const UserType = require('./UserType');
StatusType
is loaded from const StatusType = require('./StatusType');
UserType
from const UserType = require('./UserType')
StatusType
but nodeJs prevent this to avoid infinite loop. As a result, it executes next linesUserType
is initialized as new GraphQLObjectType(...)
and defined fields
as a function. The function closure hand a variable StatusType
not yet initialized. It's just an empty exported module {}
You can verify that adding console.log(StatusType);
when creating UserType
fields:
const UserType = new GraphQLObjectType({
name: 'User',
fields: () => {
console.log(StatusType);
return ({
id: { type: GraphQLString },
username: { type: GraphQLString },
mail: { type: GraphQLString },
password: { type: GraphQLString },
status: {
type: StatusType,
resolve(parentValue, args) {
}
},
});
}
});
You'll get:
{} //instead of StatusType
You didn't encounter this problem when everything was in the same file because both UserType
and StatusType
are defined within the same closure and now each others.
To resolve that you had to define UserType
and StatusType
on the same level and inject them. A good example of how to do it can be found here. In your case:
// StatusType.js
const StatusType = (types) => new GraphQLObjectType({
name: 'Status',
fields: () => {
console.log(types.UserType);
return ({
id: { type: GraphQLInt },
statusName: { type: GraphQLString },
user: {
type: new GraphQLList(types.UserType),
resolve(parentValue, args) {
}
}
});
}
});
module.exports = StatusType;
// UserType.js
const UserType = (types) => new GraphQLObjectType({
name: 'User',
fields: () => {
console.log(types.StatusType);
return ({
id: { type: GraphQLString },
username: { type: GraphQLString },
mail: { type: GraphQLString },
password: { type: GraphQLString },
status: {
type: types.StatusType,
resolve(parentValue, args) {
}
},
});
}
});
module.exports = UserType;
// Schema.js
const StatusTypeInject = require('./StatusType');
const UserTypeInject = require('./UserType');
const types = {};
types.StatusType = StatusTypeInject(types);
types.UserType = UserTypeInject(types);
const StatusType = types.StatusType;
const UserType = types.UserType;
Upvotes: 7
Reputation: 949
You are importing UserType inside StatusType before declaration.
const StatusType = require('./StatusType');
const UserType = require('./UserType');
Upvotes: -1