gqlschema

package
v1.131.0 Latest Latest
Warning

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

Go to latest
Published: Sep 10, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Package gqlschema holds the GraphQL schema machinery the platform's graphql connection kind is built on: turning an introspection result into a schema the platform can keep, walking that schema into the operation units an agent discovers and calls, rendering a runnable skeleton for one of them, and deciding whether a document a model wrote may be executed.

It knows nothing about connections, HTTP, personas or tools. It takes schema text and document text and answers questions about them, which is what makes the namespace descent testable against a hand-authored schema rather than against whatever upstream a deployment happens to point at.

Index

Constants

View Source
const DefaultNamespaceDepth = 3

DefaultNamespaceDepth caps how many segments a dotted operation id may have. Three reaches the entity-level verb of a namespaced schema (package, entity, verb) without indexing every leaf of a deep object graph.

View Source
const DefaultSelectionDepth = 4

DefaultSelectionDepth is how deep a rendered selection set goes. Four is what a Relay connection needs to reach data — connection, edges, node, then the node's own scalar fields — so the default skeleton for a paged operation is runnable rather than a stub the caller has to finish.

View Source
const IntrospectionQuery = `` /* 1094-byte string literal not displayed */

IntrospectionQuery is the document sent to an upstream to read its schema. It is the canonical introspection query at the compatibility level every GraphQL server implements: no `isRepeatable` on directives, no `specifiedByURL` on scalars, no `includeDeprecated` argument on `args`. Those fields postdate servers still in production, and a schema read is the one call that must succeed before a connection is usable at all.

The cost of that floor is that directive repeatability is not recorded, so a document repeating a custom directive on one element is refused under strict validation. Such a document passes under schema_validation: warn.

Variables

View Source
var (
	// ErrOperationNameRequired reports a document defining more than one
	// operation with no operation_name naming which to run. GraphQL
	// leaves that undefined, so the platform refuses rather than
	// picking.
	ErrOperationNameRequired = errors.New("gqlschema: document defines more than one operation, so operation_name is required")
	// ErrOperationNotInDocument reports an operation_name the document
	// does not define.
	ErrOperationNotInDocument = errors.New("gqlschema: document defines no operation with that name")
	// ErrNoOperation reports a document with no executable operation
	// (fragments only).
	ErrNoOperation = errors.New("gqlschema: document defines no operation to execute")
	// ErrSubscriptionUnsupported reports a subscription. A subscription
	// is a long-lived stream over a transport this kind does not open.
	ErrSubscriptionUnsupported = errors.New("gqlschema: subscriptions are not supported")
	// ErrIntrospectionSelection reports a document reading the schema
	// rather than the data. The stored schema is what graphql_discover
	// serves, so an agent reaching for __schema is steered there instead
	// of spending a call and a context window on the raw result.
	ErrIntrospectionSelection = errors.New("gqlschema: introspection selections (__schema, __type) are not executed through this tool, so call graphql_discover for the schema")
)

Errors a document is refused with before it is ever sent upstream.

View Source
var ErrNoIntrospection = errors.New("gqlschema: response carried no __schema (introspection may be disabled upstream)")

ErrNoIntrospection reports an introspection response that carried no __schema. Every upstream that disables introspection answers this way, so the connection reports a named cause rather than an empty operation index.

View Source
var ErrOperationNotFound = errors.New("gqlschema: operation not found")

ErrOperationNotFound reports an operation id that no field of the schema answers to.

Functions

func IndexText

func IndexText(s *Schema, op Operation) string

IndexText is what an operation is embedded from and ranked lexically against: its dotted path, the descriptions collected along that path, its argument names and types, and the scalar field names of what it returns. The return type's leaf names are in it because they are the vocabulary a caller asks in — someone looking for an order's ship date searches for "ship date", which appears nowhere in the operation's own name.

func SDLFromIntrospection

func SDLFromIntrospection(payload []byte) (string, error)

SDLFromIntrospection converts an introspection result to SDL. The SDL, not the JSON, is what a connection stores: it is what the parser loads, it is what an operator can read when diagnosing a refused document, and it is the one form both the introspection path and the admin upload path normalize to.

Returns ErrNoIntrospection when the payload carries no __schema at any of the three nesting levels.

func SearchFields

func SearchFields(op Operation) []string

SearchFields are the texts a query's tokens are matched against when an operation is ranked lexically.

Types

type Argument

