dagql

package
v0.14.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 8, 2024 License: Apache-2.0 Imports: 23 Imported by: 0

README

dagql

DagQL is a strongly opinionated implementation of a GraphQL server.

axioms

Below are a set of assertions that build on one another.

  • All Objects are immutable.
  • All Objects are Nodes, i.e. all objects have an id.
  • All Objects have their own ID type, e.g. PointID.
  • All Objects have a top-level constructor named after the object, e.g. point.
  • All Objects may be loaded from an ID, which will create the Object if needed.
  • An Object's field may be @impure which indicates that the field's result shall not be cached.
  • An Object's field may be @meta which indicates that the field may be omitted without affecting the result.
  • All IDs are derived from the query that constructed the Object.
  • An ID is canonicalized by removing any embedded @meta selectors.
  • An ID is impure if it contains any @impure selectors or any tainted IDs.
  • An ID may be loaded on a server that has never seen its Object before.
  • When a pure ID is loaded it must always return the same Object.
  • When an impure ID is loaded it may return a different Object each time.
  • An impure query or ID may return an Object with a pure ID.
  • All data may be kept in-memory with LRU-like caching semantics.
  • All Arrays returned by Objects have deterministic order.
  • An ID may refer to an Object returned in an Array by specifying the nth index (starting at 1).
  • All Objects in Arrays have IDs: either an ID of their own, or the field's ID with nth set.
  • At the GraphQL API layer, Objects are passed to each other by ID.
  • At the code layer, Objects received as arguments are automatically loaded from a given ID.

context

This repository might be re-integrated into Dagger, but for now is just a personal experiment.

It should replace our use of the following forks:

  • github.com/dagger/graphql
  • github.com/dagger/graphql-go-tools

I think it may make sense to leave as its own repo just to make sure there's a clear boundary between the theory and the practice. But it should probably move into the Dagger account.

TODO

  • parallel query execution
  • figure out whether constructor patterns are enshrined or ad-hoc
    • ad-hoc; you can now Extend any ObjectType in the Server.
  • figure out how to return objects that already have an ID (e.g. loadFooFromID should not have itself in the returned ID)
    • if resolvers return an Object no further wrapping/ID-ing is required
  • implement caching semantics, including @impure and @meta
  • figure out telemetry
    • resolvers can be wrapped, have access to the current *idproto.ID
  • support schema docs for everything (types, fields, args, enum values, etc)
  • figure out how interfaces work
    • don't need this yet, but might be a next step for Dagger interfaces
  • IDs should also contain module info
    • IDs can now contain a reference to a single module ID which provides the implementation of the field that the ID resolves
    • all modules contained recursively by an ID (i.e. in parents or arguments) are loaded prior to evaluating the ID
      • technically we might not need to load all modules, since arguably arguments could be evaluated in a vacuum; TBD
  • IDs should also contain digest of result (stretch goal, this is higher level, e.g. we want literal file checksums for objects that represent a file)
  • get rid of Identified in favor of Object? (see interfaces + wrapping concern below)

Documentation

Index

Constants

View Source
const InstrumentationLibrary = "dagger.io/dagql"

Variables

View Source
var (
	DirectiveLocationQuery                = DirectiveLocations.Register("QUERY")
	DirectiveLocationMutation             = DirectiveLocations.Register("MUTATION")
	DirectiveLocationSubscription         = DirectiveLocations.Register("SUBSCRIPTION")
	DirectiveLocationField                = DirectiveLocations.Register("FIELD")
	DirectiveLocationFragmentDefinition   = DirectiveLocations.Register("FRAGMENT_DEFINITION")
	DirectiveLocationFragmentSpread       = DirectiveLocations.Register("FRAGMENT_SPREAD")
	DirectiveLocationInlineFragment       = DirectiveLocations.Register("INLINE_FRAGMENT")
	DirectiveLocationVariableDefinition   = DirectiveLocations.Register("VARIABLE_DEFINITION")
	DirectiveLocationSchema               = DirectiveLocations.Register("SCHEMA")
	DirectiveLocationScalar               = DirectiveLocations.Register("SCALAR")
	DirectiveLocationObject               = DirectiveLocations.Register("OBJECT")
	DirectiveLocationFieldDefinition      = DirectiveLocations.Register("FIELD_DEFINITION")
	DirectiveLocationArgumentDefinition   = DirectiveLocations.Register("ARGUMENT_DEFINITION")
	DirectiveLocationInterface            = DirectiveLocations.Register("INTERFACE")
	DirectiveLocationUnion                = DirectiveLocations.Register("UNION")
	DirectiveLocationEnum                 = DirectiveLocations.Register("ENUM")
	DirectiveLocationEnumValue            = DirectiveLocations.Register("ENUM_VALUE")
	DirectiveLocationInputObject          = DirectiveLocations.Register("INPUT_OBJECT")
	DirectiveLocationInputFieldDefinition = DirectiveLocations.Register("INPUT_FIELD_DEFINITION")
)
View Source
var DirectiveLocations = NewEnum[DirectiveLocation]()
View Source
var ErrCacheMapRecursiveCall = fmt.Errorf("recursive call detected")

Functions

func CurrentID

func CurrentID(ctx context.Context) *call.ID

func FormatDescription

func FormatDescription(paras ...string) string

func IDTypeNameFor added in v0.9.8

