Send null value to GraphQL mutation in Nest.js - graphql

I want send null value to mutation resolver. But i can't even mark input field via null.
My input type:
#InputType()
export class TableSettingsInput {
#Field()
allElements: null;
}
And i get an error, when i try compile my project:
Error: Undefined type error. Make sure you are providing an explicit type for the "allElements" of the "TableSettingsInput" class.
If i "explicit" this type like this:
#Field(() => null)
allElements: null;
I get other error:
Error: Cannot determine a GraphQL input type null for the "allElements". Make sure your class is decorated with an appropriate decorator.
How can i send null-value for my mutation?

Related

Spring Boot GraphQL: Expected type to be a GraphQLInputType, but it wasn't

I am trying to set up a GraphQL endpoint in Spring Boot, and when I try to run my App, I get the following error:
Expected type 'Order' to be a GraphQLInputType, but it wasn't! Was a type only permitted for object types incorrectly used as an input type, or vice-versa?
Here is my models.graphqls:
type Order {
id: String!
storeOrderId: String
connectionId: String
}
type Mutation {
createOrder(order: Order): Order
}
This is happening because you're trying to use a type for an input, which isn't allowed.
type Order {
Should be...
input Order {
So that the whole thing looks like:
I am trying to set up a GraphQL endpoint in Spring Boot, and when I try to run my App, I get the following error:
Expected type 'Order' to be a GraphQLInputType, but it wasn't! Was a type only permitted for object types incorrectly used as an input type, or vice-versa?
Here is my models.graphqls:
input Order {
id: String!
storeOrderId: String
connectionId: String
}
type Mutation {
createOrder(order: Order): Order
}
if it still does't work after use a input type, There may be other problems here.
the input java types should have public getters,
the input java types should also implement Serializable interface

How can I parse JSON data in Lighthouse?

I have notification table , where data field stored as json :
{"data":{"description":"Event Status has been changed to pending","event_id":19}}
I get this error
"errors": [
{
"debugMessage": "Expected a value of type \"String\" but received: {\"data\":{\"description\":\"Event Status has been changed to pending\",\"event_id\":19}}",
I have tried to add the following on notifications model:
public function getDataAttribute($data)
{
return json_decode($data, true);
}
But no solution.
I tried to use [String] in GraphQL schema but nothing.
If you want arbitrary JSON data to be returned as a string there are 2 options:
The first is to use a JSON scalar, you can either built your own or use a composer package. It wil encode the data to a valid JSON string.
The second option is to make sure you are returning just the JSON and not the decoded JSON. I'm assuming your data is already decoded to JSON because you are using model casts, if not you could just remove the json_decode call. You could add a getter to re-encode it back to JSON or add a getter to get the value from the attributes property on your model.
public function getRawDataAttribute(): string
{
return $this->attributes['data'];
}
// or
public function getRawDataAttribute(): string
{
return json_encode($this->data);
}
You can use this in your schema like this:
type MyType {
data: String! #rename(attribute: "raw_data")
}
But the first option is definitely the easiest and the best in my opinion because it correctly indicates in the schema the field contains JSON and handles the encoding (and decoding when used in inputs) for you.
Add this package for implementing JSON type to your app:
https://github.com/mll-lab/graphql-php-scalars
then add this line to your schema.graphql file:
scalar JSON #scalar(class: "MLL\\GraphQLScalars\\JSON")
After than you can easily use JSON type like this:
type MyType {
data: JSON! #rename(attribute: "raw_data")
}

can't use type 'object' for Type-GraphQL field types

I would like to create a GraphQL layer for my NestJs API. So based on this interface holding a key/value pairs
export interface Mapping {
id: string;
value: object;
}
I created a DTO acting as a return type for the GraphQL queries
#ObjectType()
export class MappingDTO {
#Field(() => ID)
id: string;
#Field()
value: object;
}
So when I want to find all mappings I would come up with this
#Query(() => [MappingDTO])
public async mappings(): Promise<Mapping[]> {
return this.mappingsService.getMappings();
}
Unfortunately I can't use object for the value field. I'm getting this error
NoExplicitTypeError: You need to provide explicit type for
MappingDTO#value !
When chaning the type e.g. to string no error gets thrown on startup. The thing is that I can't specify an explicit type because my MongoDB stores objects holding "anything".
How can I fix my resolver or DTO to deal with an object type?
Edit:
Same for the resolver decorator. When I have this
#Query(() => Object)
public async getValueByKey(#Args('id') id: string): Promise<object> {
return this.mappingsService.getValueByKey(id);
}
I get this error
Error: Cannot determine GraphQL output type for getValueByKey
Sounds like you should be using a custom JSON scalar. Like this one.
import { GraphQLJSONObject } from 'graphql-type-json'
This can then either be used directly in the field decorator:
#Field(() => GraphQLJSONObject)
value: object
or you can leave the decorator as #Field() and add the appropriate scalarsMap to the options you pass to buildSchema. See the docs for additional details.
Just to point out the fact that the whole idea of GraphQL is declarative data fetching.
Also you can define custom types in GraphQL the scalar types don't have object as option, but you can define a type of yourself like this.
type customObject {
keyOne: Int!
KeyTwo: String!
...
key(n): ...
}
and use this type in Interfaces, Query, Mutations:
export interface Mapping {
id: string;
value: customObject;
}
You might think that you will have to define every key of the object you are storing in the mongoDB in this type customObject, but you don't have to. this is where the GraphQL declarative data fetching comes in. You only define those fields in the type (customObject) that you want to use on the front end, you don't need to fetch the complete object from DB.

How to deal with nulls in GraphQL schema

I keep getting the "Cannot return null for non-nullable field Airline.id." error when FlightSchedule.operatingAirline is null (perfectly valid as per schema) and client queries for FlightSchedule.operatingAirline.id. How to fix this? Making Airline.id, Airline.code and Airline.name as nullable fixes this but is not the right way to solve this problem because if an Airline exist, these 3 fields will always exist too. Below is my schema:
type Airline {
id: String!,
code: String!,
name: String!
}
type FlightSchedule {
airline: Airline!
operatingAirline: Airline
}
And below is my query:
getFlightSchedules {
airline
{
id
code
name
}
operatingAirline
{
id
code
name
}
}
A field will resolve to null when an error is encountered while resolving it. This includes validation errors like the one you're encountering. From the spec:
If during ExecuteSelectionSet() a field with a non‐null fieldType throws a field error then that error must propagate to this entire selection set, either resolving to null if allowed or further propagated to a parent field.
If this occurs, any sibling fields which have not yet executed or have not yet yielded a value may be cancelled to avoid unnecessary work.
In other words, if a parent field is of a particular object type, and that type has a non-nullable field, and that field resolves to null, that parent field will also resolve to null. The parent field cannot return an object that is invalid (in this case because it had a non-null field return null), so the only thing it can do is return null. Of course, if the parent field itself is non-null, this behavior is propagated up the tree until a nullable field is finally encountered.
So, why are you getting that error? Because your resolver for operatingAirline is not returning null. It is returning some kind of object (either an incomplete airline object, an array, a string or something else) that GraphQL then effectively tries to coerce into the Airline type. The id field was requested, but it resolves to null based on the object returned by operatingAirline's resolver. Since the id was requested and returned null, the entire operatingAirline field fails validation and returns null.

How to return an object or null in GraphQL?

I have the following schema:
type User {
email: String!,
user_id: String!,
img: String!,
},
type Query {
getUser(user_id: String!): User
}
The schema reflects the fact that I must return an User object. However, I can not always do this, and sometimes I need to return null. For example, if I make a request to the DB, it will return return object or null (if the user was not found).
In my GraphQL schema, I set the type for a particular field. If I try to return a different type than what I set, I get an error. How do I allow a field to return either an object or null?
According to the spec:
By default, all types in GraphQL are nullable; the null value is a valid response for all of the above types. To declare a type that disallows null, the GraphQL Non‐Null type can be used.
In other words, types in GraphQL are nullable by default. So a field like
getUser: User
may return either a User object or null. A field like
name: String
may return either a String or null. Only by explicitly specifying a field as non-null (in SDL, by appending a ! to the type), can we specify that a field should never return null. For example:
name: String!
It's also important to note that the Promise returned in your resolver must resolve to either null or undefined in order to be coerced into a null value. In other words, if you return an empty object ({}), an empty array ([]) or some other value, GraphQL will treat this as you returning an object and not a null value!
In your schema, the email field on User is String!, meaning it cannot resolve to null. If you run a query like
query {
getUser(user_id: "1") {
email
}
}
and the resolver for getUser returns an empty object ({}), GraphQL will attempt to resolve email, return null for it and blow up because email is not supposed to be null! If, however, getUser resolves to null, none of the child fields will be resolved and you will not get any error.
According to Graphql - get full sub-object, or null if doesn't exist, you get the error you describe when you return empty object (i.e. {}) instead of null from your GraphQL function.
I had similar problem: I kept getting the "error: lack the require field" error in GraphQL response until I made sure I was actually returning null, not empty object.

Resources