GraphQL/Relay Schema "Cannot query field..." - javascript

I'm having a problem with querying some fields in graphql/relay.
I'm trying to query the "courseName" field on Courses in the schema below.
If I query the User with for example:
{ user(id:1){firstname,lastname}}
It works and returns the correct response.
Here is my schema:
import {
GraphQLBoolean,
GraphQLFloat,
GraphQLID,
GraphQLInt,
GraphQLList,
GraphQLNonNull,
GraphQLObjectType,
GraphQLSchema,
GraphQLString,
} from 'graphql';
import {
connectionArgs,
connectionDefinitions,
connectionFromArray,
fromGlobalId,
globalIdField,
mutationWithClientMutationId,
nodeDefinitions,
} from 'graphql-relay';
import {
// Import methods that your schema can use to interact with your database
User,
Course,
getUser,
getCourses
} from './database';
/**
* We get the node interface and field from the Relay library.
*
* The first method defines the way we resolve an ID to its object.
* The second defines the way we resolve an object to its GraphQL type.
*/
var {nodeInterface, nodeField} = nodeDefinitions(
(globalId) => {
var {type, id} = fromGlobalId(globalId);
if (type === 'User') {
return getUser(id);
} else if (type === 'Course') {
return getCourses(id);
} else {
return null;
}
},
(obj) => {
if (obj instanceof User) {
return userType;
} else if (obj instanceof Course) {
return courseType;
} else {
return null;
}
}
);
/**
* Define your own types here
*/
var userType = new GraphQLObjectType({
name: 'User',
description: 'A person who uses our app',
fields: () => ({
id: globalIdField('User'),
firstname : {
type : GraphQLString,
description : 'User First Name'
},
lastname :{
type : GraphQLString,
description : 'User Last Name'
},
email : {
type : GraphQLString,
description : 'User email'
},
company : {
type : GraphQLString,
description : 'User company'
},
courses: {
type: courseConnection,
description: 'A user\'s collection of courses',
// args: {
// userId: {
// type: GraphQLInt
// }
// },
// resolve: (user, args) => connectionFromArray(getCourses(args.userId), args),
args: connectionArgs,
resolve: (user, args) => connectionFromArray(
getCourses(user.id),
args
)
},
}),
interfaces: [nodeInterface],
});
var courseType = new GraphQLObjectType({
name: 'Course',
description: 'A shiny course',
fields: () => ({
id: globalIdField('Course'),
courseName: {
type: GraphQLString,
description: 'The name of the Course',
}
}),
interfaces: [nodeInterface],
});
/**
* Define your own connection types here
*/
var {connectionType: courseConnection} =
connectionDefinitions({name: 'Course', nodeType: courseType});
/**
* This is the type that will be the root of our query,
* and the entry point into our schema.
*/
var queryType = new GraphQLObjectType({
name: 'Query',
fields: () => ({
node: nodeField,
// Add your own root fields here
user: {
type: userType,
args: {
id: { type: GraphQLInt }
},
resolve: (_,{id}) => getUser(id)
}
})
});
/**
* This is the type that will be the root of our mutations,
* and the entry point into performing writes in our schema.
*/
var mutationType = new GraphQLObjectType({
name: 'Mutation',
fields: () => ({
// Add your own mutations here
})
});
/**
* Finally, we construct our schema (whose starting query type is the query
* type we defined above) and export it.
*/
export var Schema = new GraphQLSchema({
query: queryType,
// Uncomment the following after adding some mutation fields:
// mutation: mutationType
});
here is my database.js:
import Course from './models/course';
import User from './models/user';
module.exports = {
User : User,
// Export methods that your schema can use to interact with your database
getUser: (id) => {
return User.findOne( {_id: id}).exec();
},
getCourses: (userId) => {
return Course.find( { userId : userId }).exec();
},
Course : Course
// getCourse: (id) => widgets.find(w => w.id === id),
// User,
// Widget,
};
When I try to query for:
{ user (id:1){courses{courseName}} }
It gives me the error:
"Cannot query field 'courseName' in 'CourseConnection'"
It seems that it is a problem with the connection.
Also I'm testing this queries with cURL. Since I want to test the schema before moving to react/relay.
What am I missing?
Thank you.

