GraphQL input type not found - javascript

I have a backend made with Express / Apollo Server / GraphQL / MongoDB / Mongoose and a frontend made with React.
I have my component where I want to do mutations and queries, I checked the connection between frontend and backend and it's good.
My mutation on backend:
createUser(input: SignupInput!): AuthUser!
input SignupInput {
name: String!
username: String!
email: String!
password: String!
}
The AuthUser return is an User! that has more fields but I think it's not necessary info.
On my frontend
const NEW_USER = gql`
mutation CreateUser($type: SignupInput!) {
createUser(input: $type) {
user {
id
}
}
}
`;
const [newTest, { data }] = useMutation(NEW_USER);
const onSubmit = (formData) => {
newTest({
variables: {
name: formData.name,
username: formData.username,
email: formData.email,
password: formData.password,
},
});
};
The network response for error 400:
"Variable \"$type\" of required type \"SignupInput!\" was not provided."
I don't really understand why this is happening, I've seen in other people's code that creating the variable with the name of the input type you have on the backend works.
If I try to destructure the SignInput! type and write {$name: !String, ...) I get this error:
Unknown argument \"name\" on field \"Mutation.createUser\".", locations: […], extensions: {…} }

newTest({
variables: {
input: {
name: formData.name,
username: formData.username,
email: formData.email,
password: formData.password,
}
},
});
Input was not passed in the mutation function.

Related

GraphQL: TypeError: Cannot read property of undefined

I have an Apollo GraphQL projects where I have created my own Query and Mutations. I have done using mock data and Query and Mutation works fine. But when I am trying to do with Sequelize ORM, I am getting the error
"TypeError: Cannot read property 'getListings' of undefined",
" at listings (/home/ayman/Desktop/apollo-graphql/graphql-app/functions/graphql.js:50:19)",
" at field.resolve (/home/ayman/Desktop/apollo-graphql/graphql-app/node_modules/graphql-extensions/dist/index.js:134:26)"
Query and Mutations in graphql.js:
const { ApolloServer, gql} = require("apollo-server-lambda");
const { Listing, User } = require("../db");
const jwt = require("jsonwebtoken");
const typeDefs = gql`
type Query {
listings: [Listing!]!
}
type Mutation {
createListing(input: CreateListingInput!): Listing!
}
input CreateListingInput {
title: String!
description: String
url: String!
notes: String
}
type Contact {
id: ID!
name: String!
company: Company
email: String
notes: String
}
type Company {
id: ID!
name: String!
logo: String
listings: [Listing!]!
url: String
}
type Listing {
id: ID!
title: String!
description: String
url: String!
notes: String
company: Company
contacts: [Contact!]!
}
`;
const resolvers = {
Query: {
listings(_, __, { user }) {
return user.getListings();
},
},
Mutation: {
createListing(_, { input }, { user }) {
return Listing.create({ ...input, userId: user.id });
},
},
};
const server = new ApolloServer({
typeDefs,
resolvers,
});
exports.handler = server.createHandler();
I have Sequilize along with Postgres database:
db.js
const Sequelize = require("sequelize");
const sequelize = new Sequelize(process.env.DB_CONNECTION_STRING, {
dialect: "pg",
dialectModule: require('pg'),
dialectOptions: {
ssl: true,
},
});
class User extends Sequelize.Model {}
User.init(
{
email: Sequelize.STRING,
password: Sequelize.STRING,
},
{
sequelize,
modelName: "user",
}
);
class Listing extends Sequelize.Model {}
Listing.init(
{
title: Sequelize.STRING,
description: Sequelize.TEXT,
url: Sequelize.STRING,
notes: Sequelize.TEXT,
},
{
sequelize,
modelName: "listing",
}
);
Listing.belongsTo(User);
User.hasMany(Listing);
exports.sequelize = sequelize;
exports.User = User;
exports.Listing = Listing;
Github Link
Run using netlify dev
Go to URL: http://localhost:8888/.netlify/functions/graphql
Sample GraphQL query
{
listings {
id
title
description
url
company {
name
url
}
}
}
return user.getListings();
you probably mean User, because user is undefined
I see, you are trying to access user object from context. Please check the context definition. It should return an object containing user object explicitly.

Grabbing the ID of a linked object with GraphQL, Apollo and React

