mochi/schema
Core schema types and execution context for GraphQL.
This module provides:
- Schema type definitions (ObjectType, FieldType, ScalarType, etc.)
- ExecutionContext for managing DataLoaders and middleware
- Builder functions for constructing schemas
ExecutionContext with DataLoaders
// Create context with multiple loaders
let ctx = schema.execution_context(types.to_dynamic(dict.new()))
|> schema.with_loaders([
#("pokemon", pokemon_loader),
#("trainer", trainer_loader),
])
// Load by ID (handles context threading automatically)
let #(ctx, pokemon) = schema.load_by_id(ctx, "pokemon", 25)
let #(ctx, trainers) = schema.load_many_by_id(ctx, "trainer", [1, 2, 3])
Schema Building
let my_schema = schema.schema()
|> schema.query(query_type)
|> schema.mutation(mutation_type)
|> schema.add_type(schema.ObjectTypeDef(user_type))
|> schema.add_directive(auth_directive)
Types
pub type ArgumentDefinition {
ArgumentDefinition(
name: String,
description: option.Option(String),
arg_type: FieldType,
default_value: option.Option(dynamic.Dynamic),
)
}
Constructors
-
ArgumentDefinition( name: String, description: option.Option(String), arg_type: FieldType, default_value: option.Option(dynamic.Dynamic), )
Custom directive definition
pub type DirectiveDefinition {
DirectiveDefinition(
name: String,
description: option.Option(String),
arguments: dict.Dict(String, ArgumentDefinition),
locations: List(DirectiveLocation),
is_repeatable: Bool,
handler: option.Option(
fn(dict.Dict(String, dynamic.Dynamic), dynamic.Dynamic) -> Result(
dynamic.Dynamic,
String,
),
),
)
}
Constructors
-
DirectiveDefinition( name: String, description: option.Option(String), arguments: dict.Dict(String, ArgumentDefinition), locations: List(DirectiveLocation), is_repeatable: Bool, handler: option.Option( fn(dict.Dict(String, dynamic.Dynamic), dynamic.Dynamic) -> Result( dynamic.Dynamic, String, ), ), )
Handler function for custom directives Takes the directive arguments and field value, returns modified value or error
pub type DirectiveHandler =
fn(dict.Dict(String, dynamic.Dynamic), dynamic.Dynamic) -> Result(
dynamic.Dynamic,
String,
)
Locations where a directive can be used
pub type DirectiveLocation {
QueryLocation
MutationLocation
SubscriptionLocation
FieldLocation
FragmentDefinitionLocation
FragmentSpreadLocation
InlineFragmentLocation
VariableDefinitionLocation
SchemaLocation
ScalarLocation
ObjectLocation
FieldDefinitionLocation
ArgumentDefinitionLocation
InterfaceLocation
UnionLocation
EnumLocation
EnumValueLocation
InputObjectLocation
InputFieldDefinitionLocation
}
Constructors
-
QueryLocation -
MutationLocation -
SubscriptionLocation -
FieldLocation -
FragmentDefinitionLocation -
FragmentSpreadLocation -
InlineFragmentLocation -
VariableDefinitionLocation -
SchemaLocation -
ScalarLocation -
ObjectLocation -
FieldDefinitionLocation -
ArgumentDefinitionLocation -
InterfaceLocation -
UnionLocation -
EnumLocation -
EnumValueLocation -
InputObjectLocation -
InputFieldDefinitionLocation
pub type EnumType {
EnumType(
name: String,
description: option.Option(String),
values: dict.Dict(String, EnumValueDefinition),
)
}
Constructors
-
EnumType( name: String, description: option.Option(String), values: dict.Dict(String, EnumValueDefinition), )
pub type EnumValueDefinition {
EnumValueDefinition(
name: String,
description: option.Option(String),
value: dynamic.Dynamic,
is_deprecated: Bool,
deprecation_reason: option.Option(String),
)
}
Constructors
-
EnumValueDefinition( name: String, description: option.Option(String), value: dynamic.Dynamic, is_deprecated: Bool, deprecation_reason: option.Option(String), )
Context for GraphQL execution, including DataLoader instances
pub type ExecutionContext {
ExecutionContext(
user_context: UserContext,
data_loaders: dict.Dict(
String,
dataloader.DataLoader(dynamic.Dynamic, dynamic.Dynamic),
),
middleware_fn: option.Option(
fn(
String,
FieldDefinition,
ResolverInfo,
fn(ResolverInfo) -> Result(dynamic.Dynamic, String),
) -> Result(dynamic.Dynamic, String),
),
telemetry: option.Option(TelemetryContext),
telemetry_fn: option.Option(fn(SchemaEvent) -> Nil),
)
}
Constructors
-
ExecutionContext( user_context: UserContext, data_loaders: dict.Dict( String, dataloader.DataLoader(dynamic.Dynamic, dynamic.Dynamic), ), middleware_fn: option.Option( fn( String, FieldDefinition, ResolverInfo, fn(ResolverInfo) -> Result(dynamic.Dynamic, String), ) -> Result(dynamic.Dynamic, String), ), telemetry: option.Option(TelemetryContext), telemetry_fn: option.Option(fn(SchemaEvent) -> Nil), )Arguments
- user_context
-
Custom user context data. Construct via
schema.user_context(value), read viaschema.context_accessororschema.read_user_context. - data_loaders
-
DataLoader instances for batching and caching
- middleware_fn
-
Optional middleware function for field resolution
- telemetry
-
Optional telemetry context for instrumentation (opaque, legacy)
- telemetry_fn
-
Optional telemetry event callback — receives SchemaEvents during execution. Use
telemetry.to_schema_fn/1to bridge to a full TelemetryConfig.
pub type FieldDefinition {
FieldDefinition(
name: String,
description: option.Option(String),
field_type: FieldType,
arguments: dict.Dict(String, ArgumentDefinition),
resolver: option.Option(
fn(ResolverInfo) -> Result(dynamic.Dynamic, String),
),
is_deprecated: Bool,
deprecation_reason: option.Option(String),
topic_fn: option.Option(
fn(args.Args, ExecutionContext) -> Result(String, String),
),
rich_resolver: option.Option(
fn(ResolverInfo) -> Result(
dynamic.Dynamic,
#(
String,
option.Option(dict.Dict(String, dynamic.Dynamic)),
),
),
),
)
}
Constructors
-
FieldDefinition( name: String, description: option.Option(String), field_type: FieldType, arguments: dict.Dict(String, ArgumentDefinition), resolver: option.Option( fn(ResolverInfo) -> Result(dynamic.Dynamic, String), ), is_deprecated: Bool, deprecation_reason: option.Option(String), topic_fn: option.Option( fn(args.Args, ExecutionContext) -> Result(String, String), ), rich_resolver: option.Option( fn(ResolverInfo) -> Result( dynamic.Dynamic, #(String, option.Option(dict.Dict(String, dynamic.Dynamic))), ), ), )Arguments
- topic_fn
-
Optional topic resolver for subscription fields. Maps resolved arguments + context to a pub/sub topic string.
A guard function that runs before the resolver. Returns Ok(Nil) to allow the resolver to proceed, or Error(message) to reject.
pub type FieldGuard =
fn(ResolverInfo) -> Result(Nil, String)
pub type InputFieldDefinition {
InputFieldDefinition(
name: String,
description: option.Option(String),
field_type: FieldType,
default_value: option.Option(dynamic.Dynamic),
)
}
Constructors
-
InputFieldDefinition( name: String, description: option.Option(String), field_type: FieldType, default_value: option.Option(dynamic.Dynamic), )
pub type InputObjectType {
InputObjectType(
name: String,
description: option.Option(String),
fields: dict.Dict(String, InputFieldDefinition),
)
}
Constructors
-
InputObjectType( name: String, description: option.Option(String), fields: dict.Dict(String, InputFieldDefinition), )
pub type InterfaceType {
InterfaceType(
name: String,
description: option.Option(String),
fields: dict.Dict(String, FieldDefinition),
resolve_type: option.Option(
fn(dynamic.Dynamic) -> Result(String, String),
),
)
}
Constructors
-
InterfaceType( name: String, description: option.Option(String), fields: dict.Dict(String, FieldDefinition), resolve_type: option.Option( fn(dynamic.Dynamic) -> Result(String, String), ), )
Function type for middleware execution - avoids circular dependency with middleware.gleam
pub type MiddlewareFn =
fn(
String,
FieldDefinition,
ResolverInfo,
fn(ResolverInfo) -> Result(dynamic.Dynamic, String),
) -> Result(dynamic.Dynamic, String)
pub type ObjectType {
ObjectType(
name: String,
description: option.Option(String),
fields: dict.Dict(String, FieldDefinition),
interfaces: List(InterfaceType),
)
}
Constructors
-
ObjectType( name: String, description: option.Option(String), fields: dict.Dict(String, FieldDefinition), interfaces: List(InterfaceType), )
pub type Resolver =
fn(ResolverInfo) -> Result(dynamic.Dynamic, String)
Information passed to field resolvers.
args is the typed view; arguments is the legacy raw dict. New
resolvers should read via args.get_string(info.args, "id") etc.
arguments is kept so existing resolvers keep compiling, and so
callers that need to forward the raw dict can.
pub type ResolverInfo {
ResolverInfo(
parent: option.Option(dynamic.Dynamic),
arguments: dict.Dict(String, dynamic.Dynamic),
args: args.Args,
context: ExecutionContext,
info: dynamic.Dynamic,
)
}
Constructors
-
ResolverInfo( parent: option.Option(dynamic.Dynamic), arguments: dict.Dict(String, dynamic.Dynamic), args: args.Args, context: ExecutionContext, info: dynamic.Dynamic, )
pub type RichResolver =
fn(ResolverInfo) -> Result(
dynamic.Dynamic,
#(String, option.Option(dict.Dict(String, dynamic.Dynamic))),
)
pub type RichResolverPayload =
#(String, option.Option(dict.Dict(String, dynamic.Dynamic)))
pub type ScalarType {
ScalarType(
name: String,
description: option.Option(String),
serialize: fn(dynamic.Dynamic) -> Result(
dynamic.Dynamic,
String,
),
parse_value: fn(dynamic.Dynamic) -> Result(
dynamic.Dynamic,
String,
),
parse_literal: fn(dynamic.Dynamic) -> Result(
dynamic.Dynamic,
String,
),
)
}
Constructors
-
ScalarType( name: String, description: option.Option(String), serialize: fn(dynamic.Dynamic) -> Result( dynamic.Dynamic, String, ), parse_value: fn(dynamic.Dynamic) -> Result( dynamic.Dynamic, String, ), parse_literal: fn(dynamic.Dynamic) -> Result( dynamic.Dynamic, String, ), )
pub type Schema {
Schema(
query: option.Option(ObjectType),
mutation: option.Option(ObjectType),
subscription: option.Option(ObjectType),
types: dict.Dict(String, TypeDefinition),
directives: dict.Dict(String, DirectiveDefinition),
document_cache: option.Option(document_cache.DocumentCache),
)
}
Constructors
-
Schema( query: option.Option(ObjectType), mutation: option.Option(ObjectType), subscription: option.Option(ObjectType), types: dict.Dict(String, TypeDefinition), directives: dict.Dict(String, DirectiveDefinition), document_cache: option.Option(document_cache.DocumentCache), )
Events emitted during GraphQL execution for telemetry/instrumentation.
These are emitted by the executor and passed to the telemetry_fn if one is configured.
pub type SchemaEvent {
SchemaParseStart
SchemaParseEnd(success: Bool, duration_ns: Int)
SchemaValidationStart
SchemaValidationEnd(
success: Bool,
error_count: Int,
duration_ns: Int,
)
SchemaFieldStart(
field_name: String,
parent_type: String,
path: List(String),
)
SchemaFieldEnd(
field_name: String,
parent_type: String,
path: List(String),
success: Bool,
duration_ns: Int,
)
SchemaOperationStart(operation_name: option.Option(String))
SchemaOperationEnd(
operation_name: option.Option(String),
success: Bool,
error_count: Int,
)
SchemaDataLoaderBatch(
loader_name: String,
batch_size: Int,
duration_ns: Int,
)
}
Constructors
-
SchemaParseStartQuery parsing is about to start.
-
SchemaParseEnd(success: Bool, duration_ns: Int)Query parsing has completed.
-
SchemaValidationStartQuery validation is about to start.
-
SchemaValidationEnd( success: Bool, error_count: Int, duration_ns: Int, )Query validation has completed.
-
SchemaFieldStart( field_name: String, parent_type: String, path: List(String), )A field resolver is about to be called.
-
SchemaFieldEnd( field_name: String, parent_type: String, path: List(String), success: Bool, duration_ns: Int, )A field resolver has completed.
-
SchemaOperationStart(operation_name: option.Option(String))A GraphQL operation is about to be executed.
-
SchemaOperationEnd( operation_name: option.Option(String), success: Bool, error_count: Int, )A GraphQL operation has completed.
-
SchemaDataLoaderBatch( loader_name: String, batch_size: Int, duration_ns: Int, )DataLoader batch was executed.
Opaque type for telemetry context (defined in mochi/telemetry.gleam)
pub type TelemetryContext
Callback for receiving schema execution events.
Wire this up to a telemetry handler (e.g. via telemetry.to_schema_fn/1).
pub type TelemetryFn =
fn(SchemaEvent) -> Nil
pub type TypeDefinition {
ObjectTypeDef(object_type: ObjectType)
ScalarTypeDef(scalar_type: ScalarType)
EnumTypeDef(enum_type: EnumType)
InterfaceTypeDef(interface_type: InterfaceType)
UnionTypeDef(union_type: UnionType)
InputObjectTypeDef(input_object_type: InputObjectType)
}
Constructors
-
ObjectTypeDef(object_type: ObjectType) -
ScalarTypeDef(scalar_type: ScalarType) -
EnumTypeDef(enum_type: EnumType) -
InterfaceTypeDef(interface_type: InterfaceType) -
UnionTypeDef(union_type: UnionType) -
InputObjectTypeDef(input_object_type: InputObjectType)
Type resolver function that determines the concrete type at runtime
pub type TypeResolver =
fn(dynamic.Dynamic) -> Result(String, String)
pub type UnionType {
UnionType(
name: String,
description: option.Option(String),
types: List(ObjectType),
resolve_type: option.Option(
fn(dynamic.Dynamic) -> Result(String, String),
),
)
}
Constructors
-
UnionType( name: String, description: option.Option(String), types: List(ObjectType), resolve_type: option.Option( fn(dynamic.Dynamic) -> Result(String, String), ), )
Opaque holder for user-provided execution context data.
Resolvers expect a specific user context type — the one their app
configured. Exposing the raw Dynamic in ExecutionContext lied about
that: it advertised “any data here” when in fact the system requires
the app’s chosen type. UserContext keeps the runtime erasure
(necessary because the executor doesn’t know the app’s type) but stops
the lie at the type level.
Use user_context to wrap a value, and either
context_accessor for typed reads, or
read_user_context for one-off reads.
pub opaque type UserContext
Values
pub fn add_directive(
schema: Schema,
directive: DirectiveDefinition,
) -> Schema
Add a directive definition to the schema
pub fn add_type(
schema: Schema,
type_def: TypeDefinition,
) -> Schema
pub fn all_guards(
guard_fns: List(fn(ResolverInfo) -> Result(Nil, String)),
) -> fn(ResolverInfo) -> Result(Nil, String)
Combine guards with AND logic — all must pass (checked in list order). Returns a single guard that fails with the first error encountered.
pub fn any_guard(
guard_fns: List(fn(ResolverInfo) -> Result(Nil, String)),
) -> fn(ResolverInfo) -> Result(Nil, String)
Combine guards with OR logic — at least one must pass. Returns a single guard that succeeds if any guard passes, or fails with the last error if all fail.
pub fn arg(
name: String,
arg_type: FieldType,
) -> ArgumentDefinition
pub fn arg_description(
arg: ArgumentDefinition,
desc: String,
) -> ArgumentDefinition
pub fn argument(
field: FieldDefinition,
arg_def: ArgumentDefinition,
) -> FieldDefinition
pub fn auto_field(
obj: ObjectType,
name: String,
field_type: FieldType,
) -> ObjectType
Add a field with auto-resolver (extracts field by name from parent)
pub fn auto_resolver(
field_name: String,
) -> fn(ResolverInfo) -> Result(dynamic.Dynamic, String)
Create a resolver that auto-extracts a field from parent by name
pub fn bool_field(obj: ObjectType, name: String) -> ObjectType
Add a nullable Boolean field with auto-resolver
pub fn boolean_scalar() -> ScalarType
pub fn boolean_type() -> FieldType
pub fn builtin_directives() -> List(DirectiveDefinition)
Get all built-in directives
pub fn context_accessor(
decoder: decode.Decoder(a),
) -> fn(ExecutionContext) -> Result(a, String)
Create a typed accessor for user_context. Define once per app, use in every resolver.
// context.gleam
pub const get_user_id = schema.context_accessor(decode.optional(decode.string))
// resolver
let auth = ctx |> context.get_user_id |> require_auth
use uid <- result.try(auth)
pub fn datetime_type() -> FieldType
pub fn default_value(
arg: ArgumentDefinition,
value: dynamic.Dynamic,
) -> ArgumentDefinition
pub fn deprecated(
field: FieldDefinition,
reason: String,
) -> FieldDefinition
pub fn deprecated_directive() -> DirectiveDefinition
@deprecated(reason: String) directive
pub fn deprecated_no_reason(
field: FieldDefinition,
) -> FieldDefinition
pub fn description(obj: ObjectType, desc: String) -> ObjectType
pub fn directive(
name: String,
locations: List(DirectiveLocation),
) -> DirectiveDefinition
Create a new directive definition
pub fn directive_argument(
dir: DirectiveDefinition,
arg_def: ArgumentDefinition,
) -> DirectiveDefinition
Add an argument to a directive
pub fn directive_description(
dir: DirectiveDefinition,
desc: String,
) -> DirectiveDefinition
Add description to a directive
pub fn directive_handler(
dir: DirectiveDefinition,
handler: fn(dict.Dict(String, dynamic.Dynamic), dynamic.Dynamic) -> Result(
dynamic.Dynamic,
String,
),
) -> DirectiveDefinition
Set the handler function for a directive (for field-level directives)
pub fn directive_location_to_string(
loc: DirectiveLocation,
) -> String
Convert DirectiveLocation to string (for SDL generation)
pub fn directive_repeatable(
dir: DirectiveDefinition,
) -> DirectiveDefinition
Make a directive repeatable
pub fn email_type() -> FieldType
pub fn execution_context(
user_context user_context_value: a,
) -> ExecutionContext
Create a new execution context. The user_context value can be any
app-defined type; it is wrapped opaquely and surfaced to resolvers via
context_accessor / read_user_context.
pub fn field(
obj: ObjectType,
field_def: FieldDefinition,
) -> ObjectType
pub fn field_def(
name: String,
field_type: FieldType,
) -> FieldDefinition
pub fn field_description(
field: FieldDefinition,
desc: String,
) -> FieldDefinition
pub fn float_field(obj: ObjectType, name: String) -> ObjectType
Add a nullable Float field with auto-resolver
pub fn float_scalar() -> ScalarType
pub fn float_type() -> FieldType
pub fn get_data_loader(
context: ExecutionContext,
name: String,
) -> Result(
dataloader.DataLoader(dynamic.Dynamic, dynamic.Dynamic),
String,
)
Get a DataLoader from the execution context
pub fn get_middleware(
context: ExecutionContext,
) -> option.Option(
fn(
String,
FieldDefinition,
ResolverInfo,
fn(ResolverInfo) -> Result(dynamic.Dynamic, String),
) -> Result(dynamic.Dynamic, String),
)
Get the middleware function from context
pub fn get_telemetry(
context: ExecutionContext,
) -> option.Option(TelemetryContext)
Get the telemetry context
pub fn get_telemetry_fn(
context: ExecutionContext,
) -> option.Option(fn(SchemaEvent) -> Nil)
Get the telemetry callback function from the execution context
pub fn guard(
field: FieldDefinition,
guard_fn: fn(ResolverInfo) -> Result(Nil, String),
) -> FieldDefinition
Add a guard to a field definition. The guard runs before the resolver — if it returns Error, the resolver is skipped. Multiple guards can be stacked by calling this function multiple times; each new guard wraps the previous resolver+guards, so all must pass.
pub fn guards(
field: FieldDefinition,
guard_fns: List(fn(ResolverInfo) -> Result(Nil, String)),
) -> FieldDefinition
Add multiple guards to a field definition. Guards are checked in list order — the first guard in the list is checked first.
schema.field_def("secret", schema.string_type())
|> schema.resolver(my_resolver)
|> schema.guards([require_auth, require_admin])
// require_auth is checked first, then require_admin
pub fn id_field(obj: ObjectType, name: String) -> ObjectType
Add a non-null ID field with auto-resolver
pub fn id_scalar() -> ScalarType
pub fn implements(
obj: ObjectType,
interface: InterfaceType,
) -> ObjectType
pub fn include_directive() -> DirectiveDefinition
@include(if: Boolean!) directive
pub fn int_field(obj: ObjectType, name: String) -> ObjectType
Add a nullable Int field with auto-resolver
pub fn int_scalar() -> ScalarType
pub fn interface(name: String) -> InterfaceType
pub fn interface_description(
iface: InterfaceType,
desc: String,
) -> InterfaceType
pub fn interface_field(
iface: InterfaceType,
field_def: FieldDefinition,
) -> InterfaceType
pub fn interface_resolve_type(
iface: InterfaceType,
resolver: fn(dynamic.Dynamic) -> Result(String, String),
) -> InterfaceType
pub fn list_field(
obj: ObjectType,
name: String,
item_type: String,
) -> ObjectType
Add a list field with auto-resolver
pub fn list_query(
obj: ObjectType,
name: String,
item_type: String,
desc: String,
resolve_fn: fn(ResolverInfo) -> Result(dynamic.Dynamic, String),
) -> ObjectType
Add a list query field: name: [ItemType]
pub fn load(
context: ExecutionContext,
loader_name: String,
key: dynamic.Dynamic,
) -> #(ExecutionContext, Result(dynamic.Dynamic, String))
Load a value using a named DataLoader, returning updated context and result
This handles the context threading automatically.
Example
let #(ctx, result) = schema.load(ctx, "pokemon", dataloader.int_key(25))
pub fn load_by_id(
context: ExecutionContext,
loader_name: String,
id: Int,
) -> #(ExecutionContext, Result(dynamic.Dynamic, String))
Load an entity by Int ID using a named DataLoader
Convenience wrapper for the common case of loading by integer ID.
Example
let #(ctx, pokemon) = schema.load_by_id(ctx, "pokemon", 25)
pub fn load_many(
context: ExecutionContext,
loader_name: String,
keys: List(dynamic.Dynamic),
) -> #(ExecutionContext, List(Result(dynamic.Dynamic, String)))
Load multiple values using a named DataLoader
Example
let keys = list.map([1, 2, 3], dataloader.int_key)
let #(ctx, results) = schema.load_many(ctx, "pokemon", keys)
pub fn load_many_by_id(
context: ExecutionContext,
loader_name: String,
ids: List(Int),
) -> #(ExecutionContext, List(Result(dynamic.Dynamic, String)))
Load multiple entities by Int IDs using a named DataLoader
Example
let #(ctx, pokemon_list) = schema.load_many_by_id(ctx, "pokemon", [1, 4, 7, 25])
pub fn mutation(
schema: Schema,
mutation_type: ObjectType,
) -> Schema
pub fn named_type(name: String) -> FieldType
pub fn object(name: String) -> ObjectType
pub fn parse_literal(
scalar: ScalarType,
parse_fn: fn(dynamic.Dynamic) -> Result(dynamic.Dynamic, String),
) -> ScalarType
pub fn parse_value(
scalar: ScalarType,
parse_fn: fn(dynamic.Dynamic) -> Result(dynamic.Dynamic, String),
) -> ScalarType
pub fn query(schema: Schema, query_type: ObjectType) -> Schema
pub fn query_with_args(
obj: ObjectType,
name: String,
field_type: FieldType,
args: List(ArgumentDefinition),
desc: String,
resolve_fn: fn(ResolverInfo) -> Result(dynamic.Dynamic, String),
) -> ObjectType
Add a query field with arguments
pub fn read_user_context(
uc: UserContext,
decoder: decode.Decoder(a),
) -> Result(a, String)
Read the wrapped value back, decoding into an app-defined type.
pub fn ref_field(
obj: ObjectType,
name: String,
type_name: String,
) -> ObjectType
Add a reference field to another type with auto-resolver
pub fn ref_query(
obj: ObjectType,
name: String,
type_name: String,
desc: String,
resolve_fn: fn(ResolverInfo) -> Result(dynamic.Dynamic, String),
) -> ObjectType
Add a reference query field: name: TypeName
pub fn required_bool_field(
obj: ObjectType,
name: String,
) -> ObjectType
Add a non-null Boolean field with auto-resolver
pub fn required_float_field(
obj: ObjectType,
name: String,
) -> ObjectType
Add a non-null Float field with auto-resolver
pub fn required_int_field(
obj: ObjectType,
name: String,
) -> ObjectType
Add a non-null Int field with auto-resolver
pub fn required_list_field(
obj: ObjectType,
name: String,
item_type: String,
) -> ObjectType
Add a non-null list field with auto-resolver
pub fn required_ref_field(
obj: ObjectType,
name: String,
type_name: String,
) -> ObjectType
Add a non-null reference field with auto-resolver
pub fn required_string_field(
obj: ObjectType,
name: String,
) -> ObjectType
Add a non-null String field with auto-resolver
pub fn resolver(
field: FieldDefinition,
resolve_fn: fn(ResolverInfo) -> Result(dynamic.Dynamic, String),
) -> FieldDefinition
pub fn resolver_field(
obj: ObjectType,
name: String,
field_type: FieldType,
desc: String,
resolve_fn: fn(ResolverInfo) -> Result(dynamic.Dynamic, String),
) -> ObjectType
Add a field with custom resolver and optional description
pub fn rich_resolver_fn(
field: FieldDefinition,
resolve_fn: fn(ResolverInfo) -> Result(
dynamic.Dynamic,
#(String, option.Option(dict.Dict(String, dynamic.Dynamic))),
),
) -> FieldDefinition
pub fn scalar(name: String) -> ScalarType
pub fn scalar_description(
scalar: ScalarType,
desc: String,
) -> ScalarType
pub fn serialize(
scalar: ScalarType,
serialize_fn: fn(dynamic.Dynamic) -> Result(
dynamic.Dynamic,
String,
),
) -> ScalarType
pub fn string_field(obj: ObjectType, name: String) -> ObjectType
Add a nullable String field with auto-resolver
pub fn string_scalar() -> ScalarType
pub fn string_type() -> FieldType
pub fn subscription(
schema: Schema,
subscription_type: ObjectType,
) -> Schema
pub fn union_member(
union_type: UnionType,
member: ObjectType,
) -> UnionType
pub fn union_resolve_type(
union_type: UnionType,
resolver: fn(dynamic.Dynamic) -> Result(String, String),
) -> UnionType
pub fn update_data_loader(
context: ExecutionContext,
name: String,
loader: dataloader.DataLoader(dynamic.Dynamic, dynamic.Dynamic),
) -> ExecutionContext
Update a DataLoader in the execution context
pub fn update_telemetry(
context: ExecutionContext,
telemetry: TelemetryContext,
) -> ExecutionContext
Update the telemetry context
pub fn user_context(value: a) -> UserContext
Wrap an app-defined value so it can be carried through the executor.
pub fn with_loader(
context: ExecutionContext,
name: String,
loader: dataloader.DataLoader(dynamic.Dynamic, dynamic.Dynamic),
) -> ExecutionContext
pub fn with_loaders(
context: ExecutionContext,
loaders: List(
#(
String,
dataloader.DataLoader(dynamic.Dynamic, dynamic.Dynamic),
),
),
) -> ExecutionContext
Add multiple DataLoaders to the execution context at once
Example
let ctx = schema.execution_context(user_ctx)
|> schema.with_loaders([
#("pokemon", pokemon_loader),
#("move", move_loader),
#("trainer", trainer_loader),
])
pub fn with_middleware(
context: ExecutionContext,
middleware: fn(
String,
FieldDefinition,
ResolverInfo,
fn(ResolverInfo) -> Result(dynamic.Dynamic, String),
) -> Result(dynamic.Dynamic, String),
) -> ExecutionContext
Set middleware function on an execution context
pub fn with_telemetry(
context: ExecutionContext,
telemetry: TelemetryContext,
) -> ExecutionContext
Set telemetry on an execution context
pub fn with_telemetry_fn(
context: ExecutionContext,
telemetry_fn: fn(SchemaEvent) -> Nil,
) -> ExecutionContext
Set a telemetry callback function on the execution context.
This function is called for each SchemaEvent emitted during execution.
Use telemetry.to_schema_fn/1 to bridge a TelemetryConfig to this callback.