type Argument struct {
	// Name is the argument name as the document must spell it.
	Name string `json:"name"`
	// Type is the rendered GraphQL type ("String", "ProductFilter!",
	// "[ID!]").
	Type string `json:"type"`
	// Description is the argument's own description, when the schema
	// carries one.
	Description string `json:"description,omitempty"`
	// Required reports a non-null type with no default: a document
	// omitting it does not validate.
	Required bool `json:"required,omitempty"`
	// DefaultValue is the literal the schema declares, or "" for none.
	DefaultValue string `json:"default,omitempty"`
}

Argument is one argument an operation takes.

type Detail

type Detail struct {
	// Operation is the indexed operation this describes.
	Operation Operation
	// InputTypes are the input-object types the arguments reference,
	// expanded one level and deduplicated.
	InputTypes []InputType
	// ReturnShape is the return type's field tree, depth-limited.
	ReturnShape []FieldNode
	// Skeleton is a document that validates against this schema and
	// calls this operation, with every argument bound to a variable.
	Skeleton string
	// Variables is a JSON object literal carrying one entry per
	// argument, ready to edit and send as the variables argument.
	Variables string
}

Detail is everything graphql_discover reports about one operation: what it takes, what it returns, and a document that runs.

func Describe

func Describe(s *Schema, op Operation, selectionDepth int) (Detail, error)

Describe builds the full description of one operation. selectionDepth caps the rendered return shape and skeleton selection; zero or less means DefaultSelectionDepth.

type Document

type Document struct {
	// Raw is the document text as the caller wrote it. It is what goes
	// on the wire: the platform never re-prints a caller's document,
	// so a formatting quirk is never mistaken for a semantic change.
	Raw string
	// Operation is the operation that will execute.
	Operation *ast.OperationDefinition
	// contains filtered or unexported fields
}

Document is a parsed GraphQL document with the operation to execute already resolved.

func Parse

func Parse(raw, operationName string) (*Document, error)

Parse parses a document and resolves which of its operations will execute. operationName may be empty for a single-operation document.

func (*Document) Depth

func (d *Document) Depth() int

Depth measures the executed operation's deepest selection, counting the root fields as depth 1 and expanding fragment spreads inline — the depth an upstream resolves, not the depth the document is written at.

func (*Document) HasIntrospectionSelection

func (d *Document) HasIntrospectionSelection() bool

HasIntrospectionSelection reports the executed operation selecting __schema or __type at its root.

func (*Document) InvokedPaths

func (d *Document) InvokedPaths(idx PathIndex) []string

InvokedPaths reduces the executed operation to the dotted paths it invokes, sorted. The walk descends through a namespace field and stops at the operation underneath it, so a document reaching `masterData { product { query { ... } } }` is authorized as `masterData.product.query` rather than as its root field — which is the difference between a rule that names an entity's verb and a rule that can only name a whole package.

A field that is an operation and also a namespace (an object with scalar fields of its own and object children that are operations in turn) is recorded and descended into, so a rule naming either level governs a document that reaches the deeper one.

Below a recorded operation, a path the index does not hold is that operation's return shape and is not recorded: authorizing it would require a rule per selected field. Above one — at a namespace, or at the root — such a path is recorded as it stands, because nothing has authorized it yet and an index that has not been built must still reach the policy.

Aliases are ignored (the walk reads field names) and fragments are expanded, so a caller cannot reach a denied operation by renaming it or by hiding it in a fragment.

func (*Document) Kind

func (d *Document) Kind() OperationKind

Kind reports the operation kind, in the vocabulary a persona rule names as the method.

func (*Document) TopLevelFields

func (d *Document) TopLevelFields() []string

TopLevelFields returns the field names the executed operation selects at its root, sorted and deduplicated. Aliases are resolved to the underlying field name and fragment spreads are expanded, so a caller cannot reach a denied operation by renaming it or by hiding it in a fragment.

func (*Document) Validate

func (d *Document) Validate(s *Schema) []string

Validate checks the document against a schema, returning one message per violation. An empty result means the document is executable against this schema.

The whole document is validated, not only the operation that will execute: an unused operation with an unknown field is still a sign the caller is working from a schema this connection does not serve.

type FieldNode

type FieldNode struct {
	// Name is the field name, or the inline-fragment condition
	// ("... on Dataset") for a union or interface member.
	Name string `json:"name"`
	// Type is the rendered field type.
	Type string `json:"type"`
	// Description is the field's description, when it has one.
	Description string `json:"description,omitempty"`
	// Deprecated reports the field carrying @deprecated.
	Deprecated bool `json:"deprecated,omitempty"`
	// Fields are the node's own sub-fields, empty at a leaf or at the
	// depth limit.
	Fields []FieldNode `json:"fields,omitempty"`
}

