GraphQL, incorrect syntax for query using GraphiQL - graphql

New to GraphQL, I'm having problems sending a query through GraphiQL.
This is my schema.js
const graphql = require('graphql');
const _ = require('lodash');
const{
GraphQLObjectType,
GraphQLInt,
GraphQLString,
GraphQLSchema
} = graphql;
const users = [
{id:'23', firstName:'Bill', age:20},
{id:'47', firstName:'Samantha', age:21}
];
const UserType = new GraphQLObjectType({
name: 'User',
fields:{
id: {type: GraphQLString},
firstName: {type: GraphQLString},
age:{type: GraphQLInt}
}
});
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields:{
user: {
type: UserType,
args:{
id: {type: GraphQLString}
},
resolve(parentValue, args){ // move the resolve function to here
return _.find(users, {id: args.id});
}
},
}
});
module.exports = new GraphQLSchema({
query: RootQuery
});
And when I run the following query on graphiql:
query {
user {
id: "23"
}
}
I got "Syntax Error GraphQL request (3:9) Expected Name, found String", but I would expect to get the user with id "23".
What am I missing?

You are putting your argument value on your selection it should instead look like
query {
user(id: “23”) {
id
firstName
age
}
}
Please review the arguments section of the tutorial http://graphql.org/graphql-js/passing-arguments/

Related

Querying Schema in GraphiQL Sandbox

I am learning graph via a tutorial for work. I think the tutorial is a little out of date but its got some good info so I am trying to keep with it. However my queries dont seem to work the way the video is showing them. Can someone take a look and tell me whats wrong here?
Here is my Schema:
const graphql = require('graphql');
const _ = require('lodash')
const {
GraphQLObjectType,
GraphQLString,
GraphQLInt,
GraphQLSchema
} = graphql
const users = [
{ id: '23', firstName: 'Matt', age: 33 },
{ id: '47', firstName: 'Alexis', age: 28 }
]
const UserType = new GraphQLObjectType({
name: 'User',
fields: {
id: { type: GraphQLString } ,
firstName: { type: GraphQLString },
age: { type: GraphQLInt }
}
});
const RootQuery = new GraphQLObjectType({
name: "RootQueryType",
fields: {
user: {
type: UserType,
args: { id: { type: GraphQLString } },
resovle(parentValue, args) {
return _.find(users, { id: args.id } );
}
}
}
});
module.exports = new GraphQLSchema({
query: RootQuery
});
Here is my query in GraphiQL:
To cover all bases, here is the server.js
const express = require('express');
const expressGraphQL = require('express-graphql').graphqlHTTP;
const schema = require('./schema/schema');
const app = express();
app.use('/graphql', expressGraphQL({
schema,
graphiql: true
}));
app.listen(4000, () => {
console.log('Listening');
});

How can I combine a GraphQLObjectType with a schema created by graphql-tag with gql-tag?

I use graphql-tag together with apollo-server-express to connect to build a graphQL endpoint for an api. At the moment I create the schema definition like this:
properties.js
let model = {}
const typeDefs = gql`
extend type Query {
property(id: Int!): [Property]
}
type Property {
title: String
street: String
postalcode: String
city: String
country: String
}
`
const resolvers = {
Query: {
property: getTheEntriesFromDB,
},
}
model.typeDefs = typeDefs;
model.resolvers = resolvers;
module.exports = model;
and server.js
const server = new ApolloServer({
modules: [
require('./modules/properties'),
],
}):
However I want to create the type 'Property' based on a database schema automatically. I found out that I can create a GraphQLObjectType like this:
const propertyType = new graphql.GraphQLObjectType({
name: 'Property',
fields: {
title: { type: graphql.GraphQLString },
street: { type: graphql.GraphQLString },
postalcode: { type: graphql.GraphQLString },
city: { type: graphql.GraphQLString },
country: { type: graphql.GraphQLString },
}
});
but I don't know how to combine this with
let model = {}
const typeDefs = gql`
extend type Query {
property(id: Int!): [Property]
}
`
const resolvers = {
Query: {
property: getTheEntriesFromDB,
},
}
model.typeDefs = typeDefs;
model.resolvers = resolvers;
module.exports = model;
to create the final schema. Can someone point me in the right direction?
Any help is highly appreciated. Thanks a lot in advance!
OK, after hours of trial and error and searching I found this solution which works for me:
properties.js
const { buildASTSchema, GraphQLObjectType, GraphQLSchema, GraphQLString, parse, printSchema } = require('graphql')
let model = {}
const propertyType = new GraphQLObjectType({
name: 'Property',
fields: {
title: { type: GraphQLString },
street: { type: GraphQLString },
postalcode: { type: GraphQLString },
city: { type: GraphQLString },
country: { type: GraphQLString },
}
});
let typeDefs = gql`
extend type Query {
property(id: Int!): [Property]
}
type Property {
id: Int
}
`
typeDefs.definitions[0].kind = 'ObjectTypeDefinition' //replace ObjectTypeExtension with ObjectTypeDefinition to make AST 'valid' but keep extend in gql-tag to satisfy code inspection in ide
typeDefs = parse(printSchema(buildASTSchema(typeDefs)).replace('type Query {', 'extend type Query {') + printSchema(new GraphQLSchema({ types: [ propertyType ]})).replace('type Property {', 'extend type Property {'))
const resolvers = {
Query: {
property: getTheEntriesFromDB,
},
}
model.typeDefs = typeDefs;
model.resolvers = resolvers;
module.exports = model;
The "extend" keywords are needed because Property needs to be declared inside the gql tag and Query is declared more than once throughout the project.

