GraphiQL Mutation: How can I ignore other objects in query variables - postgresql

Currently having hard time setting up my end points clerk to hasura.
I am absolute new to this platform specially at GraphiQL and just following documentations and youtube video
What I am trying to do is import/insert specific data i neeed only from clerk. Here's the sample query variables:
{
"data": {
"birthday": "",
"created_at": 1654012591514,
"email_addresses": [
{
"email_address": "example#example.org",
"id": "idn_29w83yL7CwVlJXylYLxcslromF1",
"linked_to": [],
"object": "email_address",
"verification": {
"status": "verified",
"strategy": "ticket"
}
}
],
"external_accounts": [],
"external_id": "567772",
"first_name": "Example",
"gender": "",
"id": "user_29w83sxmDNGwOuEthce5gg56FcC",
"last_name": "Example",
"last_sign_in_at": 1654012591514,
"object": "user",
"password_enabled": true,
"phone_numbers": [],
"primary_email_address_id": "idn_29w83yL7CwVlJXylYLxcslromF1",
"primary_phone_number_id": null,
"primary_web3_wallet_id": null,
"private_metadata": {},
"profile_image_url": "https://www.gravatar.com/avatar?d=mp",
"public_metadata": {},
"two_factor_enabled": false,
"unsafe_metadata": {},
"updated_at": 1654012591835,
"username": null,
"web3_wallets": []
},
"object": "event",
"type": "user.created"
}
What I only need to this object is content inside of the "data" is: created_at, first_name, user_id, updated_at, profile_image_url
The GraphiQL Query I did is:
mutation CreateUser(
$created_at: String,
$first_name: String,
$user_id: String,
$updated_at: String,
$profile_image_url: String
)
{
insert_users_one(object:
{
created_at: $created_at,
first_name: $first_name,
user_id: $user_id,
updated_at: $updated_at,
profile_image_url: $profile_image_url,
}) {
created_at
first_name
user_id
updated_at
profile_image_url
}
}
Which throwing error of:
{
"errors": [
{
"extensions": {
"code": "validation-failed",
"path": "$"
},
"message": "unexpected variables in variableValues: object, type, data"
}
]
}
I tried using other method like this:
mutation CreateUser($data: users_insert_input!) {
insert_users_one(object: $data) {
created_at
first_name
user_id
updated_at
profile_image_url
}
}
But it is still having error because of object and type fields
{
"errors": [
{
"extensions": {
"code": "validation-failed",
"path": "$"
},
"message": "unexpected variables in variableValues: object, type"
}
]
}
Here's a sample of GraphQL type:
//is this how you break things down?
type Mutation {
data(
created_at: Int
first_name: String
id: String
updated_at: Int
profile_image_url: String
): Data
}
//this is what i will send in the database, things that I only need
type Verification {
status: String
strategy: String
}
type EmailAddresses {
email_address: String
id: String
object: String
verification: Verification
linked_to: [String]
}
type Data {
birthday: String
created_at: Int
external_id: String
first_name: String
gender: String
id: String
last_name: String
last_sign_in_at: Int
object: String
password_enabled: Boolean
primary_email_address_id: String
primary_phone_number_id: String
primary_web3_wallet_id: String
profile_image_url: String
two_factor_enabled: Boolean
updated_at: Int
username: String
web3_wallets: [String]
phone_numbers: [String]
external_accounts: [String]
email_addresses: [EmailAddresses]
}
type AutogeneratedMainType {
object: String
type: String
data: Data
}
I was expecting based on documents, It will ignore aren't included data.
Visit Github Discussions here

