argument Where of type xxxxxx is required, but it was not provided - apollo-server

I have this strange issue . maybe i missed something
i have two tables , Vehicles and purchases
when i try to query the vehicles via
query {
vehicles{
id
}
}
It returns data normally 👍
{
"data": {
"vehicles": [
{
"id": 29
}
]
}
}
But with this query
query {
purchase{
id
}
}
I recieve this error
{
"error": {
"errors": [
{
"message": "Field \"purchase\" argument \"where\" of type \"purchaseWhereUniqueInput!\" is required, but it was not provided.",
"locations": [
{
"line": 2,
"column": 3
}
],
here is my code : -
export const PaymentQuery =extendType({
type :"Query",
definition(t) {
t.crud.purchase({filtering : true , pagination : true , ordering : true , })
}
})
export const VehicleQuery = extendType({
type : "Query",
definition(t) {
t.crud.vehicles({filtering : true , pagination : true , ordering : true , });
}
})

I realized that nexusjs use naming convention to determine if the query should return a list or not !
changing the table name from purchase to purchases solves the problem

Related

Hasura GraphQL UPSERT mutation for nested objects

So I'm trying to construct a mutation for inserting/updating a record for a "Person" along with it's address, email, telephones information into multiple tables, using variables.
mutation insertPerson ($address: [adr_insert_input!]!, $emails: [emails_insert_input!]!) {
insert_info(objects: [{
f_name: "User1",
l_name: "Test"
address: {
data: $address,
on_conflict: {
constraint: person_id_pk,
update_column: [add_text_line1, zip_code]
}
},
emails: {
data: $emails,
on_conflict: {
constraint: person_id_pk,
update_column: [email_text]
}
}
}], on_conflict: {
constraints: person_pk,
update_columns: [f_name, l_name]
}) {
affected_rows
}
}
and my variables are set-up as follows...
{
"address": [{
"add_text_line1": "123 Main Street",
"zip_code": 50501
}],
"emails": [{
"email_text": "FirstLastName#email.com"
}]
}
This works as expected for me (with multiple values in emails array too), but I need to move the f_name & l_name values (whole Person object) into a variable as well. How do I achieve that?
I tried the below mutation this way, but this resulted into two separate inserts & empty values being passed...
mutation insertPerson ($person: person_insert_input!, $address: [adr_insert_input!]!){
insertData(objects: [
$person,
{
address: { data: $address }
}
]) { affected_rows }
}
This resulted to a two separate insertions... First person with empty address, then empty person with address.
How do I achieve the first mutation's result, while using Person Info as part of variables NOT hard-code it into the query itself?
Thank you!
You will need to pass the insert_info objects as the variables
mutation insertPerson ($info_objects: [insert_info_insert_input!]!) {
insert_info(objects: $info_objects, on_conflict: {
constraints: person_pk,
update_columns: [f_name, l_name]
}) {
affected_rows
}
}
And your variables will be an array of the info_objects
{info_objects: [{
f_name: "User1",
l_name: "Test"
address: {
data: [{
"add_text_line1": "123 Main Street",
"zip_code": 50501
}]
},
on_conflict: {
constraint: person_id_pk,
update_column: [add_text_line1, zip_code]
}
},
emails: {
data: [{
email_text: "FirstLastName#email.com"
}],
on_conflict: {
constraint: person_id_pk,
update_column: [email_text]
}
}
}]}

How to handle graphql errors on Apollo server? [duplicate]

In an express-graphql app, I have a userLogin resolver like so:
const userLogin = async ({ id, password }), context, info) => {
if (!id) {
throw new Error('No id provided.')
}
if (!password) {
throw new Error('No password provided.')
}
// actual resolver logic here
// …
}
If the user doesn't provide an id AND a password, it will throw only one error.
{
"errors": [
{
"message": "No id provided.",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"userLogin"
]
}
],
"data": {
"userLogin": null
}
}
How is it possible to throw multiple errors in the errors response array?
There is no way to throw an array of errors in JavaScript or otherwise have a single resolver reject with more than one error. A GraphQL response includes an errors array and not just a single error object because the total response can include multiple errors when those errors originate from different fields. Consider this schema and resolvers:
type Query {
a: String
b: String
c: String
}
const resolvers = {
Query: {
a: () => { throw new Error('A rejected') },
b: () => { throw new Error('B rejected') },
c: () => 'Still works!',
},
}
If you query all three fields...
query {
a
b
c
}
Your data will look something like this:
{
"errors": [
{
"message": "A rejected",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"a"
]
},
{
"message": "B rejected",
"locations": [
{
"line": 3,
"column": 3
}
],
"path": [
"b"
]
}
],
"data": {
"a": null,
"b": null,
"c": "Still works!"
}
}
This is because GraphQL supports partial responses. However, keep in mind that this works because the fields are nullable. If they were non-null, those errors would bubble up to the closest nullable parent field.
Here are some alternative approaches:
You can utilize formatError to change how the errors returned by GraphQL are displayed to the client. That means you can include any sort of extra information with your errors, like an error code or multiple error messages. A simple example:
// The middleware
app.use('/graphql', graphqlExpress({
schema: schema,
formatError: (error) => ({
message: error.message,
path: error.path,
locations: error.locations,
errors: error.originalError.details
})
}))
// The error class
class CustomError extends Error {
constructor(detailsArray) {
this.message = String(details)
this.details = details
}
}
// The resolver
const userLogin = async ({ id, password }), context, info) => {
const errorDetails = []
if (!id) errorDetails.push('No id provided.')
if (!password) errorDetails.push('No password provided.')
if (errorDetails.length) throw new CustomError(errorDetails)
// actual resolver logic here
}
Your response then looks more like this:
{
"errors": [
{
"message": "[No id provided.,No password provided.]",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"userLogin"
]
"errors" [
"No id provided.",
"No password provided."
]
}
],
"data": {
"userLogin": null
}
}
That said, there's something a bit unsavory about returning user-facing error messages alongside GraphQL validation errors. Another approach that some APIs have taken is to include an errors field alongside the actual mutation response. For example:
type Mutation {
userLogin: UserLoginResponse
}
type UserLoginResponse {
response: User
errors: [String!]
}
You can also use unions to achieve a similar effect:
type Mutation {
userLogin: UserLoginResponse
}
type Errors {
errors: [String!]!
}
union UserLoginResponse = User | Errors