Error: Expected [object Object] to be a GraphQL type

This code was working until I added the Resources part into the code. It is similar to the other two so I am not sure why isn't it working.
Thanks in advance
Update:-
After using the debugger, I came to understand that the problem is in the RootQueryType.js and files associated with it as the error pops up when I am trying to export the schema and exactly at the query:RootQueryType place but still can't pinpoint at the error.
Update:-
I have put the schema.js file too in the end
resourceType.js
const graphql = require("graphql");
const UserType = require("./userType");
const User = require("../models/User");
const Project = require("../models/Project");
const Resource = require("../models/Resource");
const ProjectType = require("./projectType");
const {
GraphQLObjectType,
GraphQLString,
GraphQLList,
} = graphql;
const ResourceType = new GraphQLObjectType({
name: "ResourceType",
fields: () => ({
id: { type: GraphQLString },
title: { type: GraphQLString },
url: { type: GraphQLString },
project:{
type:ProjectType,
resolve(parentValues,args){
return Project.findById(parentValues.id).populate("resources")
}
}
})
});
module.exports=ResourceType;
RootQueryType.js
const mongoose = require('mongoose');
const graphql = require('graphql');
const { GraphQLObjectType, GraphQLList, GraphQLID, GraphQLNonNull } = graphql;
const ProjectType = require('./../types/projectType');
const UserType = require('./../types/userType');
const Project=require("../models/Project");
const User=require("../models/User");
const RootQuery=new GraphQLObjectType({
name:"RootQueryType",
fields: () => ({
projects:{
type:new GraphQLList(ProjectType),
resolve(parentValues,args,request){
return Project.find().populate("contributors").populate("resources");
}
},
project:{
type:ProjectType,
args:{id:{type:new GraphQLNonNull(GraphQLID)}},
resolve(parentValue,args,request){
return Project.findById(args.id).populate("contributors").populate("resources");
}
},
users:{
type:new GraphQLList(UserType),
resolve(parentValues,args,request){
return User.find().populate("projects");
}
},
user:{
type:UserType,
args:{id:{type:new GraphQLNonNull(GraphQLID)}},
resolve(parentValue,args,request){
return User.findById(args.id).populate("projects")
}
},
})
})
module.exports = RootQuery;
Mutation.js
const mongoose = require("mongoose");
const ProjectType = require("./../types/projectType");
const UserType = require("./../types/userType");
const graphql = require("graphql");
const {
GraphQLObjectType,
GraphQLList,
GraphQLID,
GraphQLNonNull,
GraphQLString
} = graphql;
const Project = require("../models/Project");
const User = require("../models/User");
const mutation = new GraphQLObjectType({
name: "mutation",
fields: () => ({
addUser: {
type: UserType,
args: {
name: { type: new GraphQLNonNull(GraphQLString) },
username: { type: new GraphQLNonNull(GraphQLString) },
password: { type: new GraphQLNonNull(GraphQLString) },
email: { type: new GraphQLNonNull(GraphQLString) },
githubProfile: { type: new GraphQLNonNull(GraphQLString) }
},
resolve(parentValues, args, request) {
return User.create(args);
}
},
addProject: {
type: ProjectType,
args: {
name: { type: new GraphQLNonNull(GraphQLString) },
description: { type: new GraphQLNonNull(GraphQLString) },
image: { type:GraphQLString },
// contributor:{ type: new GraphQLNonNull(new GraphQLList(GraphQLID))
contributor:{ type: new GraphQLNonNull(GraphQLID)
},
},
resolve(parentValues, args, request) {
return Project.create(args);
}
}
})
});
module.exports = mutation;
I am positive it isnt the problem with other types because they were working earlier and I only added the .populate("resources") property to the resolve function of both of them. But just in case I am adding the code for them too.
userType.js
const graphql = require("graphql");
const ProjectType = require("./projectType");
const { GraphQLObjectType, GraphQLString, GraphQLList } = graphql;
const UserType = new GraphQLObjectType({
name: "User",
fields: () => ({
id: { type: GraphQLString },
name: { type: GraphQLString },
githubProfile: { type: GraphQLString },
username: { type: GraphQLString },
password: { type: GraphQLString },
email: { type: GraphQLString },
projects: {
type: new GraphQLList(ProjectType),
resolve(parentValues, args) {
return User.findById(parentValues.id).populate("projects");
}
}
})
});
module.exports = UserType;
and the other is
projectType.js
const graphql = require("graphql");
const UserType = require("./userType");
const ResourceType = require("./resourceType");
const User = require("../models/User");
const Project = require("../models/Project");
const {
GraphQLObjectType,
GraphQLString,
GraphQLList,
} = graphql;
const ProjectType = new GraphQLObjectType({
name: "ProjectType",
fields: () => ({
id: { type: GraphQLString },
name: { type: GraphQLString },
description: { type: GraphQLString },
image: { type: GraphQLString },
contributors: {
type: new GraphQLList(UserType),
resolve(parentValues, args, request) {
return Project.findContributors(parentValues.id);
}
},
resources:{
type: new GraphQLList(ResourceType),
resolve(parentValues, args, request) {
return Project.findResources(parentValues.id);
}
}
})
});
module.exports=ProjectType;
schema.js
const graphql = require("graphql");
const RootQuery = require("./RootQueryType");
const Mutation = require("./Mutation");
const { GraphQLSchema } = graphql;
console.log(RootQuery,Mutation);
module.exports = new GraphQLSchema({
query: RootQuery,
mutation: Mutation
});
Update:- I have removed the resources files and I am still getting the same error so it must be between user and project types
Update:-I finally tracked down the bug to being in the type files of both project and user type and it is being caused by the new GraphQLList, I still havent solved the error but removing it seems to make the error go away, no idea why.
Finally solved the problem, it was as #cito said, because of circular dependencies that was the cause of the error, that is as my UserType is dependent on ProjectType and likewise and hence I was getting this error, this was solved by
const graphql = require("graphql");
const User = require("../models/User");
const Project = require("../models/Project");
const {
GraphQLObjectType,
GraphQLString,
GraphQLList,
} = graphql;
const ProjectType = new GraphQLObjectType({
name: "ProjectType",
fields: () => ({
id: { type: GraphQLString },
name: { type: GraphQLString },
description: { type: GraphQLString },
image: { type: GraphQLString },
contributors: {
type: new GraphQLList(UserType),
resolve(parentValues, args, request) {
return Project.findContributors(parentValues.id);
}
},
resources:{
type: new GraphQLList(ResourceType),
resolve(parentValues, args, request) {
return Project.findResources(parentValues.id);
}
}
})
});
module.exports=ProjectType;
// This is here to prevent circular dependencies problem which will lead to the formation of infinite loop
const UserType = require("./userType");
const ResourceType = require("./resourceType");
that is requiring the files at the bottom
Your problem is the cyclic dependency between the userType and projectType module. Therefore the const value is still an empty object when it is passed to GraphQLList.
As a solution, you can move all the types into one module. Or, when exporting your classes, set them as properties of module.exports. This will work since you defined the fields properly as thunks.
By the way, you don't need the new when creating a GraphQLList or GraphQLNonNull wrapper. But that's not why you're getting the error.
Another way to go is:
resources:{
// require directly without creating a new variable
type: new GraphQLList(require("./resourceType")),
resolve(parentValues, args, request) {
return Project.findResources(parentValues.id);
}
}
I solved the problem. Just have both objectType in the same file.
I works

