Custom GraphQL types¶
Table of contents
Introduction¶
You can add custom GraphQL types in Hasura that you can utilise for defining your actions.
Limitations
It is currently not possible to define Interfaces
and Union types
as custom types
Object types¶
The most basic components of a GraphQL schema are object types, which just represent a kind of object a GraphQL query can return, and what fields it has. In the GraphQL SDL, we might represent it like this:
type UserInfo {
accessToken: String!
userId: Int!
}
This is an object type called UserInfo
that has two fields:
accessToken
: This field is of typeString!
(non-nullableString
)userId
: This field is of typeInt!
(non-nullableInt
)
Hasura supports nested objects. For example, you can define a type like the following:
type UserInfo {
accessToken: String!
userId: Int!
user: UserObj!
}
type UserObj {
name: String!
favFood: String!
isAdmin: Boolean!
}
Recursive nested objects are also supported. For example, you can use the following type:
type UserObj {
name: String!
favFood: String!
isAdmin: Boolean!
friends: [UserObj]!
}
Relationships¶
Custom object types can be connected to the rest of the graph by setting up action relationships with tables/views.
For example, given the object type:
type UserInfo {
accessToken: String!
userId: Int!
}
and tables:
user (id int, name text)
order (id int, user_id int, ...)
We can create:
- an object relationship called
loggedInUser
between theUserInfo
object type and theuser
table via theUserInfo.userId
anduser.id
fields. - an array relationship called
userOrders
between theUserInfo
object type and theorder
table via theUserInfo.userId
andorder.user_id
fields.
The object type will now be modified as:
type UserInfo {
accessToken: String!
userId: Int!
loggedInUser: user
userOrders: [order]
}
Note
Only fields with non-list scalar types (e.g. Int
, String
) can be used
to define relationships
Limitations
Hasura has the following limitations for relationship in nested object types:
For nested objects, relationships can only be defined for top-level fields. For example, for the following type definition:
type UserInfo { accessToken: String! userId: Int! user: UserObj! } type UserObj { name: String! favFood: String! isAdmin: Boolean! }
relationships can only be defined using
accessToken
anduserID
, you cannot usename
,favFood
orisAdmin
fields in a relationship definition.For
async
actions, you cannot have nested object types and relationships in the same action.
Input types¶
You can pass complex objects as arguments to queries and mutations. This is particularly valuable in cases where you might want to pass in a whole object to be created. In the GraphQL SDL, input types look exactly the same as regular object types, but with the keyword input instead of type:
input LoginInfo {
username: String!
password: String!
}
A field of an input type could be a scalar
, an enum
or another input type.
Scalar types¶
A GraphQL object type has a name and fields, but at some point those fields have to resolve to some concrete data. That’s where the scalar types come in: they represent the leaves of the query.
Inbuilt scalars¶
Hasura comes with some default GraphQL scalars that you can directly start using while defining your actions:
Int
: A signed 32‐bit integer.Float
: A signed double-precision floating-point value.String
: A UTF‐8 character sequence.Boolean
: true or false.ID
: The ID scalar type represents a unique identifier, often used to refetch an object or as the key for a cache. The ID type is serialized in the same way as a String; however, defining it as an ID signifies that it is not intended to be human‐readable.
Custom scalars¶
Hasura allows you to define custom scalars. For example, if you want to define
a scalar called Date
, you can define it like.
scalar Date
These scalars can be used as arguments of queries and mutations or as fields of object types and input types.
Postgres scalars
Postgres base types are implicitly made available as GraphQL scalars; there is no need to declare them separately. For example, in the definition
type User {
id: uuid!
name: String!
location: geography
}
the uuid
and geography
types are assumed to refer to Postgres
scalars (assuming no other definition for them is provided).
Enum types¶
Enums are a special kind of scalar that is restricted to a particular set of allowed values. This allows you to:
- Validate that any arguments of this type are one of the allowed values
- Communicate through the type system that a field will always be one of a finite set of values
Here’s what an enum definition might look like in the GraphQL schema language:
enum Color {
RED
GREEN
BLUE
}
This means that wherever we use the type Color
in our schema, we expect it
to be exactly one of RED, GREEN, or BLUE.
Additional Resources
Introduction to Hasura Actions - View Recording.