func IDTypeNameFor(t Typed) string

func IsInternal added in v0.10.0

func IsInternal(ctx context.Context) bool

IsInternal returns whether the internal flag is set in the context.

func LoadIDs

func LoadIDs[T Typed](ctx context.Context, srv *Server, ids []ID[T]) ([]T, error)

func NoopDone added in v0.11.0

func NoopDone(res Typed, cached bool, rerr error)

func Tracer added in v0.11.0

func Tracer() trace.Tracer

Types

type AllView added in v0.12.0

type AllView struct{}

AllView is similar to the global view, however, instead of being an empty view, it's still counted as a view.

This means that each call for a field is associated with the server view, which results in slightly different caching behavior. Additionally, it can be overridden in different views.

func (AllView) Contains added in v0.12.0

func (v AllView) Contains(s string) bool

type AroundFunc

type AroundFunc func(
	context.Context,
	Object,
	*call.ID,
) (context.Context, func(res Typed, cached bool, err error))

AroundFunc is a function that is called around every non-cached selection.

It's a little funny looking. I may have goofed it. This will be cleaned up soon.

type Array

type Array[T Typed] []T

Array is an array of GraphQL values.

func MapArrayInput

func MapArrayInput[T Input, R Typed](opt ArrayInput[T], fn func(T) (R, error)) (Array[R], error)

func NewBoolArray

func NewBoolArray(elems ...bool) Array[Boolean]

func NewFloatArray

func NewFloatArray(elems ...float64) Array[Float]

func NewIntArray

func NewIntArray(elems ...int) Array[Int]

func NewStringArray

func NewStringArray(elems ...string) Array[String]

func ToArray

func ToArray[A any, T Typed](fn func(A) T, elems ...A) Array[T]

ToArray creates a new Array by applying the given function to each element of the given slice.

func (Array[T]) Len

func (arr Array[T]) Len() int

func (Array[T]) Nth

func (arr Array[T]) Nth(i int) (Typed, error)

func (Array[T]) Type

func (i Array[T]) Type() *ast.Type

type ArrayInput

type ArrayInput[I Input] []I

Array is an array of GraphQL values.

func (ArrayInput[I]) DecodeInput

func (a ArrayInput[I]) DecodeInput(val any) (Input, error)

func (ArrayInput[S]) Decoder

func (a ArrayInput[S]) Decoder() InputDecoder

func (ArrayInput[I]) SetField

func (d ArrayInput[I]) SetField(val reflect.Value) error

func (ArrayInput[S]) ToArray

func (a ArrayInput[S]) ToArray() Array[S]

func (ArrayInput[S]) ToLiteral

func (i ArrayInput[S]) ToLiteral() call.Literal

func (ArrayInput[S]) Type

func (a ArrayInput[S]) Type() *ast.Type

type Boolean

type Boolean bool

Boolean is a GraphQL Boolean scalar.

func NewBoolean

func NewBoolean(val bool) Boolean

func (Boolean) Bool

func (b Boolean) Bool() bool

func (Boolean) DecodeInput

func (Boolean) DecodeInput(val any) (Input, error)

func (Boolean) Decoder

func (Boolean) Decoder() InputDecoder

func (Boolean) MarshalJSON

func (b Boolean) MarshalJSON() ([]byte, error)

func (Boolean) SetField

func (b Boolean) SetField(v reflect.Value) error

func (Boolean) ToLiteral

func (b Boolean) ToLiteral() call.Literal

func (Boolean) Type

func (Boolean) Type() *ast.Type

func (Boolean) TypeDefinition

func (b Boolean) TypeDefinition(views ...string) *ast.Definition

func (Boolean) TypeName

func (Boolean) TypeName() string

func (*Boolean) UnmarshalJSON

func (b *Boolean) UnmarshalJSON(p []byte) error

type Cache

type Cache interface {
	GetOrInitialize(
		context.Context,
		digest.Digest,
		func(context.Context) (Typed, error),
	) (Typed, bool, error)
}

Cache stores results of pure selections against Server.

func NewCache

func NewCache() Cache

NewCache creates a new cache map suitable for assigning on a Server or multiple Servers.

type CacheMap added in v0.9.9

type CacheMap[K comparable, T any] interface {
	GetOrInitialize(context.Context, K, func(context.Context) (T, error)) (T, bool, error)
	Get(context.Context, K) (T, error)
	Keys() []K
}

func NewCacheMap added in v0.9.9

func NewCacheMap[K comparable, T any]() CacheMap[K, T]

type Class

type Class[T Typed] struct {
	// contains filtered or unexported fields
}

Class is a class of Object types.

The class is defined by a set of fields, which are installed into the class dynamically at runtime.

func NewClass

func NewClass[T Typed](opts_ ...ClassOpts[T]) Class[T]

NewClass returns a new empty class for a given type.

func (Class[T]) Call

func (cls Class[T]) Call(ctx context.Context, node Instance[T], fieldName string, view string, args map[string]Input) (Typed, error)

Call calls a field on the class against an instance.

func (Class[T]) Extend

func (cls Class[T]) Extend(spec FieldSpec, fun FieldFunc)

func (Class[T]) Field

func (class Class[T]) Field(name string, views ...string) (Field[T], bool)

func (Class[T]) IDType

func (class Class[T]) IDType() (IDType, bool)

func (Class[T]) Install