GraphQL mutation structure

I am trying to create a Node.js graphql server in Typescript. I am using Express and express-graphql. I have some issues with how to structure my mutation when I want to create a new User.
My goal is to be able to use a mutation like this:
mutation {
user {
create(
data: {
name: "Foo Bar"
}
) {
id,
name
}
}
}
Here is my User types:
import {
GraphQLObjectType,
GraphQLNonNull,
GraphQLBoolean,
GraphQLString,
GraphQLInputObjectType
} from 'graphql';
export const UserType = new GraphQLObjectType({
name: 'User',
description: 'A user of the application',
fields: () => ({
id: {
type: new GraphQLNonNull(GraphQLString),
description: 'The id of the user',
},
name: {
type: new GraphQLNonNull(GraphQLString),
description: 'The name of the user',
}
})
});
export const UserInputType = new GraphQLInputObjectType({
name: 'UserInputType',
description: 'User payload definition',
fields: () => ({
name: { type: new GraphQLNonNull(GraphQLString) }
})
});
Here is my attempt at defining the mutation on the server:
// ../user/user-mutations.ts
export const userMutations = {
user: {
type: new GraphQLObjectType({
name: 'CreateUser',
fields: {
create: {
type: UserType,
args: {
data: {
type: new GraphQLNonNull(UserInputType),
}
},
resolve: async (rootValue, { data }) => {
return Object.assign(data, {
id: '123'
});
}
}
}
})
}
};
My errors/output:
{
"errors": [
{
"message": "Cannot convert undefined or null to object",
"locations": [
{
"line": 36,
"column": 3
}
],
"path": [
"user"
]
}
],
"data": {
"user": null
}
}
Question 1: Is this way of structuring a mutation not optimal? Should I rather do something like:
mutation {
createUser(
name: "Foo Bar"
) {
id,
name
}
}
Question 2: If my first structure is fine, how can I fix the structure of my mutation on the server to create my user and return the values requested?
Edit: Here is my top level schema:
import { userQueries } from '../user/user-queries';
export const queries = {
...userQueries
};
import { userMutations } from '../user/user-mutations';
export const mutations = {
...userMutations
};
const rootQuery = new GraphQLObjectType({
name: 'RootQuery',
fields: queries
});
const rootMutation = new GraphQLObjectType({
name: 'RootMutation',
fields: mutations
});
export const schema = new GraphQLSchema({
query: rootQuery,
mutation: rootMutation
});

