How to use custom object types in Hasura actions? - hasura

I want to create an action with the following input:
input PurchaseInput {
user: UserInfo!
}
UserInfo is defined as an object:
type UserInfo {
accessToken: String!
userId: Int!
}
However Hasura doens't like this and returns a 400 on saving the action.
Is it possible to define custom input types in Hasura? I feel limited by String, Int, Float, Boolean etc.

You can absolutely create custom types like in your example
type UserInfo {
accessToken: String!
userId: Int!
}
So the error is of some other origin ( action response.... ).
Hasura only has a limitation of nested object types, for example, you can not do type definition like this in action :
type User {
userId: Int!
}
type UserInfo {
accessToken: String!
user: User!
}

Related

Why does using fetch data in nuxt3

I'm new to Nuxt. I have an error retrieving data. How can I fix it?
If you are using useFetch without specifying the type of the result, typescript cannot know, what type it is.
You could tell typescript that you are receiving a list of users from an endpoint and what a user looks like by doing something like this:
interface User {
id: number
name: string
email: string
}
const {data: users} = useFetch<User[]>('api.example.com');
useFetch returns the (parsed) body of the response in data. Looking at what the URL https://reqres.in/api/users really provides, you would probably want to access the data attribute of the body. You'd need something like this to get to the list of users:
interface User {
id: number
first_name: string
last_name: string
email: string
}
const { data: body } = useFetch<{ data: User[] }>('https://reqres.in/api/users')
const users = body.value?.data ?? []

How can I use the Prisma adapter for Next-Auth without email and emailVerified values

I am using next-auth with a custom provider and the Prisma adapter and I only want to store the values: id, name, country, avatar, and gender. However, I am getting this error:
[next-auth][error][adapter_error_createUser]
https://next-auth.js.org/errors#adapter_error_createuser
Invalid `p.user.create()` invocation in
.\node_modules\#next-auth\prisma-adapter\dist\index.js:6:38
3 exports.PrismaAdapter = void 0;
4 function PrismaAdapter(p) {
5 return {
→ 6 createUser: (data) => p.user.create({
data: {
name: [redacted],
wcaId: [redacted],
country: [redacted],
avatar: [redacted],
gender: [redacted],
email: undefined,
emailVerified: null
~~~~~~~~~~~~~
}
})
Unknown arg `emailVerified` in data.emailVerified for type UserCreateInput. Available args:
...
The profile object in my custom provider looks like this:
profile(profile) {
return {
id: profile.me.id,
name: profile.me.name,
country: profile.me.country_iso2,
avatar: profile.me.avatar.url,
gender: profile.me.gender,
};
},
Everything in my Prisma schema follows the example in https://next-auth.js.org/adapters/prisma#setup except the User model which is like so:
model User {
id String #id #default(cuid())
name String
country String #db.Char(2)
avatar String
gender String #db.Char(1)
accounts Account[]
sessions Session[]
// Temporary workaround:
email String? #unique
emailVerified DateTime? #map("email_verified")
}
In the error, the adapter appears to have added email and emailVerified to the data object so the temporary workaround I am using is adding email and emailVerified columns to my Prisma model as shown above. However, this is not ideal, and I would like to know how I can remove these unnecessary columns from my database as their values are always undefined and null.

AppSync #connection not making two-way connection

I'm using graphql through AWS AppSync. Given my models below I would expect when I successfully createClassroom with createClassroomInput that the teacherClassrooms would have a new Classroom associated to it and that the newly created Classroom would have a teacher associated to it.
The outcome, however, is that Classroom is created and the User is correctly associated with the new Classroom but the Classroom is not associated to the existing User.
type User #model {
id: ID!
userType: String!
teacherClassrooms: [Classroom] #connection(name: "TeacherClassrooms")
}
type Classroom #model {
id: ID!
teacher: User #connection(name: "TeacherClassrooms")
linkCode: String!
name: String!
}
export type CreateClassroomInput = {
id?: string | null,
linkCode: string,
name: string,
classroomTeacherId?: string | null,
};
So, if I query for listClassrooms, each classroom comes back with its associated User. But if I query for a User they do not have any classrooms in their teacherClassrooms array.
Do I need to updateUser when I create a new Classroom? My intuition, and my understanding of the docs, lead me to believe that AppSync would handle both updates when #connection is specified on a model property.
Or is this just a way of indicating to the backend that "for each Id in this property array assume it's of type X and when queried go fetch by Id against the corresponding table"?
Check your list query. I had the same issue and then realised that generated list query was missing relation attributes after I updated schema with name connection. In your case something like this
listUsers {
items {
id
teacherClassrooms {
items {
linkCode
id name
}
}
}
}
inside your listUsers query