func (class Class[T]) Install(fields ...Field[T])

func (Class[T]) New

func (cls Class[T]) New(id *call.ID, val Typed) (Object, error)

New returns a new instance of the class.

func (Class[T]) ParseField

func (cls Class[T]) ParseField(ctx context.Context, view string, astField *ast.Field, vars map[string]any) (Selector, *ast.Type, error)

ParseField parses a field selection into a Selector and return type.

func (Class[T]) TypeDefinition

func (cls Class[T]) TypeDefinition(views ...string) *ast.Definition

TypeDefinition returns the schema definition of the class.

The definition is derived from the type name, description, and fields. The type may implement Definitive or Descriptive to provide more information.

Each currently defined field is installed on the returned definition.

func (Class[T]) TypeName

func (cls Class[T]) TypeName() string

func (Class[T]) Typed

func (class Class[T]) Typed() Typed

type ClassOpts

type ClassOpts[T Typed] struct {
	// NoIDs disables the default "id" field and disables the IDType method.
	NoIDs bool

	// Typed contains the Typed value whose Type() determines the class's type.
	//
	// In the simple case, we can just use a zero-value, but it is also allowed
	// to use a dynamic Typed value.
	Typed T
}

type DecoderFunc

type DecoderFunc func(any) (Input, error)

func (DecoderFunc) DecodeInput

func (f DecoderFunc) DecodeInput(val any) (Input, error)

type Definitive

type Definitive interface {
	TypeDefinition(views ...string) *ast.Definition
}

Definitive is a type that knows how to define itself in the schema.

type Derefable

type Derefable interface {
	Deref() (Typed, bool)
}

Derefable is a type that wraps another type.

In practice this is only used for Optional and Nullable. It should be used sparingly, since wrapping interfaces explodes very quickly.

type Descriptive

type Descriptive interface {
	TypeDescription() string
}

Descriptive is an interface for types that have a description.

The description is used in the schema. To provide a full definition, implement Definitive instead.

type DirectiveLocation

type DirectiveLocation string

func (DirectiveLocation) Decoder

func (DirectiveLocation) Decoder() InputDecoder

func (DirectiveLocation) ToLiteral

func (d DirectiveLocation) ToLiteral() call.Literal

func (DirectiveLocation) Type

func (DirectiveLocation) Type() *ast.Type

type DirectiveSpec

type DirectiveSpec struct {
	Name         string              `field:"true"`
	Description  string              `field:"true"`
	Args         InputSpecs          `field:"true"`
	Locations    []DirectiveLocation `field:"true"`
	IsRepeatable bool                `field:"true"`
}

func (DirectiveSpec) DirectiveDefinition

func (d DirectiveSpec) DirectiveDefinition() *ast.DirectiveDefinition

type DynamicArrayInput

type DynamicArrayInput struct {
	Elem   Input
	Values []Input
}

func (DynamicArrayInput) DecodeInput

func (d DynamicArrayInput) DecodeInput(val any) (Input, error)

func (DynamicArrayInput) Decoder

func (d DynamicArrayInput) Decoder() InputDecoder

func (DynamicArrayInput) Len

func (d DynamicArrayInput) Len() int

func (DynamicArrayInput) Nth

func (d DynamicArrayInput) Nth(i int) (Typed, error)

func (DynamicArrayInput) SetField

func (d DynamicArrayInput) SetField(val reflect.Value) error

func (DynamicArrayInput) ToLiteral

func (d DynamicArrayInput) ToLiteral() call.Literal

func (DynamicArrayInput) Type

func (d DynamicArrayInput) Type() *ast.Type

type DynamicArrayOutput

type DynamicArrayOutput struct {
	Elem   Typed
	Values []Typed
}

func (DynamicArrayOutput) Len

func (d DynamicArrayOutput) Len() int

func (DynamicArrayOutput) MarshalJSON

func (d DynamicArrayOutput) MarshalJSON() ([]byte, error)

func (DynamicArrayOutput) Nth

func (d DynamicArrayOutput) Nth(i int) (Typed, error)

func (DynamicArrayOutput) SetField added in v0.9.9

func (d DynamicArrayOutput) SetField(val reflect.Value) error

func (DynamicArrayOutput) Type

func (d DynamicArrayOutput) Type() *ast.Type

type DynamicNullable

type DynamicNullable struct {
	Elem  Typed
	Value Typed
	Valid bool
}

func (DynamicNullable) Deref

func (n DynamicNullable) Deref() (Typed, bool)

func (DynamicNullable) MarshalJSON

func (n DynamicNullable) MarshalJSON() ([]byte, error)

func (DynamicNullable) Type

func (n DynamicNullable) Type() *ast.Type

func (*DynamicNullable) UnmarshalJSON

func (n *DynamicNullable) UnmarshalJSON(p []byte) error

type DynamicOptional

type DynamicOptional struct {
	Elem  Input
	Value Input
	Valid bool
}

func (DynamicOptional) DecodeInput

func (o DynamicOptional) DecodeInput(val any) (Input, error)

func (DynamicOptional) Decoder

func (o DynamicOptional) Decoder() InputDecoder

func (DynamicOptional) Deref

func (o DynamicOptional) Deref() (Typed, bool)

func (DynamicOptional) MarshalJSON

func (o DynamicOptional) MarshalJSON() ([]byte, error)

