Can I create a single validation error bag for Lighthouse PHP, include GraphQL validation issues - laravel

Is there a way when using Lighthouse PHP to get the GraphQL validation error to appear side by side with the Laravel validation errors? Currently the graph QL validations cause a different type of error, before the Laravel error are run.
For example if I submit the following mutation:
mutation register(
password: 123456
) {
id
}
I will get back just an error back
{ "message": "Variable username not present. Expected type String",
"extensions": {
"category": "graphql"
}
}
Then when I submit:
mutation register(
username: somethingStupid
password: 123456
) {
id
}
Then I will get this error:
{ "message": "Validation failed for the field [register].",
"extensions": {
"validation": {
"username": [
"Username must be unique."
]
},
"password": [
"Password must contain letters and numbers"
]
},
"category": "validation"
},
}
For my front end I'd like them only to have to expect a single error bag, but this seems to require them to expect two different types of errors. Assuming my Laravel validations cover the schema definition, I would like for them never to see the GraphQl errors. Or am I missing the concept of GraphQL somehow?

Related

Use Postman to test Appsync Subscription

I have been able to successfully execute Appsync GraphQL queries and mutations from Postman. However, i'm struggling to connect to subscriptions which are websocket urls.
How can I achieve the same ?
Since Postman supports WebSockets testing GraphQL subscriptions is achievable as well. Such a testing requires two steps:
connection to a server,
sending a start message.
Establishing a connection:
Create a new WebSocket request.
Put your server URL ws:// or wss://.
Add custom header parameter Sec-WebSocket-Protocol: graphql-ws. Other headers may depend on your server configuration.
Press the "Connect" button.
When the connection is established we may start a subscription.
In the "New message" field put the command.
Press the "Send" button.
The start message should look like this:
{
"id":"1",
"payload": {
"operationName": "MySubscription",
"query": "subscription MySubscription {
someSubscription {
__typename
someField1
someField2 {
__typename
someField21
someField22
}
}
}",
"variables": null
},
"type": "start"
}
operationName is just the name of your subscription, I guess it's optional. And someSubscription must be a subscription type from your schema.
query reminds regular GraphQL syntax with one difference:
__typename keyword precedes every field list.
For example, the query from the payload in regular syntax looks like the following:
subscription MySubscription {
someSubscription {
someField1
someField2 {
someField21
someField22
}
}
}
Example message with parameters (variables):
{
"id":"1",
"payload": {
"operationName": "MySubscription",
"query": "subscription MySubscription($param1: String!) {
someSubscription((param1: $param1)) {
__typename
someField
}
}",
"variables": {
"param1": "MyValue"
}
},
"type": "start"
}
It also reminds regular GraphQL syntax as described above.
variables is an object with your parameters.
#Vladimir's answer is spot on. Adding a few notes for folks still having trouble.
Full document here # https://docs.aws.amazon.com/appsync/latest/devguide/real-time-websocket-client.html
Step 1 - establish connection:
make sure to base64 encode values in "header" and "payload" querystrings
header example:
{
"host":"example1234567890000.appsync-api.us-east-1.amazonaws.com",
"x-api-key":"da2-12345678901234567890123456"
}
payload: You can pass in empty payload
{}
Step 2 - register subscription:
Include the authorization in the message. Escape line feeds properly "\n" throws an error but "\\n" works. it throws the following error - misleading.
Don't forget to stringify value in "data" field.
{
"type": "error",
"payload": {
"errors": [
{
"errorType": "UnsupportedOperation",
"message": "unknown not supported through the realtime channel"
}
]
}
}
{
"id": "2",
"payload": {
"data": "{\"query\":\"subscription onCreateMessage { changeNotification{ __typename changeType from } }\",\"variables\":{}}",
"extensions":{
"authorization":{
"host":"example1234567890000.appsync-api.us-east-1.amazonaws.com",
"x-api-key":"da2-12345678901234567890123456"
}
}
},
"type": "start"
}

When I send a mutation request to chaskiq graphql endpoint I get "Data not found"

I have been using Chaskiq for some work but ran into an error.
I built from source on Ubuntu 20.04.
I got the graphql part working and query requests work. However, whenever I make a mutation request I seem to get this response:
{
"errors": [
{
"message": "Data not found",
"data": {}
}
]
}
Example mutation request I sent to get the response above:
mutation updateAppUser($appKey: String!, $options: Json!, $id: Int!) {
updateAppUser(appKey: $appKey, options: $options, id: $id) {
appUser {
id
name
email
}
}
}
I have the variables Query Variables as below:
{
"appKey": <My_APP_KEY>,
"options": {
"name": <Custom_Name>
},
"id": <My_ID>
}
Please help me know the solution to the problem.
Data not found is returned when the server does not found any record.
basically ActiveRecord::RecordNotFound , so you are probably trying to find the wrong record. check the logs to see what's happening

Insert more than one record using GraphQL Mutation