So, I found out why this was not working.
I had to do the query in RelayJS style:
so:
{ user(id:1){courses(first:2){edges{node{courseName}}}} }

Related

GraphQL: One of the provided types for building the Schema is missing a name

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
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');
StatusType.js loads UserType from const UserType = require('./UserType')
UserType.js should require StatusType but nodeJs prevent this to avoid infinite loop. As a result, it executes next lines
UserType 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;
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: () => ({})
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");
https://i.stack.imgur.com/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.
You are importing UserType inside StatusType before declaration.
const StatusType = require('./StatusType');
const UserType = require('./UserType');

joinmonster is not a function - GraphQL

I am using the library join-monster with GraphQL and postgres, with GraphiQL as client. When querying the database, I got the error: "joinMonster is not a function".
The method joinMonster() is provided by the library and is used in the resolvers.
The connection to the database is by knex and, apparently, it works. if I run the following code, I get the data form the table:
knex('students').then(rows => console.log(rows))
Database diagram
GraphiQL outpup
This is the schema-resolvers code:
const joinMonster = require('join-monster');
const knex = require('knex')({
client: 'postgres',
connection: {
host: 'localhost',
user: 'postgres',
password: 'myPassword',
database: 'test'
}
});
const { graphQLSchema } = require("graphql");
const {
GraphQLSchema,
GraphQLObjectType,
GraphQLString,
GraphQLInt,
GraphQLList,
GraphQLNonNull,
GraphQL
} = require('graphql');
const Subject = new GraphQLObjectType({
name: "Subject",
sqlTable: 'subjects',
uniqueKey: 'id',
fields: () => ({
id: {
type: GraphQLInt
},
name: {
type: GraphQLString
},
idEncoded: {
description: 'The ID base-64 encoded',
type: GraphQLString,
sqlColumn: 'id',
// specifies SQL column and applies a custom resolver
resolve: user => toBase64(user.idEncoded)
},
teacher: {
type: GraphQLString
},
students: {
type: new GraphQLList(Student),
junction: {
sqlTable: 'class',
sqlJoins: [
(subjectTable, junctionTable, args) => `${subjectTable}.id = ${junctionTable}.subject_id`,
(junctionTable, studentTable, args) => `${junctionTable}.student_id = ${studentTable}.id`
]
}
}
})
});
const Student = new GraphQLObjectType({
name: "Student",
sqlTable: 'students',
uniqueKey: 'id',
fields: () => ({
id: {
type: GraphQLInt
},
name: {
type: GraphQLString
},
idEncoded: {
description: 'The ID base-64 encoded',
type: GraphQLString,
sqlColumn: 'id',
resolve: user => toBase64(user.idEncoded)
},
lastname: {
type: GraphQLString
},
subjects: {
type: new GraphQLList(Subject),
junction: {
sqlTable: 'class',
sqlJoins: [
(studentTable, junctionTable, args) => `${studentTable}.id = ${junctionTable}.student_id`,
(junctionTable, subjectTable, args) => `${junctionTable}.subject_id = ${subjectTable}.id`
]
}
}
})
});
const QueryRoot = new GraphQLObjectType({
name: 'Query',
fields: () => ({
student: {
type: Student,
args: {
id: {
type: GraphQLInt
}
},
where: (studentsTable, args, context) => {
if (args.id) return `${studentsTable}.id = ${args.id}`
},
resolve: (parent, args, context, resolveInfo) => {
return joinMonster(resolveInfo, {}, sql => {
return knex.raw(sql)
})
}
},
subject: {
type: Subject,
args: {
id: {
type: GraphQLInt
}
},
where: (subjectsTable, args, context) => {
if (args.id) return `${subjectsTable}.id = ${args.id}`
},
resolve: (parent, args, context, resolveInfo) => {
return joinMonster(resolveInfo, {}, sql => {
return knex.raw(sql)
})
}
}
})
})
const schema = new GraphQLSchema({
query: QueryRoot,
});
module.exports = schema;
function toBase64(clear) {
return Buffer.from(String(clear)).toString('base64')
}
I have followed the documentation from https://join-monster.readthedocs.io/
Thanks
You can also import the function like this:
const joinMonster = require('join-monster').default;
The problem is that when making available the library to the file, an object is provided instead of a function.
const joinMonster = require('join-monster');
console.log(joinMonster)
// output
{ default: { [Function: joinMonster] getNode: [Function: getNode], version: '2.0.16' } }
I don't know why is served an object instead of a function. But
now, I invoke joinMonster.default, and it works:
resolve: (parent, args, context, resolveInfo) => {
return joinMonster.default(resolveInfo, {}, sql => {
return knex.raw(sql)
})

Many to Many graphql schema error

I'm new with GrpahQL and I'm trying to simulate Many to Many relationship between Users and Groups. I have the followinf types defined in my schema:
// UserType.js
const {
GraphQLObjectType,
GraphQLString,
GraphQLList,
GraphQLID } = require('graphql');
const {
GraphQLEmail } = require('graphql-custom-types');
const GroupType = require('./GroupType'); const AuthService = require('../../services/AuthService');
let authService = new AuthService();
const UserType = new GraphQLObjectType({
name: "UserType",
fields: () => ({
id: { type: GraphQLID },
user: { type: GraphQLString },
password: { type: GraphQLString },
name: { type: GraphQLString },
lastname: { type: GraphQLString },
email: { type: GraphQLEmail },
groups: {
type: new GraphQLList(GroupType),
resolve(parentValue) {
return authService.userGroups(userId);
}
}
}) });
module.exports = UserType;
and this is the other file:
// GroupType.js
const {
GraphQLObjectType,
GraphQLString,
GraphQLID,
GraphQLList
} = require('graphql');
const UserType = require('./UserType');
const AuthService = require('../../services/AuthService');
let authService = new AuthService();
const GroupType = new GraphQLObjectType({
name: "GroupType",
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
description: { type: GraphQLString },
users: {
type: new GraphQLList(UserType),
resolve(parentArgs) {
return authService.userGroups(parentArgs.id);
}
}
})
});
module.exports = GroupType;
This example doesn't work for me because for some reason i got this error:
Error: Can only create List of a GraphQLType but got: [object Object].
This error happens only for the GroupType and not for the UserType when both are similars. What's going on here? What am I doing wrong?
The problem is that UserType requires GroupType, and GroupType requires UserType: this is known as a circular dependency.
What happens is that UserType.js gets required, exports an {} while finishing to run (this is standard Node.js module execution), requires GroupType, which requires back UserType and gets an empty object back, and exports the correct GraphQL GroupType to UserType. So UserType works because it is a list of GroupType, but GroupType doesn't it got an empty object for its require of UserType.
To circumvent this, you can use a runtime require in GroupType.js:
// GroupType.js
...
// Remove the line which requires UserType at the top
// const UserType = require('./UserType');
const AuthService = require('../../services/AuthService');
...
const GroupType = new GraphQLObjectType({
...
fields: () => ({
...
users: {
type: new GraphQLList(require('./UserType')), // Require UserType at runtime
...
}
})
});
...