func (DynamicOptional) SetField

func (o DynamicOptional) SetField(val reflect.Value) error

func (DynamicOptional) ToLiteral

func (o DynamicOptional) ToLiteral() call.Literal

func (DynamicOptional) Type

func (o DynamicOptional) Type() *ast.Type

type EnumValue

type EnumValue interface {
	Input
	~string
}

type EnumValueName added in v0.13.6

type EnumValueName struct {
	Enum  string
	Value string
}

func (*EnumValueName) DecodeInput added in v0.13.6

func (e *EnumValueName) DecodeInput(val any) (Input, error)

func (*EnumValueName) Decoder added in v0.13.6

func (e *EnumValueName) Decoder() InputDecoder

func (*EnumValueName) MarshalJSON added in v0.13.6

func (e *EnumValueName) MarshalJSON() ([]byte, error)

func (*EnumValueName) ToLiteral added in v0.13.6

func (e *EnumValueName) ToLiteral() call.Literal

func (*EnumValueName) Type added in v0.13.6

func (e *EnumValueName) Type() *ast.Type

func (*EnumValueName) TypeDefinition added in v0.13.6

func (e *EnumValueName) TypeDefinition(views ...string) *ast.Definition

func (*EnumValueName) TypeName added in v0.13.6

func (e *EnumValueName) TypeName() string

type EnumValues

type EnumValues[T EnumValue] struct {
	// contains filtered or unexported fields
}

EnumValues is a list of possible values for an Enum.

func NewEnum

func NewEnum[T EnumValue](vals ...T) *EnumValues[T]

NewEnum creates a new EnumType with the given possible values.

func (*EnumValues[T]) DecodeInput

func (e *EnumValues[T]) DecodeInput(val any) (Input, error)

func (*EnumValues[T]) Install

func (e *EnumValues[T]) Install(srv *Server)

func (*EnumValues[T]) Literal

func (e *EnumValues[T]) Literal(val T) call.Literal

func (*EnumValues[T]) Lookup

func (e *EnumValues[T]) Lookup(val string) (T, error)

func (*EnumValues[T]) PossibleValues

func (e *EnumValues[T]) PossibleValues() ast.EnumValueList

func (*EnumValues[T]) Register

func (e *EnumValues[T]) Register(val T, desc ...string) T

func (*EnumValues[T]) Type

func (e *EnumValues[T]) Type() *ast.Type

func (*EnumValues[T]) TypeDefinition

func (e *EnumValues[T]) TypeDefinition(views ...string) *ast.Definition

func (*EnumValues[T]) TypeName

func (e *EnumValues[T]) TypeName() string

type Enumerable

type Enumerable interface {
	// Len returns the number of elements in the Enumerable.
	Len() int
	// Nth returns the Nth element of the Enumerable, with 1 representing the
	// first entry.
	Nth(int) (Typed, error)
}

Enumerable is a value that has a length and allows indexing.

type ExactView added in v0.12.0

type ExactView string

ExactView contains exactly one view.

func (ExactView) Contains added in v0.12.0

func (v ExactView) Contains(s string) bool

type ExtendedError

type ExtendedError interface {
	error
	Extensions() map[string]any
}

ExtendedError is an error that can provide extra data in an error response.

type Field

type Field[T Typed] struct {
	Spec FieldSpec
	Func func(context.Context, Instance[T], map[string]Input) (Typed, error)

	// ViewFilter is filter that specifies under which views this field is
	// accessible. If not view is present, the default is the "global" view.
	ViewFilter View
}

Field defines a field of an Object type.

func Func

func Func[T Typed, A any, R any](name string, fn func(ctx context.Context, self T, args A) (R, error)) Field[T]

Func is a helper for defining a field resolver and schema.

The function must accept a context.Context, the receiver, and a struct of arguments. All fields of the arguments struct must be Typed so that the schema may be derived, and Scalar to ensure a default value may be provided.

Arguments use struct tags to further configure the schema:

  • `name:"bar"` sets the name of the argument. By default this is the toLowerCamel'd field name.
  • `default:"foo"` sets the default value of the argument. The Scalar type determines how this value is parsed.
  • `doc:"..."` sets the description of the argument.

The function must return a Typed value, and an error.

To configure a description for the field in the schema, call .Doc on the result.

func NodeFunc

func NodeFunc[T Typed, A any, R any](name string, fn func(ctx context.Context, self Instance[T], args A) (R, error)) Field[T]

NodeFunc is the same as Func, except it passes the Instance instead of the receiver so that you can access its ID.

func (Field[T]) ArgDeprecated

func (field Field[T]) ArgDeprecated(name string, paras ...string) Field[T]

func (Field[T]) ArgDoc

func (field Field[T]) ArgDoc(name string, paras ...string) Field[T]

func (Field[T]) ArgRemove added in v0.13.0

func (field Field[T]) ArgRemove(name string) Field[T]

func (Field[T]) ArgSensitive

func (field Field[T]) ArgSensitive(name string) Field[T]

func (Field[T]) Deprecated

func (field Field[T]) Deprecated(paras ...string) Field[T]

Deprecated marks the field as deprecated, meaning it should not be used by new code.

func (Field[T]) Doc

func (field Field[T]) Doc(paras ...string) Field[T]

Doc sets the description of the field. Each argument is joined by two empty lines.