Partial Update Mutations(GraphQL)

How can I be able to update a node with only one field change and leave the rest of the fields alone?
My User Type
type User {
id: ID!
user_id: String!
username: String!
email: String!
role: Role!
isVerified: Boolean!
}
My Input Types
input UserUpdateInput {
user_id: String
username: String
email: String
password: String
role: Role
isVerified: Boolean
}
input UserWhereUniqueInput {
id: ID
user_id: String
email: String
}
My Mutation type
type Mutation {
updateUser(data: UserUpdateInput!, where: UserWhereUniqueInput): User
}
My Resolver
function updateUser(root, args, context, info){
return context.db.mutation.updateUser({
data: args.data,
where: {
id: args.where.id
}
}, info)
}
This is the request am sending on the GraphQL playground
mutation{
updateUser(
data: {
isVerified: true
}
where:{
user_id : "afc485b"
}
)
{
isVerified
}
}
This is the error am getting
{
"errors": [
{
"message": "Cannot read property 'mutation' of undefined",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"updateUser"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"stacktrace": [
"TypeError: Cannot read property 'mutation' of undefined"
Someone help me. What am I missing?
After updating my server as suggested by Daniel Rearden on the answer section, am getting a new error
{
"message": "Cannot read property 'updateUser' of undefined",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"updateUser"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"stacktrace": [
"TypeError: Cannot read property 'updateUser' of undefined"
The error is the result of not correctly adding the db property to you context. Assuming you're still using version 1, your code should look something like this:
const { prisma } = require('./generated/prisma-client')
const server = new ApolloServer({
...
context: {
db: prisma,
},
})
First thing I notice is you GQL query is not correct.
Yours:
mutation{
updateUser(
data: {
isVerified: true
}
where:{
user_id : "afc485b"
}
)
{
isVerified
}
}
after the word "mutation" you set a name to the call, i.e.
"UpdateUser" but can literally be anything. for each part of the
where clause you need to make the check value an object, i.e.
where: { myProperty: {eq: "some value"}}
So your query should be more like this:
mutation UpdateUser {
updateUser(
data: {isVerified: true}
where:{user_id : {eq: "afc485b"}}
)
{
isVerified
}
}
Hope that helps a little... I didn't fully read the rest but thought this would help with the initial error you were getting.

GraphQL mutation issue

I am new in GraphQL. I am learning GraphQL.
My input is like below
mutation {
createEvent:{eventInput: {title: "A Test", description:"Does this work?", price:9.99, date:"2018-12-06T09:26:30.645Z"}
}
}
I am getting error like below
{
"errors": [
{
"message": "Syntax Error: Expected Name, found {",
"locations": [
{
"line": 2,
"column": 15
}
]
}
]
}
Well, I believe your createEvent mutation should return an object type. And for the object type , you have to specify at least one of the field from of return type for this Mutation.
It should be :
mutation {
createEvent(eventInput: {
title: "A Test"
description:"Does this work?"
price:9.99
date:"2018-12-06T09:26:30.645Z"
}){
someFieldInTheReturnType
}
}

How to filter table with multiple values against one field

I am new to AWS App Sync, I want to query which accepts multiple values against one field and return result based on the input. Is this possible?
listBookByName(bookID: [String], limit: Int, nextToken: String): listBookByNameConnection
You can use DynamoDB Batch Resolvers to accomplish this.
You would attach a resolvers to the listBookByName field. The request mapping template (Takes the GraphQL query and converts it to a DynamoDB query) would look like the following:
#set($ids = [])
#foreach($id in ${ctx.args.bookID})
#set($map = {})
$util.qr($map.put("id", $util.dynamodb.toString($id)))
$util.qr($ids.add($map))
#end
{
"version" : "2018-05-29",
"operation" : "BatchGetItem",
"tables" : {
"Books": {
"keys": $util.toJson($ids),
"consistentRead": true
}
}
}
Your response mapping template will then have to marshall the results into your listBookByNameConnection type.
Here is an example in the documentation where they have batchGet query which takes a list of identifiers, and returns a list of posts.
https://docs.aws.amazon.com/appsync/latest/devguide/tutorial-dynamodb-batch.html#single-table-batch
I have configured the setting as mentioned in the link. but it is returning null all the time.
type Query {
listBookByName(bookID: [String], limit: Int, nextToken: String): istBookByNameConnections
}
type listBookByNameConnections {
items: [Books]
}
My Resolver Mapping:
#set($ids = [])
#foreach($id in ${ctx.args.bookID})
#set($map = {})
$util.qr($map.put("id", $util.dynamodb.toString($id)))
$util.qr($ids.add($map))
#end
{
"version" : "2018-05-29",
"operation" : "BatchGetItem",
"tables" : {
"Books": {
"keys": $util.toJson($ids),
"consistentRead": true
}
}
}
Response Mapping:
$util.toJson($ctx.result.data.Books)
Query i used to check the response:
query get {
listBookByName(bookID:["JAVA","JUNIT"]){
items{
name
}
}
}
output :
{
"data": {
"listDriverTripsByName": null
}
}

Resources