Context about the error
This is error you are receiving is based on this graphql spec - https://spec.graphql.org/June2018/#sec-Input-Objects . More over there is also a different spec for validation against variables here - https://spec.graphql.org/June2018/#sec-All-Variables-Used
TLDR; Using variable which isn’t defined in operation, will result into “unexpected variableValues” error. In your case apart from data , you have type and object as variables in your query variables object which is not defined in operation itself. Remember that query variables is an “object” expecting the variable key-values in it.
Workaround
Cleanest way to do this is to sanitize your object (which you will pass in query variables) by either creating a new object from it and passing data to it or either you remove the unnecessary fields from it which are not defined in operation. You could just delete the properties of that object. Consider yourObject containing data,type and object fields. Then you can do delete yourObject.type and delete yourObject.object. And then pass it.
This workaround is intended for client side code. But there's no exception for graphiQL explorer as that error would be thrown upon undefined variables in operation. If trying via graphiQL explorer, you would manually need to not pass those variables in query variables scope.
Conclusion
This behavior is in compliant with this graphql spec and not with Hasura directly, so we would suggest you to go through those graphql spec links and understand the aspect of it.

Related

GORM don't create many2many associations

I have model:
type Book struct {
gorm.Model
Title string `json:"title"`
Author string `json:"author"`
Description string `json:"description"`
Category string `json:"Category"`
Publisher string `json:"publisher"`
AuthorsCard []*AuthorsCard `gorm:"many2many:book_authorscard; "json:"authorscard"`
}
type AuthorsCard struct {
gorm.Model
Name string `json:"name"`
Age int `json:"age"`
YearOfBirth int `json:"year"`
Biography string `json:"biography"`
}
After db.AutoMigrate(&models.Book{}, &models.AuthorsCard{})
I have a creation function:
func TestCreate() {
var testbook = models.Book{
Title: "Test",
Author: "tst",
AuthorsCard: []*models.AuthorsCard{
{
Age: 23,
Name: "test",
YearOfBirth: 1999,
Biography: "23fdgsdddTEST",
},
},
Description: "something",
}
db.Preload("AuthorsCard").Find(&models.Book{})
db.Create(&testbook)
}
despite That AuthorsCard has some data in it, I receive this as a response:
{
"ID": 78,
"CreatedAt": "2022-06-23T13:10:58.01629+03:00",
"UpdatedAt": "2022-06-23T13:10:58.01629+03:00",
"DeletedAt": null,
"title": "Test",
"author": "tst",
"description": "something",
"Category": "",
"publisher": "",
"authorscard": null
}
As you can see "authorscard" is null.
How can I save "authorscard" to the database?
I used Gorm + postgresql and also I sent a few request with postman, results are the same - Authors card is null
The code is working when it's called in the correct order:
func TestCreate() {
db := getDB()
db.AutoMigrate(&Book{}, AuthorsCard{})
var testbook = Book{
Title: "Test",
Author: "tst",
AuthorsCard: []*AuthorsCard{
{
Age: 23,
Name: "test",
YearOfBirth: 1999,
Biography: "23fdgsdddTEST",
},
},
Description: "something",
}
// 1. Create your testbook.
db.Create(&testbook)
// 2. Store it into a variable:
var b1 *Book
db.Preload("AuthorsCard").Find(&b1)
fmt.Println(b1.AuthorsCard[0].Age)
fmt.Println(b1.AuthorsCard[0].Name)
fmt.Println(b1.AuthorsCard[0].YearOfBirth)
fmt.Println(b1.AuthorsCard[0].Biography)
}
prints:
23
test
1999
23fdgsdddTEST
Also your JSON export might fail since you pass a pointer to AuthorCard and the marshalling not always works properly in those cases. However, GORM does the right job here.
Static check also gave me some hints here:
type Book struct {
gorm.Model
Title string `json:"title"`
Author string `json:"author"`
Description string `json:"description"`
Category string `json:"Category"`
Publisher string `json:"publisher"`
AuthorsCard []*AuthorsCard `gorm:"many2many:book_authorscard" json:"authorscard"` // wrong space
}

What is a wrapper type in Graphql?

