"Variable \"$input\" of required type \"CreateUserInput!\" was not provided." - graphql

I have been working on this for 3 days now and keep getting stuck. I am trying to register a new user and then have it push to a new page after registration.
The error that I am stuck on is the error above. Here is my frontend code.
const REGISTER_USER = gql`
mutation createUser($input: CreateUserInput!) {
createUser(input: $input) {
email
name
password
}
}
`
const Register = () => {
const context = useContext(AuthContext)
let navigate = useNavigate()
const [errors, setErrors] = useState([])
function registerUserCallback() {
console.log("Callback hit")
registerUser()
}
const {onChange, onSubmit, values} = useForm(registerUserCallback, {
name: '',
email: '',
password:'',
})
const [registerUser, {loading}] = useMutation(REGISTER_USER, {
update(proxy, {data: {createUser: userData}}) {
context.login(userData)
navigate('/Dashboard')
},
onError({graphQLErrors}) {
setErrors(graphQLErrors)
console.log("Error: " + graphQLErrors)
},
variables: {CreateUserInput: values}
})
Any information would be great!

Related

Unable to upload file graphql urql

I got empty object while uploading image. I follow all the step provided, but still can't make it solve. The error said "Variable "$file" got invalid value {}; Upload value invalid."
const client = createClient({
url: import.meta.env.VITE_BASE_API_URL ?? '',
exchanges: [
...defaultExchanges,
dedupExchange,
cacheExchange,
subscriptionExchange({
forwardSubscription: (operation) => ({
subscribe: (sink) => ({
unsubscribe: wsClient.subscribe(operation, sink),
}),
}),
}),
refocusExchange(),
multipartFetchExchange,
],
});
export const UPLOAD_WORKER_IMAGE = gql`
mutation setImage($file: Upload!, $workerId: UUID!) {
updateWorker(input: { patch: { imageUrl: $file }, id: $workerId }) {
}
}
}
`;
// Upload.tsx
const [, mutateWorkerImage] = useMutation<UpdateWorker>(UPLOAD_WORKER_IMAGE);
const file = bindData.avatarFile;
const { error: errorUploadImage, data } = await mutateWorkerImage({
workerId: dataWorker.createWorker.worker.id,
file: file,
});

Post Error with Apollo Client While Creating a New User

I am running into a POST http://localhost:4000/ 400 (Bad Request) Error.
I am trying to create a new user with the following frontend.
const REGISTER_USER = gql`
mutation Mutation(
$createUser: CreateUserInput!
) {
createUser(createUserInput: $createUserInput){
email
name
token
password
}
}
`
const Register = () => {
const context = useContext(AuthContext)
let navigate = useNavigate()
const [errors, setErrors] = useState([])
function registerUserCallback() {
console.log("Callback hit")
registerUser()
}
const {onChange, onSubmit, values} = useForm(registerUserCallback, {
name: '',
email: '',
password:'',
confirmPassword: '',
})
const [registerUser, {loading}] = useMutation(REGISTER_USER, {
update(proxy, {data: {registerUser: userData}}) {
context.login(userData)
navigate('/Dashboard')
},
onError({graphQLErrors}) {
setErrors(graphQLErrors)
console.log("Error: " + graphQLErrors)
console.log(graphQLErrors)
},
variables: {createUserInput: values}
})
However, the grapQLErrors is not even being console.logged for some reason. When I run the Mutation via Apollo Studio it works. Any information would be great!
Edit: Network Tab Screenshot:
Adding Code for my httpLink:
import { ApolloClient, InMemoryCache, createHttpLink } from "#apollo/client";
import { setContext } from "#apollo/client/link/context";
const httpLink = createHttpLink({
uri: 'http://localhost:4000'
})
const authLink = setContext((_, {headers}) => {
return {
headers: {
...headers,
authorization: localStorage.getItem('token') || ""
}
}
})
export const client = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache()
});
Edit: createUser Mutation seems to be the issue. This is the Network response error: ["GraphQLError: Unknown argument "createUserInput" on field "Mutation.createUser".","
#Mutation((returns) => User)
async createUser(#Arg('data') data:CreateUserInput, #Ctx() ctx: Context) {
const oldUser = await ctx.prisma.user.findFirst({ where: { email: data.email}})
if(oldUser) {
throw new ApolloError('A user is already registered with the email' + data.email, 'USER_ALREADY_EXISTS')
}
var encryptedPassword = await bcrypt.hash(data.password, 10)
const newUser = await ctx.prisma.user.create({
data: {
name: data.name,
email: data.email,
password: encryptedPassword
}
})
return {token: jwt.sign(newUser, 'supersecret')}
}
Here is a screen shot of my Preview in my Network...I really don't get it.
export class CreateUserInput {
#Field((type) => String)
name: string
#Field((type) => String)
email: string
#Field((type) => String)
password: string

How to use remove mutation in Relay server?

I work with an express graphql server, prepared for react-relay.
Queries and createPost mutation works correctly in graphiql interface.
There is a problem with removePost mutation.
Trying to use it, I get this responce:
"Cast to ObjectId failed for value \"{ id: '5db0026a76376e0f7c82d431'
}\" at path \"_id\" for model \"Post\".
Tell me please, what's wrong with removePost mutation. Thanks!
Post.js:
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
mongoose.connect("mongodb://localhost/relay-project", {
useNewUrlParser: true,
useUnifiedTopology: true
});
const Schema = mongoose.Schema;
const postSchema = new Schema({
title: String,
content: String
});
var PostModel = mongoose.model("Post", postSchema);
module.exports = {
getPosts: () => {
return PostModel.find().sort({_id: -1});
},
getPost: id => {
return PostModel.findOne({ _id: id });
},
createPost: post => {
return PostModel(post).save();
},
removePost: id => {
return PostModel.findByIdAndRemove(id);
}
};
Mutation.js:
const {
GraphQLObjectType,
GraphQLNonNull,
GraphQLString,
GraphQLID
} = require('graphql');
const {mutationWithClientMutationId} = require('graphql-relay');
const {Post} = require('./Post');
const PostModel = require('../model/Post');
const CreatePostMutation = mutationWithClientMutationId({
name: "CreatePost",
inputFields: {
title: {type: new GraphQLNonNull(GraphQLString)},
content: {type: new GraphQLNonNull(GraphQLString)}
},
outputFields: {
post: {
type: Post
}
},
mutateAndGetPayload: args => {
return new Promise((resolve,reject)=>{
PostModel.createPost({
title: args.title,
content: args.content
})
.then(post=>resolve({post}))
.catch(reject);
});
}
});
const RemovePostMutation = mutationWithClientMutationId({
name: "RemovePost",
inputFields: {
id: {type: GraphQLID}
},
outputFields: {
post: {
type: Post
}
},
mutateAndGetPayload: args => {
return new Promise((resolve,reject)=>{
PostModel.removePost({
id: args.id
})
.then(post=>resolve({post}))
.catch(reject);
});
}
});
const Mutation = new GraphQLObjectType({
name: "Mutation",
description: "kjhkjhkjhkjh",
fields: {
createPost: CreatePostMutation,
removePost: RemovePostMutation
}
});
module.exports = Mutation;
you have to convert your id to object id as mongodb save
i guess use below code for id
const toBase64 = (str: string) => {
return new Buffer(str.toString()).toString('base64')
}
const fromBase64 = (str: string) => {
return Buffer.from(str, 'base64').toString('ascii')
}
The working mutation is:
const RemovePostMutation = mutationWithClientMutationId({
name: "RemovePost",
inputFields: {
id: { type: new GraphQLNonNull(GraphQLString) },
},
outputFields: {
deleted: { type: GraphQLBoolean },
deletedId: { type: GraphQLString }
},
mutateAndGetPayload: async ({ id }, { viewer }) =>{
const { id: productId } = fromGlobalId(id);
const result = await PostModel.removePost(productId);
return { deletedId: id, deleted: true };
}
});
Cheers, Kiten

Followed GraphQL tutorial / Resolver object to query MySQL DB fails

Developing entirely local, I followed the tutorial here: https://scotch.io/tutorials/super-simple-graphql-with-node#toc-creating-the-graphql-server
Hardly any modification, only to restrict the focus to a "product" table. No "User" or "Recipe" table.
It appears the only issue I have now is retrieving the data from the MySQL DB.
Of course I've Googled and compared tutorials extensively. I've been through the code quite a bit as well to the point it's getting blurry.
If I change the "return" to {"name":"test"}, the data passes through to my local GraphQL dashboard perfectly.
models/index.js
'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.database, config.username, config.password, config);
}
fs.readdirSync(__dirname).filter(file => {
return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
}).forEach(file => {
const model = sequelize['import'](path.join(__dirname, file));
db[model.name] = model;
}); //console.log(db); Object.keys(db).forEach(modelName => { if (db[modelName].associate) { db[modelName].associate(db); } }); db.sequelize = sequelize; db.Sequelize = Sequelize;
module.exports = db;
'use strict';
module.exports = (sequelize, DataTypes) => {
const Product = sequelize.define('Product', {
name: DataTypes.STRING,
urlWordRef: DataTypes.STRING,
seoTitle: DataTypes.STRING,
seoDescription: DataTypes.STRING,
standardEquipment: DataTypes.STRING,
technicalSpecs: DataTypes.STRING
}, {});
Product.associate = function(models) {
// associations can be defined here
//Product.hasMany(models.RefProductOptions)
};
return Product;
};
// src/resolvers.js
const resolvers = {
Query: {
async products (root, { id }, { models }) {
return models.Products.findById(id) // *** THE LINE OF CODE WHICH FAILS ***
return {"name":"test"} // ** SUBSTITUTING THE ABOVE LINE WITH THIS - SUCCESS! ***
}
}
}
module.exports = resolvers
// src/schema.js
const { gql } = require('apollo-server')
const typeDefs = gql `
type Products {
id: Int!
name: String
urlWordRef: String
seoTitle: String
seoDescription: String
standardEquipment: String
technicalSpecs: String
}
type Query {
products(id: Int!): Products
}
`;
module.exports = typeDefs
// src/index.js
const { ApolloServer } = require('apollo-server')
const typeDefs = require('./schema')
const resolvers = require('./resolvers')
const models = require('../models')
const server = new ApolloServer({
typeDefs,
resolvers,
context: { models }
})
server.listen({port: 4000}).then(({ url }) => console.log('Server is running on localhost:4000'))
GraphQL query via the dashboard:
{
products(id: 1) {
name
}
}
I would expect that I can pass the id via the noted GRaphQL query above and get the correct table row result.
Alas, I'm ready to start coding with my forehead!
Error response in GraphQL:
{
"errors": [
{
"message": "Cannot read property 'findById' of undefined",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"products"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"stacktrace": [
"TypeError: Cannot read property 'findById' of undefined",
" at products (/home/bob/graphql-server/src/resolvers.js:6:26)",
" at field.resolve (/home/bob/graphql-server/node_modules/graphql-extensions/dist/index.js:140:26)",
" at resolveFieldValueOrError (/home/bob/graphql-server/node_modules/graphql/execution/execute.js:486:18)",
" at resolveField (/home/bob/graphql-server/node_modules/graphql/execution/execute.js:453:16)",
" at executeFields (/home/bob/graphql-server/node_modules/graphql/execution/execute.js:294:18)",
" at executeOperation (/home/bob/graphql-server/node_modules/graphql/execution/execute.js:238:122)",
" at executeImpl (/home/bob/graphql-server/node_modules/graphql/execution/execute.js:85:14)",
" at Object.execute (/home/bob/graphql-server/node_modules/graphql/execution/execute.js:62:35)",
" at /home/bob/graphql-server/node_modules/apollo-server-core/dist/requestPipeline.js:239:46",
" at Generator.next (<anonymous>)",
" at /home/bob/graphql-server/node_modules/apollo-server-core/dist/requestPipeline.js:7:71",
" at new Promise (<anonymous>)",
" at __awaiter (/home/bob/graphql-server/node_modules/apollo-server-core/dist/requestPipeline.js:3:12)",
" at execute (/home/bob/graphql-server/node_modules/apollo-server-core/dist/requestPipeline.js:218:20)",
" at Object.<anonymous> (/home/bob/graphql-server/node_modules/apollo-server-core/dist/requestPipeline.js:156:42)",
" at Generator.next (<anonymous>)",
" at fulfilled (/home/bob/graphql-server/node_modules/apollo-server-core/dist/requestPipeline.js:4:58)",
" at <anonymous>",
" at process._tickCallback (internal/process/next_tick.js:188:7)"
]
}
}
}
],
"data": {
"products": null
}
}