FieldNode is one node of an operation's return shape.

type InputType

type InputType struct {
	// Name is the type name as an argument's type names it.
	Name string `json:"name"`
	// Description is the type's own description.
	Description string `json:"description,omitempty"`
	// Fields are the input object's fields, in schema order.
	Fields []Argument `json:"fields,omitempty"`
}

InputType is an input-object type an argument references, expanded so the caller can fill the argument in without a second lookup.

type Operation

type Operation struct {
	// ID is the kind-prefixed dotted identifier
	// ("query:x3MasterData.product.query"). It is what
	// graphql_discover reports and what an embedding row is keyed on.
	ID string
	// Kind is QUERY or MUTATION.
	Kind OperationKind
	// Path is the dotted id's segments, root field first.
	Path []string
	// Description is the descriptions collected along the path, nearest
	// last, so the operation's own description reads at the end.
	Description string
	// Arguments are the arguments the terminal field takes.
	Arguments []Argument
	// ReturnType is the named type at the bottom of the terminal
	// field's type, with its list and non-null wrappers rendered.
	ReturnType string
	// Deprecated reports the terminal field carrying @deprecated.
	Deprecated bool
}

Operation is one unit of work an agent discovers and calls: a field on a root type, or a field reached by descending through fields that are namespaces rather than work.

func Lookup

func Lookup(ops []Operation, id string) (Operation, bool)

Lookup finds an operation by id. The kind prefix is optional: an agent that read "query:search" back from a ranked list passes it whole, and one that typed "search" from a description gets the same operation as long as only one kind defines it.

func Operations

func Operations(s *Schema, maxDepth int) []Operation

Operations walks a schema into the operations it exposes. maxDepth caps the number of segments in a dotted id; zero or less means DefaultNamespaceDepth.

The walk descends through a field only when the field is a namespace rather than work: it takes no arguments, and it returns a singular object type that is not a Relay connection. Everything else is terminal and becomes an operation. A flat schema therefore indexes its root fields, and a namespaced one indexes the verbs underneath its packages.

Results are ordered by id so two walks of one schema produce the same index.

func (Operation) Dotted

func (o Operation) Dotted() string

Dotted returns the id without its kind prefix.

func (Operation) PolicyPath

func (o Operation) PolicyPath() string

PolicyPath is the path a persona rule matches this operation under: the dotted id with dots as slashes, leading slash included. Together with Kind as the method it puts a GraphQL operation into the same (connection, method, path) space the API route rules already evaluate.

type OperationKind

type OperationKind string

OperationKind distinguishes the two root types a schema exposes for execution. It is also the method an operation is authorized under, so the values are the ones a persona rule names.

const (
	// OperationQuery is a read. Persona rules name it as the method
	// QUERY.
	OperationQuery OperationKind = "QUERY"
	// OperationMutation is a write. Persona rules name it as the method
	// MUTATION.
	OperationMutation OperationKind = "MUTATION"
)

type PathIndex

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

PathIndex is the operation index a document is reduced against: the dotted paths that are operations, and the paths that are namespaces on the way to one. It is what turns "the fields this document selects" into "the operations this document invokes", which is the unit a persona rule names.

func NewPathIndex

func NewPathIndex(ops []Operation, kind OperationKind) PathIndex

NewPathIndex builds the index for one operation kind. Only that kind's operations are in it, because a query document can never invoke a mutation.

type Schema

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

Schema is a loaded GraphQL schema plus the identity of the text it was loaded from. The hash is what an operation index is keyed on: a re-introspection that produces the same schema leaves the index and its embeddings alone, and one that does not rebuilds them.

func Load

func Load(sdl string) (*Schema, error)

Load parses SDL into a schema. The text may be SDL an operator uploaded or SDL rendered from an introspection result; by this point the two are the same thing.

func LoadAny

func LoadAny(payload []byte) (*Schema, error)

LoadAny accepts either SDL or an introspection result and loads whichever it was given. The admin upload route takes both, and an operator pasting a schema should not have to declare which of the two they pasted.

func LoadIntrospection

func LoadIntrospection(payload []byte) (*Schema, error)

LoadIntrospection normalizes an introspection result to SDL and loads it. This is the path a connection takes on register and on reconcile.

func (*Schema) Hash

func (s *Schema) Hash() string

Hash is the sha256 of the SDL, hex-encoded. It identifies the schema version an operation index and its embeddings belong to.

func (*Schema) SDL

func (s *Schema) SDL() string

SDL returns the schema text this schema was loaded from.

Jump to

Keyboard shortcuts

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