I am learning the official GraphQl doc.
When I come to the chapter introspection link here
I have encounter something called wrapper type.
input:
{
__type(name: "Droid") {
name
fields {
name
type {
name
kind
}
}
}
}
Output:
{
"data": {
"__type": {
"name": "Droid",
"fields": [
{
"name": "id",
"type": {
"name": null, # here
"kind": "NON_NULL"
}
},
{
"name": "name",
"type": {
"name": null, # here
"kind": "NON_NULL"
}
},
{
"name": "friends",
"type": {
"name": null, # here
"kind": "LIST"
}
},
{
"name": "friendsConnection",
"type": {
"name": null, # here
"kind": "NON_NULL"
}
},
{
"name": "appearsIn",
"type": {
"name": null, # here
"kind": "NON_NULL"
}
},
{
"name": "primaryFunction",
"type": {
"name": "String", # normal here
"kind": "SCALAR"
}
}
]
}
}
}
The article claims the name of those type of fields of type is NULL because it's a " wrapper" type of kind NON_NULL
Could someone explain what is exactly a wrapper type? Better provide an example or code to explain why primaryFunction has a name but others do not.
From the spec:
All of the types so far are assumed to be both nullable and singular: e.g. a scalar string returns either null or a singular string.
A GraphQL schema may describe that a field represents list of another types; the List type is provided for this reason, and wraps another type.
Similarly, the Non-Null type wraps another type, and denotes that the resulting value will never be null (and that an error cannot result in a null value).
These two types are referred to as “wrapping types”; non‐wrapping types are referred to as “named types”. A wrapping type has an underlying named type, found by continually unwrapping the type until a named type is found.
A wrapping type wraps another type, which itself may also be a wrapping type. However, as you "unwrap" each wrapping type, eventually you have to hit a named type that all those wrapping types are associated with. In other words, wrapping types can never be used by themselves. A wrapping type always has exactly one named type it's associated to.
In introspection, to determine what type the wrapping type is wrapping, use the ofType field:
{
__schema {
types {
name
ofType {
name
}
}
}
}
You can add additional levels to potentially "unwrap" types further:
{
__schema {
types {
name
ofType {
name
ofType {
name
}
}
}
}
}
As to why introspection doesn't show a name for these types, it's because the spec specifically prohibits it. Take a look at the section for the List type:
Lists represent sequences of values in GraphQL. A List type is a type modifier: it wraps another type instance in the ofType field, which defines the type of each item in the list.
Fields
kind must return __TypeKind.LIST.
ofType: Any type.
All other fields must return null.
Here is some snippet from a tutorial I have done the other day. It represents a type wrapped with GraphQLNonNull operator (it's for the server side):
const ContestStatusType = require('./contest-status')
const NameType = require('./name')
module.exports = new GraphQLObjectType({
name: 'ContestType',
fields: {
id: { type: GraphQLID },
description: { type: GraphQLString },
status: { type: new GraphQLNonNull(ContestStatusType) },
createdAt: { type: new GraphQLNonNull(GraphQLString) },
createdBy: { type: new GraphQLNonNull(GraphQLString) },
names: {
type: new GraphQLList(NameType),
resolve(obj, args, { loaders, pgPool }) {
return loaders.namesForContestIds.load(obj.id);
return pgdb(pgPool).getNames(obj)
}
}
}
});

Need help to debug this updateLink resolver

I need to implement an updateLink to my graphQL server, but it keeps throwing 'id is not defined' error. The server doesn't have a database yet, only an array for practice purpose.
I have defined the schema for the mutation for update, also wrote the resolver, but it just didn't work.I have looked into the apollo document, it seems my resolver and schema are correct.
The following is the resolver
updateLink:(parent,args)=>{
const link = {
id:args.id,
description:args.description,
url:args.url,
}
links[Number(id)]=link
return link
}
},
The following the schema
type Query {
info: String!
feed: [Link!]!
link(id:ID!):Link
}
type Mutation {
post(url: String!, description: String!): Link!
updateLink(id:ID!,url:String!, description: String!): Link
delete(id:ID!):Link
}
type Link {
id: ID!
description: String!
url: String!
}
The expected outcome should be the update of the server of the link array, but I got the following error instead.
{
"data": {
"updateLink": null
},
"errors": [
{
"message": "id is not defined",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"updateLink"
]
}
]
}
You reference a variable called id here:
links[Number(id)]=link
but you have not defined a variable with that name as the error indicates. I would suggest adding a linter to your project to help you catch errors like that.