How could graphql mutation resolver retrieve data to pass to children resolvers

Given the GraphQL Schema:
schema {
query: Query
mutation: Mutation
subscription: Subscription
}
type Mutation {
addPost(id: ID! author: String! title: String content: String url: String): Post!
updatePost(id: ID! author: String! title: String content: String url: String ups: Int! downs: Int! expectedVersion: Int!): Post!
deletePost(id: ID!): Post!
}
type Post {
id: ID!
author: String!
title: String
content: String
url: String
ups: Int
downs: Int
version: Int!
}
type Query {
allPost: [Post]
getPost(id: ID!): Post
}
type Subscription {
newPost: Post
}
We see that the addPost expects a Post type. So in the resolver function of addPost, we need to retrieve all the data that form a Post type from database, right? But what we are gonna do in our resolver function is to send a PutItem (ex.) request to Post table in database without getting all the data back from database. Then where do we get the data needed for Post type to pass to the children resolvers?
Is there some misunderstanding for me on how resolvers work?

Meteor - Validating new user document serverside

I'm having trouble with this seemingly trivial stuff, harrrr!
I have this user document:
userData = {
account: {
type: 'free'
},
profile: {
name: 'Artem',
},
username: 'aaa#gmail.com',
password: '123'
};
Which I'm sending client-side: Accounts.createUser(userData);
Then server side I want to check if account type equals 'free'. If it doesn't - I want to abort new user creation (and hopefully throw error client side)
There are 2 functions which I've found in the docs that presumably can help me do it:
Accounts.validateNewUser
Problem: it receives 'trimmed-down' user object which doesn't contain properties other than profile, username, password, email. Thus I cannot validate account.type as it doesn't exist on user object being validated.
Accounts.onCreateUser
Problem: it is called after a generic user object is created and there is no way I can cancel inserting new document in Users collection. It absolutely requires to return a user document. If I return undefined it throws errors on server:
Exception while invoking method 'createUser' Error: insert requires an argument
It also doesn't allow to throw method errors (as it's not a method) -> thus I cannot log error client side.
You can use Accounts.validateNewUser with little change to your data structure:
userData = {
profile: {
name: 'Artem',
account : {
type : 'free'
}
},
username: 'aaa#gmail.com',
password: '123'
};
Then you should be able to access data you need.
As far as I remember there were some discussion on meteor forum about removing profile field, that's why I'm solving this kind of problems in different way. For me Meteor.users is collection which should not be changed for sake of peace in mind - it could be changed by future version of meteor. My approach require to write more code in the beginning, but later it pays off, because you have place to store data about user and Meteor.users collection has docs with minimal amount of data.
I would use jagi:astronomy#0.12.1 to create schema and custom methods. In general I would create new collection UserAccounts with schema:
UserAccount = new Astro.Class( {
name: 'UserAccount',
collection: 'UserAccounts',
fields: {
'userId' : {type: 'string'},
'type' : {type: 'string', default:'free'}
},
} )
and add schema to Meteor.users :
User = new Astro.Class( {
name: 'User',
collection: Meteor.users,
fields: {
'services' : {type: 'object'},
'emails' : {type: 'array'}
},
methods:{
account : function(){
return UserAccounts.findOne({userId:this._id})
}
}
} )
The usage looks like this:
var user = Meteor.users.findOne();
user.account().type
In summary:
Accounts.onCreateUser : always allow to create user account and always create UserAccount which corresponds to it ( with field userId)

Resources