I'm building an event managing database that handles RSVPs and links those RSVPs to a specific event. I'm using React, Apollo, GraphQL and Prisma as my stack and am having trouble correctly writing a mutation that would link an RSVP to an existing event. Still relatively new to the syntax, but I can't grab the event.id when I'm using the createRsvp mutation.
I'm able to pass the event.id down on the front-end through props, and I think a less-elegant way of receiving event.id in the args of the RSVP would be creating a hidden form with the event.id, but I KNOW there's got to be a way through graphQL. I've tried looking through the docs and various examples on grabbing the id from a different object. Any help is much appreciated :)
On the backend, here's my datamodel:
type Rsvp {
id: ID! #id
event: Event! #relation(link: INLINE)
firstName: String!
lastName: String!
email: String! #unique
company: String
jobTitle: String
mobile: String
dietary: String
}
type Event {
id: ID! #id
isPublished: Boolean
title: String!
startDate: String!
endDate: String!
description: String!
image: String
address: String
url: String!
suburb: String
postcode: String
state: String
country: String
guestLimit: Int
rsvps: [Rsvp]
}
The actual resolver for the Mutation.. I think I'm incorrectly retrieving the event.id here. My though process is that data: {...args} is first taking in the data from the RSVP form, and the connection to event is linking it to a certain event.
async createRsvp(parent, args, ctx, info) {
// 1. Query the event that is being registered for
const eventId = ctx.request.event.id;
// 2. Create the RSVP for this specific event
const rsvp = await ctx.db.mutation.createRsvp(
{
data: {
...args,
event: {
connect: { id: eventId }
}
}
},
info
);
console.log(rsvp);
return rsvp;
}
};
On the front end, this is what my Mutation looks like
const RSVP_MUTATION = gql`
mutation RSVP_MUTATION(
$email: String!
$firstName: String!
$lastName: String!
$company: String
$jobTitle: String
$mobile: String
$dietary: String
) {
createRsvp(
email: $email
firstName: $firstName
lastName: $lastName
company: $company
jobTitle: $jobTitle
mobile: $mobile
dietary: $dietary
) {
id
}
}
`;
and finally, the Mutation function in the form:
<Mutation mutation={RSVP_MUTATION} variables={({ id }, this.state)}>
{(createRsvp, { loading, error }) => (
<Form
onSubmit={async e => {
e.preventDefault();
const res = await createRsvp();
}}>
The error I receive in the console is "Uncaught (in promise) Error: GraphQL error: Cannot read property 'id' of undefined" which leads me to believe I'm incorrectly trying to access the event.id. Any tips or advice? Thanks again!
Divide and conquer
You can use /graphiql playground to test queries and mutations (API generally).
Testing this mutation:
mutation RSVP_MUTATION(
$email: String!
$firstName: String!
$lastName: String!
$company: String
$jobTitle: String
$mobile: String
$dietary: String
) {
createRsvp(
email: $email
firstName: $firstName
lastName: $lastName
company: $company
jobTitle: $jobTitle
mobile: $mobile
dietary: $dietary
) {
id
}
}
... with required variables you should quickly notice that you need to pass event id as variable, too. No special (more/less elegant), separate method required, this is a standard, query/mutation and variables, nothing more!!!
Just add eventId variable:
mutation RSVP_MUTATION(
$eventId: ID!
$email: String!
$firstName: String!
$lastName: String!
$company: String
$jobTitle: String
$mobile: String
$dietary: String
) {
createRsvp(
eventId: $eventId
email: $email
firstName: $firstName
lastName: $lastName
company: $company
jobTitle: $jobTitle
mobile: $mobile
dietary: $dietary
) {
id
}
}
Of course in resolver you'll get it within args, you can use f.e.
const { eventId, ...rest } = args;
const rsvp = await ctx.db.mutation.createRsvp(
{
data: {
...rest,
event: {
React variables can be passed f.e. by
variables={{ eventId: id, ...this.state }}

Object as input variable in mutation: GraphQL - Apollo - React

I have a React client-side project and a Node.js/GraphQL api in two separate repo's.
In my React app, I want to pass an object as variable type into my mutation. Here's how my mutation looks like:
export const CREATE_SPEAKER = gql`
input Expertise {
title: String!
domain: String!
}
mutation CreateSpeaker(
$name: String!
$age: String!
$nationality: String!
$avatar: String!
$expertise: Expertise!
) {
createSpeaker(
speakerInput: {
name: $name
age: $age
nationality: $nationality
avatar: $avatar
expertise: $expertise
}
) {
name
age
nationality
avatar
expertise {
title
domain
}
}
}
`;
In my Node.js project I have the following schema:
input SpeakerInput {
name: String!
age: String!
expertise: ExpertiseInput!
nationality: String!
avatar: String
}
input ExpertiseInput {
title: String!
domain: String!
}
And my resolver:
createSpeaker: async args => {
const { name, age, nationality, avatar, expertise } = args.speakerInput;
const newSpeaker = new Speaker({
name,
age,
nationality,
avatar,
expertise: {
title: expertise.title,
domain: expertise.domain
}
});
try {
return await newSpeaker.save();
} catch (error) {
throw ("Failed to create speaker:: ", error);
}
}
But I'm getting the following error when trying to create the speaker:
Uncaught (in promise) Invariant Violation: Schema type definitions not
allowed in queries. Found: "InputObjectTypeDefinition"
Any suggestions/ideas how to do this?
You can't define additional types when sending requests to a GraphQL service and you don't need to -- just use the types you've already defined on the server (in this case ExpertiseInput:
$expertise: ExpertiseInput!
However, there's no need to use this many variables in the first place:
mutation CreateSpeaker($input: SpeakerInput!) {
createSpeaker(speakerInput: $input) {
name
age
nationality
avatar
expertise {
title
domain
}
}
}

Select by given variable

My mongo db data:
{
username: 'gemmi',
age: 14,
id: 'xsxsxsxsxss'
}
type Query:
{
type Query {
getUser(id: String, username: String): User
}
}
resolver
getUser(root, args) {
return Meteor.users.findOne({ _id: args.id, username: args.username });
},
My question is how I can get user by given variable?
So it should return user when i type:
getUser(id: "xsxsxsxsxss", username:"gemmi") { username _id }
and also when I type:
getUser(username:"gemmi") { username _id }
You could replace the id with _id in the Query
{
type Query {
getUser(_id: String, username: String): User
}
}
And then you could simply use the args parameter to perform findOne call
getUser(root, args) {
return Meteor.users.findOne(args);
}
The args object depends on how you performed the query call. You should remember about replacing id with _id in your calls. In the first case, when you did getUser(_id: "xsxsxsxsxss", username:"gemmi"), then args object is { _id: 'xsxsxsxsxss', username: 'gemmi' }, however in second case, when you want to use getUser(username:"gemmi"), the args object is { username: 'gemmi' }, so in both cases you can use it as a query lookup in the findOne method call.
I suggest you add a input type for your query. And let meteor search for the respective user.
It could look like this:
Query:
`
type User {
id: ID!
username: String!
}
input UserInput {
id: ID
username: String
}
type Query {
getUser(user: UserInput!): User!
}
`
Resolver:
...
getUser(root, { user }) {
return Meteor.users.findOne(user);
}
...

GraphQL "Cannot return null for non-nullable" [duplicate]

This question already has answers here:
Why does a GraphQL query return null?
(6 answers)
Closed 3 years ago.
Trying to make my first graphQL server, here's what I have written so far.
https://gist.github.com/tharakabimal/7f2947e805e69f67af2b633268db0406
Following error pops up on GraphQL when I try to filter the users by username.
Error on GraphQL
The error occurs in the users field in UserQueriesQL.js.
Is there anything wrong the way I pass arguments on the resolve functions?
user: {
type: UserType,
args: {
username: {
name: 'username',
type: new GraphQLNonNull(GraphQLString)
}
},
resolve: function(parentValue, args) {
return User.find( args ).exec();
}
As I am beginner into GraphQL, even I ran into this issue. After going through each file individually I found that I forgot to import into my resolvers
import User from './User';
**import Post from './Post';**
const resolvers = [User, **Posts**];
Maybe this will help!
user: {
type: UserType,
args: {
username: { type: new GraphQLNonNull(GraphQLString) }
},
resolve: function(parentValue, args) {
return User.find( args ).exec(); // User.find({username: 'some name'}).exec();
// will work as matches your mongoose schema
}
Previously, in the args you are providing an an object with nested object username so,
args: { // this won't match your mongoose schema field as it's nested object
username: {
name: 'username',
type: new GraphQLNonNull(GraphQLString)
}
}
so when the user queries and provides args then
your args would be { username: { name: 'abcd' } }
// args = {username: {name: 'abcd'}}
and resolve() is executing User.find({username: {name: 'abcd'}}).exec();
/* searching for username{} object, but
your mongoose schema is username: String */
which doesn't match your database fields, which will always return an empty array [],also which will not match your GraphQL field type, as it is GraphQLNonNull
after viewing the gist the problem is with rootquery
the problem is with rootquery
let RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: () => ({
users: { type:UserQueries.users, resolve: UserQueries.users }
user: { type: UserQueries.user, resolve: UserQueries.user }
})
});

Categories