GraphQL cyclical reference using thunks - Error: field type must be Output Type but got: undefined

I have to solve a cyclic definition for GraphQL, but for some reason I´m not being able to solve. I´ve checked several posts about thunks and lazy loading and here is my current code:
History/types.js
const fields = {
id: {
type: new GraphQLNonNull(GraphQLID),
resolve: (obj) => dbIdToNodeId(obj._id, "History")
},
timestamp: {
type: GraphQLLong
},
objectId: {
type: GraphQLString
},
user: {
type: require('../User/connections').default,
args: connectionArgs,
resolve: (source, args) => {
return UserModel.findOne({ id: source.id }).exec();
}
},
action: {
type: new GraphQLNonNull(GraphQLString)
}
};
export const HistoryType = new GraphQLObjectType({
name: 'History',
description: 'History',
interfaces: () => [NodeInterface],
isTypeOf: (value) => value instanceof HistoryModel,
fields: () => (fields)
});
History/connections.js:
import { HistoryType } from './types';
const { connectionType: HistoryConnectionType } = connectionDefinitions( { nodeType: HistoryType });
export default HistoryConnectionType;
User/types.js
const fields = {
id: {
type: new GraphQLNonNull(GraphQLID),
resolve: (obj) => dbIdToNodeId(obj._id, "User")
},
email: {
type: GraphQLString
},
history: {
type: require('../History/connections').default,
args: connectionArgs,
resolve: (source, args, context) => {
return HistoryModel.find({ deleted: false, objectId: source.id}).sort('timestamp').exec();
}
}
};
export const UserType = new GraphQLObjectType({
name: 'User',
description: 'User',
interfaces: () => [NodeInterface],
isTypeOf: (value) => value instanceof UserModel,
fields: () => (fields)
});
User/connections.js
import { UserType } from './types';
const { connectionType: UserConnectionType } = connectionDefinitions( { nodeType: UserType });
export default UserConnectionType;
Company/types.js
const fields = {
id: {
type: new GraphQLNonNull(GraphQLID),
resolve: (obj) => dbIdToNodeId(obj._id, "Company")
},
name: {
type: GraphQLString
},
users: {
type: require('../User/connections').default,
args: connectionArgs,
resolve: (source, args) => {
const { id } = source;
return UserModel.find({ companyId: id }).then((rows) => connectionFromArray(rows,args));
}
},
history: {
type: require('../History/connections').default,
args: connectionArgs,
resolve(source, args, context) {
return loaders.getHistory(source.id);
}
}
};
export const CompanyType = new GraphQLObjectType({
name: 'Company',
description: 'Company',
interfaces: () => [NodeInterface],
isTypeOf: (value) => value instanceof CompanyModel,
fields: () => (fields)
});
Company/connections.js
import { CompanyType } from './types';
const { connectionType: CompanyConnectionType } = connectionDefinitions( { nodeType: CompanyType });
export default CompanyConnectionType;
I can´t make it work. When running I´m getting the following output:
History.user field type must be Output Type but got: undefined
I guess you resolved it by now, but for anyone passing by:
In history/types.js, the fields object must be inlined in the fields function of HistoryType, so it gets created at runtime.
const HistoryType = new GraphQLObjectType({
...
fields: () => ({ ... }), // not a var, object is inlined
...
});