func (Field[T]) Extend added in v0.12.0

func (field Field[T]) Extend() Field[T]

func (Field[T]) FieldDefinition

func (field Field[T]) FieldDefinition() *ast.FieldDefinition

FieldDefinition returns the schema definition of the field.

func (Field[T]) Impure

func (field Field[T]) Impure(reason string, paras ...string) Field[T]

Impure marks the field as "impure", meaning its result may change over time, or it has side effects.

func (Field[T]) Meta

func (field Field[T]) Meta() Field[T]

Meta indicates that the field has no impact on the field's result.

func (Field[T]) View added in v0.12.0

func (field Field[T]) View(view View) Field[T]

View sets a view for this field.

type FieldFunc

type FieldFunc func(context.Context, Object, map[string]Input) (Typed, error)

FieldFunc is a function that implements a field on an object while limited to the object's external interface.

type FieldSpec

type FieldSpec struct {
	// Name is the name of the field.
	Name string
	// Description is the description of the field.
	Description string
	// Args is the list of arguments that the field accepts.
	Args InputSpecs
	// Type is the type of the field's result.
	Type Typed
	// Meta indicates that the field has no impact on the field's result.
	Meta bool
	// ImpurityReason indicates that the field's result may change over time.
	ImpurityReason string
	// DeprecatedReason deprecates the field and provides a reason.
	DeprecatedReason string
	// Module is the module that provides the field's implementation.
	Module *call.Module
	// Directives is the list of GraphQL directives attached to this field.
	Directives []*ast.Directive
	// contains filtered or unexported fields
}

FieldSpec is a specification for a field.

func (FieldSpec) FieldDefinition

func (spec FieldSpec) FieldDefinition() *ast.FieldDefinition

type Fields

type Fields[T Typed] []Field[T]

Fields defines a set of fields for an Object type.

func (Fields[T]) Install

func (fields Fields[T]) Install(server *Server)

Install installs the field's Object type if needed, and installs all fields into the type.

type Float

type Float float64

Float is a GraphQL Float scalar.

func NewFloat

func NewFloat(val float64) Float

func (Float) DecodeInput

func (Float) DecodeInput(val any) (Input, error)

func (Float) Decoder

func (Float) Decoder() InputDecoder

func (Float) Float64

func (f Float) Float64() float64

func (Float) MarshalJSON

func (f Float) MarshalJSON() ([]byte, error)

func (Float) SetField

func (f Float) SetField(v reflect.Value) error

func (Float) ToLiteral

func (f Float) ToLiteral() call.Literal

func (Float) Type

func (Float) Type() *ast.Type

func (Float) TypeDefinition

func (f Float) TypeDefinition(views ...string) *ast.Definition

func (Float) TypeName

func (Float) TypeName() string

func (*Float) UnmarshalJSON

func (f *Float) UnmarshalJSON(p []byte) error

type ID

type ID[T Typed] struct {
	// contains filtered or unexported fields
}

ID is a type-checked ID scalar.

func NewDynamicID

func NewDynamicID[T Typed](id *call.ID, typed T) ID[T]

func NewID

func NewID[T Typed](id *call.ID) ID[T]

func WalkedIDs added in v0.12.1

func WalkedIDs[T Typed](idWalker *IDWalker) []ID[T]

func (*ID[T]) Decode

func (i *ID[T]) Decode(str string) error

func (ID[T]) DecodeInput

func (i ID[T]) DecodeInput(val any) (Input, error)

New creates a new ID with the given value.

It accepts either an *call.ID or a string. The string is expected to be the base64-encoded representation of an *call.ID.

func (ID[T]) Decoder

func (i ID[T]) Decoder() InputDecoder

func (ID[T]) Display

func (i ID[T]) Display() string

func (ID[T]) Encode

func (i ID[T]) Encode() (string, error)

func (ID[T]) ID

func (i ID[T]) ID() *call.ID

ID returns the ID of the value.

func (ID[T]) Load

func (i ID[T]) Load(ctx context.Context, server *Server) (Instance[T], error)

Load loads the instance with the given ID from the server.

func (ID[T]) MarshalJSON

func (i ID[T]) MarshalJSON() ([]byte, error)

func (ID[T]) SetField

func (i ID[T]) SetField(v reflect.Value) error

func (ID[T]) String

func (i ID[T]) String() string

String returns the ID in ClassID@sha256:... format.

func (ID[T]) ToLiteral

func (i ID[T]) ToLiteral() call.Literal

func (ID[T]) Type

func (i ID[T]) Type() *ast.Type

Type returns the GraphQL type of the value.

func (ID[T]) TypeDefinition

func (i ID[T]) TypeDefinition(views ...string) *ast.Definition

TypeDefinition returns the GraphQL definition of the type.

func (ID[T]) TypeName

func (i ID[T]) TypeName() string

TypeName returns the name of the type with "ID" appended, e.g. `FooID`.

func (*ID[T]) UnmarshalJSON

func (i *ID[T]) UnmarshalJSON(p []byte) error

type IDType

type IDType interface {
	Input
	IDable
	ScalarType
}

type IDWalker added in v0.12.1

type IDWalker struct {
	// contains filtered or unexported fields
}

func WalkID added in v0.12.1

func WalkID(id *call.ID, skipTopLevel bool) (*IDWalker, error)

type IDable