Why is this GraphQL query returning null? [duplicate]

This question already has answers here:
Why does a GraphQL query return null?
(6 answers)
Closed 3 years ago.
Schema:
const graphql = require('graphql');
const _ = require('lodash');
const {
GraphQLObjectType,
GraphQLString,
GraphQLInt,
GraphQLSchema
} = graphql;
const users = [
{ id: '23', firstName: 'Bill', age: 20 },
{ id: '47', firstName: 'Samantha', age: 21 }
]
const UserType = new GraphQLObjectType({
name: 'User',
fields: {
id: { type: GraphQLString },
firstName: { type: GraphQLString },
age: {type: GraphQLInt },
}
});
const RootQueryType = new GraphQLObjectType({
name: 'RootQuery',
fields: {
user: {
type: UserType,
args: { id: {type: GraphQLString} },
resolve(parentValue, args) {
return _.find(users, args.id);
}
}
}
});
module.exports = new GraphQLSchema({
query: RootQueryType,
});
Express:
const express = require('express');
const expressGraphQL = require('express-graphql');
const schema = require('./schema/schema')
const app = express();
app.use('/graphql', expressGraphQL({
schema,
graphiql: true,
}));
app.listen(4000, () => {
console.log('Listening');
});
Query:
{
user(id:"23") {
id,
firstName,
age
}
}
Trying to learn GraphQL and can't for the life of me figure out what's wrong with my query/schema.
You just need to change how you're calling lodash's find:
return _.find(users, { id: args.id });

Resources