Graphql-js subscriptions unit tests not working as expected

I have written integration tests for graphql-js subscriptions, which are showing weird behavior.
My graphq-js subscription works perfectly in GraphiQL. But when the same subscriptions is called from unit test, it fails.
Ggraphql-Js object, with resolve function and subscribe function
return {
type: outputType,
args: {
input: {type: new GraphQLNonNull(inputType)},
},
resolve(payload, args, context, info) {
const clientSubscriptionId = (payload) ? payload.subscriptionId : null;
const object = (payload) ? payload.object : null;
var where = null;
var type = null;
var target = null;
if (object) {
where = (payload) ? payload.object.where : null;
type = (payload) ? payload.object.type : null;
target = (payload) ? payload.object.target : null;
}
return Promise.resolve(subscribeAndGetPayload(payload, args, context, info))
.then(payload => ({
clientSubscriptionId, where, type, target, object: payload.data,
}));
},
subscribe: withFilter(
() => pubSub.asyncIterator(modelName),
(payload, variables, context, info) => {
const subscriptionPayload = {
clientSubscriptionId: variables.input.clientSubscriptionId,
remove: variables.input.remove,
create: variables.input.create,
update: variables.input.update,
opts: variables.input.options,
};
subscriptionPayload.model = model;
try {
pubSub.subscribe(info.fieldName, null, subscriptionPayload);
} catch (ex) {
console.log(ex);
}
return true;
}
),
};
Subscription query
subscription {
Customer(input: {create: true, clientSubscriptionId: 112}) {
customer {
id
name
age
}
}
}
Mutation query
mutation {
Customer {
CustomerCreate (input:{data:{name:"Atif 50", age:50}}) {
obj {
id
name
}
}
}
}
Integration Test
'use strict';
const ws = require('ws');
const { SubscriptionClient } = require('subscriptions-transport-ws');
const { ApolloClient } = require('apollo-client');
const { HttpLink } = require('apollo-link-http');
const { InMemoryCache } = require('apollo-cache-inmemory');
const Promise = require('bluebird');
const expect = require('chai').expect;
const chai = require('chai').use(require('chai-http'));
const server = require('../server/server');
const gql = require('graphql-tag');
let apollo;
let networkInterface;
const GRAPHQL_ENDPOINT = 'ws://localhost:5000/subscriptions';
describe('Subscription', () => {
before(async () => {
networkInterface = new SubscriptionClient(
GRAPHQL_ENDPOINT, { reconnect: true }, ws);
apollo = new ApolloClient({
networkInterface ,
link: new HttpLink({ uri: 'http://localhost:3000/graphql' }),
cache: new InMemoryCache()
});
});
after(done => {
networkInterface.close() ;
});
it('subscription', async () => {
const client = () => apollo;
// SUBSCRIBE and make a promise
const subscriptionPromise = new Promise((resolve, reject) => {
client().subscribe({
query: gql`
subscription {
Customer(input: {create: true,
clientSubscriptionId: 112,
options: {where: {age: 50}}}) {
customer {
name
}
}
}
`
}).subscribe({
next: resolve,
error: reject
});
});
let execGraphQL;
// MUTATE
await execGraphQL(
`mutation {
Customer {
CustomerCreate (input:{data:{name:"Atif 21", age:50}}) {
obj {
id
name
}
}
}
}`
);
// ASSERT SUBSCRIPTION RECEIVED EVENT
expect(await subscriptionPromise).to.deep.equal({});
});
});
Issue Here
When test in run, payload in the resolve function contains global data, where as it should contain the subscription payload. So the code breaks.

Resources