type IDable interface {
	// ID returns the ID of the value.
	ID() *call.ID
}

type Input

type Input interface {
	// All Inputs are typed.
	Typed
	// All Inputs are able to be represented as a Literal.
	call.Literate
	// All Inputs now how to decode new instances of themselves.
	Decoder() InputDecoder
}

Input represents any value which may be passed as an input.

type InputDecoder

type InputDecoder interface {
	// Decode converts a value to the Input type, if possible.
	DecodeInput(any) (Input, error)
}

InputDecoder is a type that knows how to decode values into Inputs.

type InputObject

type InputObject[T Type] struct {
	Value T
}

func (InputObject[T]) Decoder

func (InputObject[T]) Decoder() InputDecoder

func (InputObject[T]) ToLiteral

func (input InputObject[T]) ToLiteral() call.Literal

func (InputObject[T]) Type

func (InputObject[T]) Type() *ast.Type

type InputObjectSpec

type InputObjectSpec struct {
	Name        string
	Description string
	Fields      InputSpecs
}

func MustInputSpec

func MustInputSpec(val Type) InputObjectSpec

func (InputObjectSpec) Install

func (spec InputObjectSpec) Install(srv *Server)

func (InputObjectSpec) Type

func (spec InputObjectSpec) Type() *ast.Type

func (InputObjectSpec) TypeDefinition

func (spec InputObjectSpec) TypeDefinition(views ...string) *ast.Definition

func (InputObjectSpec) TypeName

func (spec InputObjectSpec) TypeName() string

type InputSpec

type InputSpec struct {
	// Name is the name of the argument.
	Name string
	// Description is the description of the argument.
	Description string
	// Type is the type of the argument.
	Type Input
	// Default is the default value of the argument.
	Default Input
	// DeprecatedReason deprecates the input and provides a reason.
	DeprecatedReason string
	// Sensitive indicates that the value of this arg is sensitive and should be
	// omitted from telemetry.
	Sensitive bool
	// Directives is the list of GraphQL directives attached to this input.
	Directives []*ast.Directive
}

InputSpec specifies a field argument, or an input field.

type InputSpecs

type InputSpecs []InputSpec

func (InputSpecs) ArgumentDefinitions

func (specs InputSpecs) ArgumentDefinitions() []*ast.ArgumentDefinition

func (InputSpecs) FieldDefinitions

func (specs InputSpecs) FieldDefinitions() []*ast.FieldDefinition

func (InputSpecs) Lookup

func (specs InputSpecs) Lookup(name string) (InputSpec, bool)

type Inputs

type Inputs []NamedInput

func (Inputs) Lookup

func (args Inputs) Lookup(name string) (Input, bool)

type Instance

type Instance[T Typed] struct {
	Constructor *call.ID
	Self        T
	Class       Class[T]
	Module      *call.ID
}

Instance is an instance of an Object type.

func NewInstanceForCurrentID added in v0.13.6

func NewInstanceForCurrentID[P, T Typed](
	ctx context.Context,
	srv *Server,
	parent Instance[P],
	self T,
) (Instance[T], error)

NewInstanceForCurrentID creates a new Instance that's set to the current ID from the given self value.

func (Instance[T]) ID

func (r Instance[T]) ID() *call.ID

ID returns the ID of the instance.

func (Instance[T]) IDFor

func (r Instance[T]) IDFor(ctx context.Context, sel Selector) (*call.ID, error)

func (Instance[T]) ObjectType

func (r Instance[T]) ObjectType() ObjectType

ObjectType returns the ObjectType of the instance.

func (Instance[T]) Select

func (r Instance[T]) Select(ctx context.Context, sel Selector) (val Typed, err error)

Select calls a field on the instance.

func (Instance[T]) String

func (r Instance[T]) String() string

String returns the instance in Class@sha256:... format.

func (Instance[T]) Type

func (o Instance[T]) Type() *ast.Type

Type returns the type of the instance.

func (Instance[T]) Unwrap

func (r Instance[T]) Unwrap() Typed

Unwrap returns the inner value of the instance.

type Int

type Int int64

Int is a GraphQL Int scalar.

func NewInt

func NewInt[T constraints.Integer](val T) Int

func (Int) DecodeInput

func (Int) DecodeInput(val any) (Input, error)

func (Int) Decoder

func (Int) Decoder() InputDecoder

func (Int) Int

func (i Int) Int() int

func (Int) Int64

func (i Int) Int64() int64

func (Int) MarshalJSON

func (i Int) MarshalJSON() ([]byte, error)

func (Int) SetField

func (i Int) SetField(v reflect.Value) error

func (Int) ToLiteral

func (i Int) ToLiteral() call.Literal

func (Int) Type

func (Int) Type() *ast.Type

func (Int) TypeDefinition

func (i Int) TypeDefinition(views ...string) *ast.Definition

func (Int) TypeName

func (Int) TypeName() string

func (*Int) UnmarshalJSON

func (i *Int) UnmarshalJSON(p []byte) error

type Loadable

type Loadable interface {
	Load(context.Context, *Server) (Typed, error)
}

type NamedInput

type NamedInput struct {
	Name  string
	Value Input
}

func (NamedInput) String

func (arg NamedInput) String() string

type Nullable

type Nullable[T Typed] struct {
	Value T
	Valid bool
}

Nullable wraps a type and allows it to be null.

