Input Objects
Input objects are defined by using a record annotated with @gql.inputObject:
/** Config for searching for a user. */
@gql.inputObject
type userSearchConfig = {
groupId?: ResGraph.id,
name?: string,
}
@gql.field
let searchForUser = (_: query, ~input: userConfig, ~ctx: ResGraphContext.context): option<user> => {
ctx.dataLoaders.searchForUser.load(~name=input.name, ~groupId=input.groupId)
}
input UserSearchConfig {
groupId: ID
name: String
}
type Query {
searchForUser(input: UserSearchConfig!): User
}
One big difference compared to object type fields is that in input objects, all fields are automatically exposed, because the contrary wouldn't make sense since this is an input from the client and not something you're supposed to construct yourself.
Customizing field names with @as
Input object fields can also use ReScript's @as attribute when the GraphQL field name should differ from the ReScript record field name. This is useful when the GraphQL input needs a field name that is reserved in ReScript, like constraint or type.
@gql.inputObject
type ruleInput = {
@as("constraint")
constraint_: string,
@as("type")
type_: string,
}
This emits:
input RuleInput {
constraint: String!
type: String!
}
Resolvers still work with the ReScript-safe field names:
@gql.field
let validateRule = (_: query, ~input: ruleInput) => {
input.constraint_ ++ ":" ++ input.type_
}
ResGraph validates the final GraphQL field names after applying @as, so duplicate aliases are reported during schema generation.
Use @as for input object fields, including inline record payload fields generated by input unions. For reserved resolver argument names, use escaped labels on the field function instead, as shown in object type arguments.
Comments
You can add comments to the type definition itself, and to all record fields. These will then be exposed in your schema.
Handling null
Just like in arguments of object type fields, you can choose to explicitly handle null values by annotating fields in the input object to be Js.Nullable.t.
Recursive input objects
Input objects are allowed to be (mutually) recursive, if they're not recursive in a non-nullable way, as that would create an endless loop.
In ReScript, you'd handle that scenario like you'd normally handle mutually recursive types:
/** Some user config. */
@gql.inputObject
type rec userConfig = {
name?: string,
additionalConfig?: userConfig,
lastGroupConfig?: groupConfig,
}
@gql.inputObject /** Some group config. */
and groupConfig = {
groupName: string,
additionalUserConfig?: userConfig,
}
Input unions
Often you'll find yourself in a scenario where you want to your input to be one of several different values. For this, ResGraph has first class support for input unions.