I would like to insert more than one record using GraphQL Mutation but it is giving error. here is the code which I have used to perform this.
input BusinessImageInput {
business_id: Int
image_url: String
}
mutation MyMutation($images: [BusinessImageInput!]) {
insert_business_images(objects: [$images]) {
affected_rows
}
}
And here is variable which i want to pass as paramter.
{"images": [
{
"business_id": 15,
"image_url": "https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTVzlb1cEw8E0LeLJzk9c0OQV-N387Nt2Kn5w&usqp=CAU"
},
{
"business_id": 15,
"image_url": "https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTVzlb1cEw8E0LeLJzk9c0OQV-N387Nt2Kn5w&usqp=CAU"
}
]
}
Here is the error
{
"errors": [
{
"extensions": {
"path": "$.query",
"code": "bad-request"
},
"message": "not a valid GraphQL query"
}
]
}
Please help me out.
There is one glaring issue in your code. This line
insert_business_images(objects: [$images]) {
should be
insert_business_images(objects: $images) {
Notice the removed square brackets.
If that does not help, then we'll need more information, such as:
what error do you get?
which implementation of GraphQL are you using both client-side and server-side?
what does the GraphQL code (and possibly resolvers) look like on the server? You have only given us the client-side of the equation.
It's as simple as
mutation MyMutation($images: [BusinessImageInput!]) {
insert_business_images(images: $images) {
or
mutation MyMutation($objects: [BusinessImageInput!]) {
insert_business_images(objects: $objects) {
depends on server insert_business_images mutation definition, the name of argument (images or objects ?) - use explorer ... and [as you can see above] usually input arg and variable are same-named, they only differs with $ prefix.
https://graphql.org/learn/queries/#variables
Also you must follow server input types.

Is it possible to accessing GraphQL validation errors from a Relay mutation?

I'm somewhat new to GraphQL, so, still piecing all moving parts together in my head.
On my server side I'm using TypeGraphQL which uses class-validator to perform validation of the queries coming in. On the client side I'm using Relay. When the validations fail, my commitMutation call in Relay calls onError and passes a string representation of the error, but the actual response from the server looks like this:
{
"errors": [
{
"message": "Argument Validation Error",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"updateCurrentUser"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"validationErrors": [
{
"target": {
"name": "ueoa",
"nickname": "ueoa",
"email": ""
},
"value": "",
"property": "email",
"children": [],
"constraints": {
"isEmail": "email must be an email"
}
}
],
"stacktrace": [
"Error: Argument Validation Error",
" at Object.validateArg (C:\\Users\\pupeno\\Documents\\Flexpoint Tech\\imok\\node_modules\\type-graphql\\dist\\resolvers\\validate-arg.js:24:15)",
" at runMicrotasks (<anonymous>)",
" at processTicksAndRejections (internal/process/task_queues.js:97:5)",
" at async Promise.all (index 0)"
]
}
}
}
],
"data": null
}
In this case, I left the email blank and thus on errors[0].extensions.exception.validationErrors[0].constraints.isEmail I have the error: "email must be an email".
Is there a way for Relay to let me access this structure to turn this errors into UI errors for the user? Or are these errors the equivalent of a 500 and I should implement my own separate error handling (equivalent of a 401)?
I do most of my validation on the client, but uniqueness can only be on done on the server and I'm trying to figure out the protocol between the two.
I don't know much about relay but I have used Typegraphql for sometime. What I can tell is that error from class-validator is nested differently from standard error (I am talking about throw new Error('this will be different'). I would advice for you to have an error formatter function on back-end so that regardless of type of error is thrown you can just return a standard graphql error. In apollo server there is option for formating error I believe other graphql servers has one too. Here is how it looks
const apolloServer = new ApolloServer({
formatError: (error) => error,
});
If class-validator's error is thrown error above will be ArgumentValidationError So if error is instance of ArgumentValidationError you need to proper format it and return to the client with all constraints values extracted and appended on message field. In this way all errors will behave the same on front-ent.
It is really hard to handle the error when it comes to graphQL as at the end of the result you will going to get 200 OK responses.
These errors you are getting are the INTERNAL SERVER ERROR, Equivalent to 500.
So, in this case, you'll need to handle it on your own.
As Nux wrote, Apollo has error handling modules, you can refer it from here This might be helpful.
Also As you mention that you are doing most of the validation from the client end, it is not a good idea to do validations only client-side as it can be brack and might become the Major breach.

How to fix "Syntax Error: Expected Name, found String \"query\"" in GraphQL

I'm trying to test the GraphQL server I built, by sending GraphQL queries to the server using Postman.
It works when I'm using raw radio button, but when I'm trying to use GraphQL radio button, it returns "message": "Syntax Error: Expected Name, found String \"query\"".
I have tried to change the syntax: mainly add or delete curly braces but nothing happened.
The query I sent in raw mode (working):
{
person(id:"123456789") {
personal_info {
address
}
}
}
The query I sent in GraphQL mode:
QUERY:
query getPerson ($id: String){
person(id: $id){
personal_info {
address
}
}
}
GRAPHQL VARIABLES:
{
"id": "123456789"
}
I expect to get the data I asked for, but I get the error message:
{
"errors": [
{
"message": "Syntax Error: Expected Name, found String \"query\"",
"locations": [
{
"line": 1,
"column": 2
}
]
}
]
}
I had the same problem. During researching I have found the next answer on stackoverflow, thanks #gbenga_ps.
Resolved by adding the correct header to Postman request:
Body of request should be something like next:
{
courses {
title
}
}
If incorrect content-type set, error like next happened:
{
"errors": [
{
"message": "Syntax Error: Expected Name, found String \"query\"",
"locations": [
{
"line": 1,
"column": 2
}
]
}
]
}

Resources