This is used for optional arguments and return values.

func MapOpt

func MapOpt[I Input, R Typed](opt Optional[I], fn func(I) (R, error)) (Nullable[R], error)

func NonNull

func NonNull[T Typed](val T) Nullable[T]

func Null

func Null[T Typed]() Nullable[T]

func (Nullable[T]) Deref

func (n Nullable[T]) Deref() (Typed, bool)

func (Nullable[T]) MarshalJSON

func (n Nullable[T]) MarshalJSON() ([]byte, error)

func (Nullable[T]) Type

func (n Nullable[T]) Type() *ast.Type

func (*Nullable[T]) UnmarshalJSON

func (n *Nullable[T]) UnmarshalJSON(p []byte) error

type Object

type Object interface {
	Typed
	IDable
	// ObjectType returns the type of the object.
	ObjectType() ObjectType
	// IDFor returns the ID representing the return value of the given field.
	IDFor(context.Context, Selector) (*call.ID, error)
	// Select evaluates the selected field and returns the result.
	//
	// The returned value is the raw Typed value returned from the field; it must
	// be instantiated with a class for further selection.
	//
	// Any Nullable values are automatically unwrapped.
	Select(context.Context, Selector) (Typed, error)
}

Object represents an Object in the graph which has an ID and can have sub-selections.

type ObjectType

type ObjectType interface {
	Type
	// Typed returns a Typed value whose Type refers to the object type.
	Typed() Typed
	// IDType returns the scalar type for the object's IDs.
	IDType() (IDType, bool)
	// New creates a new instance of the type.
	New(id *call.ID, val Typed) (Object, error)
	// ParseField parses the given field and returns a Selector and an expected
	// return type.
	ParseField(ctx context.Context, view string, astField *ast.Field, vars map[string]any) (Selector, *ast.Type, error)
	// Extend registers an additional field onto the type.
	//
	// Unlike natively added fields, the extended func is limited to the external
	// Object interface.
	Extend(spec FieldSpec, fun FieldFunc)
}

ObjectType represents a GraphQL Object type.

type Optional

type Optional[I Input] struct {
	Value I
	Valid bool
}

Optional wraps a type and allows it to be null.

This is used for optional arguments and return values.

func NoOpt

func NoOpt[I Input]() Optional[I]

NoOpt returns an empty Optional value.

func Opt

func Opt[I Input](v I) Optional[I]

func (Optional[I]) DecodeInput

func (o Optional[I]) DecodeInput(val any) (Input, error)

func (Optional[I]) Decoder

func (o Optional[I]) Decoder() InputDecoder

func (Optional[I]) Deref

func (o Optional[I]) Deref() (Typed, bool)

func (Optional[I]) GetOr

func (n Optional[I]) GetOr(v I) I

GetOr returns the value of the Optional, or the given value if the Optional is empty.

func (Optional[I]) MarshalJSON

func (o Optional[I]) MarshalJSON() ([]byte, error)

func (Optional[I]) ToLiteral

func (o Optional[I]) ToLiteral() call.Literal

func (Optional[I]) ToNullable

func (o Optional[I]) ToNullable() Nullable[I]

func (Optional[I]) Type

func (o Optional[I]) Type() *ast.Type

func (*Optional[I]) UnmarshalJSON

func (o *Optional[I]) UnmarshalJSON(p []byte) error

type PanicError added in v0.10.0

type PanicError struct {
	Cause     any
	Self      Object
	Selection Selection
	Stack     []byte
}

func (PanicError) Error added in v0.10.0

func (err PanicError) Error() string

type Scalar added in v0.11.3

type Scalar[T ScalarValue] struct {
	Name  string
	Value T
}

Scalar is a GraphQL scalar.

func NewScalar added in v0.11.3

func NewScalar[T ScalarValue](name string, val T) Scalar[T]

func (Scalar[T]) DecodeInput added in v0.11.3

func (s Scalar[T]) DecodeInput(val any) (Input, error)

func (Scalar[T]) Decoder added in v0.11.3

func (s Scalar[T]) Decoder() InputDecoder

func (Scalar[T]) MarshalJSON added in v0.11.3

func (s Scalar[T]) MarshalJSON() ([]byte, error)

func (Scalar[T]) ToLiteral added in v0.11.3

func (s Scalar[T]) ToLiteral() call.Literal

func (Scalar[T]) Type added in v0.11.3

func (s Scalar[T]) Type() *ast.Type

func (Scalar[T]) TypeDefinition added in v0.11.3

func (s Scalar[T]) TypeDefinition(views ...string) *ast.Definition

func (Scalar[T]) TypeName added in v0.11.3

func (s Scalar[T]) TypeName() string

func (*Scalar[T]) UnmarshalJSON added in v0.11.3

func (s *Scalar[T]) UnmarshalJSON(p []byte) error

type ScalarType

type ScalarType interface {
	Type
	InputDecoder
}

ScalarType represents a GraphQL Scalar type.

type ScalarValue added in v0.11.3

type ScalarValue interface {
	ScalarType
	Input
}

type Selection

type Selection struct {
	Alias         string
	Selector      Selector
	Subselections []Selection
}

Selection represents a selection of a field on an object.

func (Selection) Name

func (sel Selection) Name() string

Name returns the name of the selection, which is either the alias or the field name.

type Selector