How to Generate A Slug on AppSync Mutation

I have a mutation to create a new Event. However I want to be able to reference/get that Event using a friendly id or slug instead of the DynamoDB primary key of id. Ideally this would use the city field from the input to generate the slug. However each slug must be unique per author
How can I generate a friendly slug in my mutation that is based on the city name and unique (per author) ?
Schema
type Event {
id: ID!
subtitle: String!
city: String!
author: String!
created: AWSDateTime
}
mutation.CreateEvent
#set( $attribs = $util.dynamodb.toMapValues($ctx.args.input))
#set( $attribs.author = $util.dynamodb.toDynamoDB($ctx.identity.username))
#set( $attribs.created = $util.dynamodb.toDynamoDB($util.time.nowFormatted("yyyy-MM-dd HH:mm:ssZ")))
{
"version": "2017-02-28",
"operation": "PutItem",
"key": {
"id": $util.dynamodb.toDynamoDBJson($util.autoId()),
},
"attributeValues": $util.toJson($attribs),
"condition": {
"expression": "attribute_not_exists(#id)",
"expressionNames": {
"#id": "id",
},
},
}
```

updating elements in nested arrays

I think I know how to get to my object, I just can't figure out how to update it's values. I am getting this error:
{
"name": "MongoError",
"message": "cannot use the part (tasks of families.25.tasks.name) to traverse the element ({tasks: [ { name: \"Correct Name\", isSelected: false, completedBy: null, submittedBy: \"web-user\", completedOn: null, submittedOn: new Date(1505857352113), message: \"Please correct family name to follow HOK standard.\", assignedTo: \"konrad.sobon\", _id: ObjectId('59c18f8991d1929d43f22f8c') }, { name: \"Some other task\", isSelected: false, completedBy: null, submittedBy: \"web-user\", completedOn: null, submittedOn: new Date(1505917405948), message: \"Yet again, testing this.\", assignedTo: \"konrad.sobon\", _id: ObjectId('59c279fb8388cb58e7454bf6') } ]})",
"driver": true,
"index": 0,
"code": 16837,
"errmsg": "cannot use the part (tasks of families.25.tasks.name) to traverse the element ({tasks: [ { name: \"Correct Name\", isSelected: false, completedBy: null, submittedBy: \"web-user\", completedOn: null, submittedOn: new Date(1505857352113), message: \"Please correct family name to follow HOK standard.\", assignedTo: \"konrad.sobon\", _id: ObjectId('59c18f8991d1929d43f22f8c') }, { name: \"Some other task\", isSelected: false, completedBy: null, submittedBy: \"web-user\", completedOn: null, submittedOn: new Date(1505917405948), message: \"Yet again, testing this.\", assignedTo: \"konrad.sobon\", _id: ObjectId('59c279fb8388cb58e7454bf6') } ]})"
}
My collection looks like this:
My request handler looks like this:
module.exports.updateTask = function (req, res) {
var id = req.params.id;
var taskId = mongoose.Types.ObjectId(req.params.taskid);
Families
.update(
{ _id: id, 'families.tasks._id': taskId},
{ $set: {
'families.$.tasks.name': req.body.name,
'families.$.tasks.message': req.body.message,
'families.$.tasks.assignedTo': req.body.assignedTo}}, function(err, result){
if(err) {
res
.status(400)
.json(err);
} else {
res
.status(202)
.json(result);
}
}
)
};
Any help will be appreciated.
Unfortunately the positional operator $ cannot be used for nested arrays:
The positional $ operator cannot be used for queries which traverse more than one array, such as queries that traverse arrays nested within other arrays, because the replacement for the $ placeholder is a single value.
https://docs.mongodb.com/manual/reference/operator/update/positional/
You might have to consider restructuring your documents.