How to add root and viewer queries on an existing GraphQL Server for Relay support

I've been working with GraphQL for a while and was able to successfully launch a simple GraphQL Server. Now I'm trying to make it support Relay, my final goal, and I'm having trouble adding support for the root node query and the viewer query.
I do understand the concept of both node and viewer, but I'm not making it work in the way I've structured my code. Here is my code, organized into separate files:
./graphql/User/types.js
import {
GraphQLObjectType,
GraphQLInputObjectType,
GraphQLNonNull,
GraphQLID,
GraphQLList,
GraphQLString,
GraphQLInt,
GraphQLBoolean
} from 'graphql';
import { GraphQLLong } from '../scalars';
import { NodeInterface } from '../interfaces';
const fields = {
_id: {
type: new GraphQLNonNull(GraphQLID)
},
email: {
type: GraphQLString
},
firstName: {
type: GraphQLString
},
lastName: {
type: GraphQLString
},
jobTitle: {
type: GraphQLString
},
phone: {
type: GraphQLString
}
};
export const UserType = new GraphQLObjectType({
name: 'User',
description: 'User',
interface: NodeInterface,
fields: fields
})
./graphql/User/queries.js
import { GraphQLNonNull, GraphQLID, GraphQLList } from 'graphql';
import { UserType, UserInputType } from './types';
import UserModel from '../../models/User';
const User = {
type: UserType,
description: 'Get single user',
args: {
id: {
name: 'id',
type: new GraphQLNonNull(GraphQLID)
}
},
resolve(root, params) {
params.deleted = false;
return UserModel.find(params).exec();
}
}
const Users = {
type: new GraphQLList(UserType),
description: 'Get all users',
resolve(root) {
const companies = UserModel.find({ deleted: false }).exec();
if (!companies) {
throw new Error('Error getting users.')
}
return companies;
}
}
export default {
User,
Users
}
./graphql/Company/types.js
import {
GraphQLObjectType,
GraphQLInputObjectType,
GraphQLNonNull,
GraphQLID,
GraphQLList,
GraphQLString,
GraphQLInt,
GraphQLBoolean
} from 'graphql';
import { GraphQLLong } from '../scalars';
import { UserType } from '../User/types';
import { NodeInterface } from '../interfaces';
import UserModel from '../../models/User';
const fields = {
_id: {
type: new GraphQLNonNull(GraphQLID)
},
name: {
type: GraphQLString
},
ein: {
type: GraphQLString
},
users: {
type: new GraphQLList(UserType),
resolve(company) {
const { _id } = company;
return UserModel.find({ companyId: _id }).exec();
}
}
};
export const CompanyType = new GraphQLObjectType({
name: 'Company',
description: 'Company',
interface: NodeInterface,
fields: fields
})
./graphql/Company/queries.js
import { GraphQLNonNull, GraphQLID, GraphQLList } from 'graphql';
import { CompanyType, CompanyInputType } from './types';
import CompanyModel from '../../models/Company';
const Company = {
type: CompanyType,
description: 'Get single company',
args: {
id: {
name: 'id',
type: new GraphQLNonNull(GraphQLID)
}
},
resolve(root, params) {
params.deleted = false;
return CompanyModel.find(params).exec();
}
}
const Companies = {
type: new GraphQLList(CompanyType),
description: 'Get all companies',
resolve(root) {
const companies = CompanyModel.find({ deleted: false }).exec();
if (!companies) {
throw new Error('Error getting companies.')
}
return companies;
}
}
export default {
Company,
Companies
}
./graphql/interfaces.js
import {
GraphQLInterfaceType,
GraphQLNonNull,
GraphQLID
} from 'graphql';
const NodeInterface = new GraphQLInterfaceType({
name: 'Node',
fields: {
id: {
type: new GraphQLNonNull(GraphQLID)
}
},
resolveType: (source) => {
return source.__type;
}
});
export default NodeInterface;
./graphql/schema.js
import { GraphQLObjectType, GraphQLSchema } from 'graphql';
import queries from './queries';
import mutations from './mutations';
export default new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: queries
}),
mutation: new GraphQLObjectType({
name: 'Mutation',
fields: mutations
})
});
./graphql/queries.js
import {
GraphQLObjectType,
GraphQLNonNull,
GraphQLID
} from 'graphql';
import { NodeInterface } from './interfaces';
import CompanyQueries from './Company/queries';
import UserQueries from './User/queries';
const RootQuery = new GraphQLObjectType({
name: 'RootQuery',
description: 'The root query',
fields: {
viewer: {
type: NodeInterface,
resolve(source, args, context) {
return { result: "VIEWER!" };
}
},
node: {
type: NodeInterface,
args: {
id: {
type: new GraphQLNonNull(GraphQLID)
}
},
resolve(source, args, context, info) {
return { result: "NODE QUERY" };
}
}
}
});
export default {
RootQuery,
...CompanyQueries,
...UserQueries
}
./server.js
import express from 'express';
import bodyParser from 'body-parser';
import mongoose from 'mongoose';
import morgan from 'morgan';
import graphqlHTTP from 'express-graphql';
import schema from './graphql/schema';
// set up example server
const app = express();
app.set('port', (process.env.API_PORT || 3001));
// logger
app.use(morgan('dev'));
// parse body
app.use(bodyParser.json());
app.use('/graphql', graphqlHTTP({
schema: schema,
graphiql: true,
pretty: true
}));
const mongoUri = process.env.MONGO_URI || 'mongodb://localhost/testdb';
mongoose.set('debug', true);
mongoose.connect(mongoUri, {
useMongoClient: true,
});
export default app;
The RootQuery is not being added to Schema. In fact I'm getting this error:
Error: Query.RootQuery field type must be Output Type but got: undefined.
Conceptually I don't know how to fix this code:
a) I don't know how to add that RootQuery to my query, and I don't know if I need to keep my other queries to my server (as Relay basically relies on node queries).
b) I cannot also see how my RootQuery will discover the object type and return it at the return source.__type. I've added that piece of code but I don't know how or where the given type will fill up this field.
Although I'm understanding a little of GraphQL, it seems that I don't have yet the fundamentals on how to build the Relay required root query (not to talk about the paginators, but this is my next step once I solve that).
The problem appears to be
import queries from './queries';
new GraphQLObjectType({
name: 'Query',
fields: queries
}),
const RootQuery = new GraphQLObjectType({
…
});
export default {
RootQuery,
…
};
The queries that you pass as the fields for the Query type is an object of types, not an object of field configurations. They are missing type and resolve properties, as the error message complains.

Categories