type Selector struct {
	Field string
	Args  []NamedInput
	Nth   int
	View  string
}

Selector specifies how to retrieve a value from an Instance.

func (Selector) AppendTo

func (sel Selector) AppendTo(id *call.ID, spec FieldSpec) *call.ID

func (Selector) String

func (sel Selector) String() string

type Server

type Server struct {

	// View is the view that is applied to all queries on this server
	View string

	// Cache is the inner cache used by the server. It can be replicated to
	// another *Server to inherit and share caches.
	//
	// TODO: copy-on-write
	Cache Cache
	// contains filtered or unexported fields
}

Server represents a GraphQL server whose schema is dynamically modified at runtime.

func NewServer

func NewServer[T Typed](root T) *Server

NewServer returns a new Server with the given root object.

func (*Server) Around

func (s *Server) Around(rec AroundFunc)

Around installs a function to be called around every non-cached selection.

func (*Server) Complexity

func (s *Server) Complexity(typeName, field string, childComplexity int, args map[string]interface{}) (int, bool)

Complexity returns the complexity of the given field.

func (*Server) Exec

Exec implements graphql.ExecutableSchema.

func (*Server) ExecOp

func (s *Server) ExecOp(ctx context.Context, gqlOp *graphql.OperationContext) (map[string]any, error)

func (*Server) InstallDirective

func (s *Server) InstallDirective(directive DirectiveSpec)

InstallDirective installs the given Directive type into the schema.

func (*Server) InstallObject

func (s *Server) InstallObject(class ObjectType)

InstallObject installs the given Object type into the schema.

func (*Server) InstallScalar

func (s *Server) InstallScalar(scalar ScalarType)

InstallScalar installs the given Scalar type into the schema.

func (*Server) InstallTypeDef

func (s *Server) InstallTypeDef(def TypeDef)

InstallTypeDef installs an arbitrary type definition into the schema.

func (*Server) Load

func (s *Server) Load(ctx context.Context, id *call.ID) (Object, error)

Load loads the object with the given ID.

func (*Server) ObjectType

func (s *Server) ObjectType(name string) (ObjectType, bool)

ObjectType returns the ObjectType with the given name, if it exists.

func (*Server) Query

func (s *Server) Query(ctx context.Context, query string, vars map[string]any) (map[string]any, error)

Query is a convenience method for executing a query against the server without having to go through HTTP. This can be useful for introspection, for example.

func (*Server) Resolve

func (s *Server) Resolve(ctx context.Context, self Object, sels ...Selection) (map[string]any, error)

Resolve resolves the given selections on the given object.

Each selection is resolved in parallel, and the results are returned in a map whose keys correspond to the selection's field name or alias.

func (*Server) Root

func (s *Server) Root() Object

Root returns the root object of the server. It is suitable for passing to Resolve to resolve a query.

func (*Server) ScalarType

func (s *Server) ScalarType(name string) (ScalarType, bool)

ScalarType returns the ScalarType with the given name, if it exists.

func (*Server) Schema

func (s *Server) Schema() *ast.Schema

Schema returns the current schema of the server.

func (*Server) Select

func (s *Server) Select(ctx context.Context, self Object, dest any, sels ...Selector) error

Select evaluates a series of chained field selections starting from the given object and assigns the final result value into dest.

func (*Server) TypeDef

func (s *Server) TypeDef(name string) (TypeDef, bool)

InputType returns the InputType with the given name, if it exists.

type Setter

type Setter interface {
	SetField(reflect.Value) error
}

Setter allows a type to populate fields of a struct.

This is how builtins are supported.

type String

type String string

String is a GraphQL String scalar.

func NewString

func NewString(val string) String

func (String) DecodeInput

func (String) DecodeInput(val any) (Input, error)

func (String) Decoder

func (String) Decoder() InputDecoder

func (String) MarshalJSON

func (s String) MarshalJSON() ([]byte, error)

func (String) SetField

func (s String) SetField(v reflect.Value) error

func (String) String

func (s String) String() string

func (String) ToLiteral

func (s String) ToLiteral() call.Literal

func (String) Type

func (String) Type() *ast.Type

func (String) TypeDefinition

func (s String) TypeDefinition(views ...string) *ast.Definition

func (String) TypeName

func (String) TypeName() string

func (*String) UnmarshalJSON

func (s *String) UnmarshalJSON(p []byte) error

type Type

type Type interface {
	// TypeName returns the name of the type.
	TypeName() string
}

Type is an object that defines a new GraphQL type.

type TypeDef

type TypeDef interface {
	Type
	Definitive
}

TypeDef is a type whose sole practical purpose is to define a GraphQL type, so it explicitly includes the Definitive interface.

type Typed

type Typed interface {
	// Type returns the GraphQL type of the value.
	Type() *ast.Type
}

Typed is any value that knows its GraphQL type.

type View added in v0.12.0

type View interface {
	Contains(string) bool
}
var GlobalView View = nil

GlobalView is the default global view. Everyone can see it, and it behaves identically everywhere.

type Wrapper

type Wrapper interface {
	Unwrap() Typed
}

Wrapper is an interface for types that wrap another type.

Directories

Path Synopsis
internal
ioctx
Package ioctx provides a way to pass standard input, output, and error streams through a context.Context.
Package ioctx provides a way to pass standard input, output, and error streams through a context.Context.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL