entgql

package
v0.0.3 Latest Latest
Warning

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

Go to latest
Published: Apr 14, 2023 License: Apache-2.0 Imports: 32 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// QueryType is the name of the root Query object.
	QueryType = "Query"
	// OrderDirectionEnum is the name of enum OrderDirection
	OrderDirectionEnum = "OrderDirection"
	// RelayCursor is the name of the cursor type
	RelayCursor = "Cursor"
	// RelayNode is the name of the interface that all nodes implement
	RelayNode = "Node"
	// RelayPageInfo is the name of the PageInfo type
	RelayPageInfo = "PageInfo"
)

Variables

View Source
var (
	// CollectionTemplate adds fields collection support using auto eager-load ent edges.
	// More info can be found here: https://spec.graphql.org/June2018/#sec-Field-Collection.
	CollectionTemplate = parseT("template/collection.tmpl")

	// EnumTemplate adds a template implementing MarshalGQL/UnmarshalGQL methods for enums.
	EnumTemplate = parseT("template/enum.tmpl")

	// NodeTemplate implements the Relay Node interface for all types.
	NodeTemplate = parseT("template/node.tmpl")

	// NodeDescriptorTemplate implements the Node descriptor API for all types.
	NodeDescriptorTemplate = parseT("template/node_descriptor.tmpl")

	// PaginationTemplate adds pagination support according to the GraphQL Cursor Connections Spec.
	// More info can be found in the following link: https://relay.dev/graphql/connections.htm.
	PaginationTemplate = parseT("template/pagination.tmpl")

	// TransactionTemplate adds support for ent.Client for opening transactions for the transaction
	// middleware. See transaction.go for for information.
	TransactionTemplate = parseT("template/transaction.tmpl")

	// EdgeTemplate adds edge resolution using eager-loading with a query fallback.
	EdgeTemplate = parseT("template/edge.tmpl")

	// WhereTemplate adds a template for generating <T>WhereInput filters for each schema type.
	WhereTemplate = parseT("template/where_input.tmpl")

	// MutationInputTemplate adds a template for generating Create<T>Input and Update<T>Input for each schema type.
	MutationInputTemplate = parseT("template/mutation_input.tmpl").SkipIf(skipMutationTemplate)

	// AllTemplates holds all templates for extending ent to support GraphQL.
	AllTemplates = []*gen.Template{
		CollectionTemplate,
		EnumTemplate,
		NodeTemplate,
		PaginationTemplate,
		TransactionTemplate,
		EdgeTemplate,
		MutationInputTemplate,
	}

	// TemplateFuncs contains the extra template functions used by entgql.
	TemplateFuncs = template.FuncMap{
		"fieldCollections":    fieldCollections,
		"fieldMapping":        fieldMapping,
		"filterEdges":         filterEdges,
		"filterFields":        filterFields,
		"filterNodes":         filterNodes,
		"gqlIDType":           gqlIDType,
		"gqlMarshaler":        gqlMarshaler,
		"gqlUnmarshaler":      gqlUnmarshaler,
		"hasWhereInput":       hasWhereInput,
		"isRelayConn":         isRelayConn,
		"isSkipMode":          isSkipMode,
		"mutationInputs":      mutationInputs,
		"nodePaginationNames": nodePaginationNames,
		"orderFields":         orderFields,
		"skipMode":            skipModeFromString,
	}
)
View Source
var (
	// ErrRelaySpecDisabled is the error returned when the relay specification is disabled
	ErrRelaySpecDisabled = errors.New("entgql: must enable relay specification via the WithRelaySpec option")
)
View Source
var (
	// WithWhereFilters configures the extension to either add or
	// remove the WhereTemplate from the code generation templates.
	//
	// Deprecated: use WithWhereInputs instead. This option is planned
	// to be removed in future versions.
	WithWhereFilters = WithWhereInputs
)

Functions

func CursorsPredicate

func CursorsPredicate[T any](after, before *Cursor[T], idField, field string, direction OrderDirection) []func(s *sql.Selector)

CursorsPredicate converts the given cursors to predicates.

func ErrNodeNotFound

func ErrNodeNotFound(id interface{}) *gqlerror.Error

ErrNodeNotFound creates a node not found graphql error.

func MultiCursorsPredicate

func MultiCursorsPredicate[T any](after, before *Cursor[T], opts *MultiCursorsOptions) ([]func(s *sql.Selector), error)

MultiCursorsPredicate returns a predicate that filters records by the given cursors.

func QueryField

func QueryField(name ...string) queryFieldAnnotation

QueryField returns an annotation for expose the field on the Query type.

Types

type Annotation

type Annotation struct {
	// OrderField is the ordering field as defined in graphql schema.
	OrderField string `json:"OrderField,omitempty"`
	// MultiOrder indicates that orderBy should accept a list of OrderField terms.
	MultiOrder bool `json:"MultiOrder,omitempty"`
	// Unbind implies the edge field name in GraphQL schema is not equivalent
	// to the name used in ent schema. That means, by default, edges with this
	// annotation will not be eager-loaded on Paginate calls. See the `MapsTo`
	// option in order to load edges be different name mapping.
	Unbind bool `json:"Unbind,omitempty"`
	// Mapping is the edge field names as defined in graphql schema.
	Mapping []string `json:"Mapping,omitempty"`
	// Type is the underlying GraphQL type name (e.g. Boolean).
	Type string `json:"Type,omitempty"`
	// Skip exclude the type
	Skip SkipMode `json:"Skip,omitempty"`
	// RelayConnection enables the Relay Connection specification for the entity.
	// It's also can apply on an edge to create the Relay-style filter.
	RelayConnection bool `json:"RelayConnection,omitempty"`
	// Implements defines a list of interfaces implemented by the type.
	Implements []string `json:"Implements,omitempty"`
	// Directives to add on the field/type.
	Directives []Directive `json:"Directives,omitempty"`
	// QueryField exposes the generated type with the given string under the Query object.
	QueryField *FieldConfig `json:"QueryField,omitempty"`
	// MutationInputs defines the input types for the mutation.
	MutationInputs []MutationConfig `json:"MutationInputs,omitempty"`
}

Annotation annotates fields and edges with metadata for templates.

func Bind deprecated

func Bind() Annotation

Bind returns a binding annotation.

No-op function to avoid breaking the existing schema. You can safely remove this function from your scheme.

Deprecated: the Bind option predates the Unbind option, and it is planned to be removed in future versions. Users should not use this annotation as it is a no-op call, or use `Unbind` in order to disable `Bind`.

func Directives

func Directives(directives ...Directive) Annotation

Directives returns a Directives annotation. The Directives() annotation is used to add directives to a GraphQL type or on the field.

For example, to add the `@deprecated` directive to the `text` field:

type Todo {
	id: ID
	text: String
	...
}

Add the entgql.Directives() to the text field's annotations:

field.Text("text").
	NotEmpty().
	Annotations(
		entgql.Directives(entgql.Deprecated("Use `description` instead.")),
	),

and the GraphQL type will be generated with the directive.

type Todo {
	id: ID
	text: String @deprecated(reason: "Use `description` instead.")
	...
}

func Implements

func Implements(interfaces ...string) Annotation

Implements returns an Implements annotation. The Implements() annotation is used to add implements interfaces to a GraphQL type.

For example, to add the `Entity` to the `Todo` type:

type Todo implements Node {
	id: ID!
	...
}

Add the entgql.Implements("Entity") to the Todo's annotations:

func (Todo) Annotations() []schema.Annotation {
	return []schema.Annotation{
		entgql.Implements("Entity"),
	}
}

and the GraphQL type will be generated with the implements interface.

type Todo implements Node & Entity {
	id: ID!
	...
}

func MapsTo

func MapsTo(names ...string) Annotation

MapsTo returns a mapping annotation.

func MultiOrder

func MultiOrder() Annotation

MultiOrder indicates that orderBy should accept a list of OrderField terms.

func Mutations

func Mutations(inputs ...MutationOption) Annotation

Mutations returns an annotation for generate input types for mutation.

func OrderField

func OrderField(name string) Annotation

OrderField enables ordering in GraphQL for the annotated Ent field with the given name. Note that, the field type must be comparable.

field.Time("created_at").
	Default(time.Now).
	Immutable().
	Annotations(
		entgql.OrderField("CREATED_AT"),
	)

For enum fields, values must be uppercase or mapped using the NamedValues option:

field.Enum("status").
	NamedValues(
		"InProgress", "IN_PROGRESS",
		"Completed", "COMPLETED",
	).
	Default("IN_PROGRESS").
	Annotations(
		entgql.OrderField("STATUS"),
	)

func RelayConnection

func RelayConnection() Annotation

RelayConnection returns an annotation indicating that the node/edge should support pagination. Hence,the returned result is a Relay connection rather than a list of nodes.

Setting this annotation on schema `T` (reside in ent/schema), enables pagination for this type and therefore, Ent will generate all Relay types for this schema, such as: `<T>Edge`, `<T>Connection`, and PageInfo. For example:

func (Todo) Annotations() []schema.Annotation {
	return []schema.Annotation{
		entgql.RelayConnection(),
		entgql.QueryField(),
	}
}

Setting this annotation on an Ent edge indicates that the GraphQL field for this edge should support nested pagination and the returned type is a Relay connection type rather than the actual nodes. For example:

func (Todo) Edges() []ent.Edge {
	return []ent.Edge{
			edge.To("parent", Todo.Type).
				Unique().
				From("children").
				Annotation(entgql.RelayConnection()),
	}
}

The generated GraphQL schema will be:

children(first: Int, last: Int, after: Cursor, before: Cursor): TodoConnection!

Rather than:

children: [Todo!]!

func Skip

func Skip(flags ...SkipMode) Annotation

Skip returns a skip annotation. The Skip() annotation is used to skip generating the type or the field from GraphQL schema.

It gives you the flexibility to skip generating the type or the field based on the SkipMode flags.

For example, if you don't want to expose a field on the <T>WhereInput type you can use the following:

field.String("name").
	Annotations(
		entgql.Skip(entgql.SkipWhereInput),
	)

Since SkipMode is a bit flag, it's possible to skip multiple modes using the bitwise OR operator as follows:

entgql.Skip(entgql.SkipWhereInput | entgql.SkipEnumField)

To skip everything except the type, use the bitwise NOT operator:

entgql.Skip(^entgql.SkipType)

You can also skip all modes with the `entgql.SkipAll` constant which is the default mode.

func Type

func Type(name string) Annotation

Type returns a type mapping annotation. The Type() annotation is used to map the underlying GraphQL type to the type.

To change the GraphQL type for a type:

func (User) Annotations() []schema.Annotation {
	return []schema.Annotation{
		entgql.Type("MasterUser"),
	}
}

To change the GraphQL type for a field (rename enum type):

field.Enum("status").
	NamedValues(
		"InProgress", "IN_PROGRESS",
		"Completed", "COMPLETED",
	).
	Default("IN_PROGRESS").
	Annotations(
		entgql.Type("TodoStatus"),
	)

func Unbind

func Unbind() Annotation

Unbind implies the edge field name in GraphQL schema is not equivalent to the name used in ent schema. That means, by default, edges with this annotation will not be eager-loaded on Paginate calls. See the `MapsTo` option in order to load edges with different name mapping.

func (Todo) Edges() []ent.Edge {
	return []ent.Edge{
		edge.To("parent", Todo.Type).
		Annotations(entgql.Unbind()).
		Unique().
		From("children").
		Annotations(entgql.Unbind()),
	}
}

func (*Annotation) Decode

func (a *Annotation) Decode(annotation interface{}) error

Decode unmarshalls the annotation.

func (Annotation) Merge

func (a Annotation) Merge(other schema.Annotation) schema.Annotation

Merge implements the schema.Merger interface.

func (Annotation) Name

func (Annotation) Name() string

Name implements ent.Annotation interface.

type Cursor

type Cursor[T any] struct {
	ID    T         `msgpack:"i"`
	Value ent.Value `msgpack:"v,omitempty"`
}

Cursor of an edge type.

func (Cursor[T]) MarshalGQL

func (c Cursor[T]) MarshalGQL(w io.Writer)

MarshalGQL implements graphql.Marshaler interface.

func (*Cursor[T]) UnmarshalGQL

func (c *Cursor[T]) UnmarshalGQL(v interface{}) error

UnmarshalGQL implements graphql.Unmarshaler interface.

type Directive

type Directive struct {
	Name      string          `json:"name,omitempty"`
	Arguments []*ast.Argument `json:"arguments,omitempty"`
}

Directive to apply on the field/type.

func Deprecated

func Deprecated(reason string) Directive

Deprecated create `@deprecated` directive to apply on the field/type

func NewDirective

func NewDirective(name string, args ...*ast.Argument) Directive

NewDirective returns a GraphQL directive to use with the entgql.Directives annotation.

type Extension

type Extension struct {
	entc.DefaultExtension
	// contains filtered or unexported fields
}

Extension implements the entc.Extension for providing GraphQL integration.

func NewExtension

func NewExtension(opts ...ExtensionOption) (*Extension, error)

NewExtension creates a new extension with the given configuration.

ex, err := entgql.NewExtension(
	entgql.WithSchemaGenerator(),
	entgql.WithSchemaPath("../ent.graphql"),
	entgql.WithWhereInputs(true),
)

func (*Extension) BuildSchema

func (e *Extension) BuildSchema(g *gen.Graph) (s *ast.Schema, err error)

func (*Extension) Hooks

func (e *Extension) Hooks() []gen.Hook

Hooks of the extension.

func (*Extension) Options

func (e *Extension) Options() []entc.Option

Options of the extension.

func (*Extension) Templates

func (e *Extension) Templates() []*gen.Template

Templates of the extension.

type ExtensionOption

type ExtensionOption func(*Extension) error

ExtensionOption allows for managing the Extension configuration using functional options.

func WithConfigPath

func WithConfigPath(path string, gqlgenOptions ...api.Option) ExtensionOption

WithConfigPath sets the filepath to gqlgen.yml configuration file and injects its parsed version to the global annotations.

Note that, enabling this option is recommended as it improves the GraphQL integration,

func WithMapScalarFunc

func WithMapScalarFunc(scalarFunc func(*gen.Field, gen.Op) string) ExtensionOption

WithMapScalarFunc allows users to provide a custom function that maps an ent.Field (*gen.Field) into its GraphQL scalar type. If the function returns an empty string, the extension fallbacks to its default mapping.

ex, err := entgql.NewExtension(
	entgql.WithMapScalarFunc(func(f *gen.Field, op gen.Op) string {
		if t, ok := knowType(f, op); ok {
			return t
		}
		// Fallback to the default mapping.
		return ""
	}),
)

func WithNodeDescriptor

func WithNodeDescriptor(b bool) ExtensionOption

WithNodeDescriptor configures the extension to either add or remove the NodeDescriptorTemplate from the code generation templates.

In case this option is enabled, EntGQL generates a `Node()` method for each type that returns its representation in one standard way. A common use case for this option is to develop an administrator tool on top of Ent as implemented in: https://github.com/ent/ent/issues/1000#issuecomment-735663175.

func WithOutputWriter

func WithOutputWriter(w func(*ast.Schema) error) ExtensionOption

WithOutputWriter sets the function to write the generated schema.

func WithRelaySpec

func WithRelaySpec(enabled bool) ExtensionOption

WithRelaySpec enables or disables generating the Relay Node interface.

func WithSchemaGenerator

func WithSchemaGenerator() ExtensionOption

WithSchemaGenerator add a hook for generate GQL schema

func WithSchemaHook

func WithSchemaHook(hooks ...SchemaHook) ExtensionOption

WithSchemaHook allows users to provide a list of hooks to run after the GQL schema generation.

func WithSchemaPath

func WithSchemaPath(path string) ExtensionOption

WithSchemaPath sets the filepath to the GraphQL schema to write the generated Ent types. If the file does not exist, it will generate a new schema. Please note that your gqlgen.yml config file should be updated as follows to support multiple schema files:

schema:
 - schema.graphql // existing schema.
 - ent.graphql	  // generated schema.

func WithTemplates

func WithTemplates(templates ...*gen.Template) ExtensionOption

WithTemplates overrides the default templates (entgql.AllTemplates) with specific templates.

func WithWhereInputs

func WithWhereInputs(b bool) ExtensionOption

WithWhereInputs configures the extension to either add or remove the WhereTemplate from the code generation templates.

The WhereTemplate generates GraphQL filters to all types in the ent/schema.

type FieldConfig

type FieldConfig struct {
	// Name is the name of the field in the Query object.
	Name string `json:"Name,omitempty"`

	// Description is the description of the field.
	Description string `json:"Description,omitempty"`

	// Directives to add on the field
	Directives []Directive `json:"Directives,omitempty"`
}

type InputFieldDescriptor

type InputFieldDescriptor struct {
	*gen.Field
	// AppendOp indicates if the field has the Append operator
	AppendOp bool
	// ClearOp indicates if the field has the Clear operator
	ClearOp bool
	// Nullable indicates if the field is nullable.
	Nullable bool
}

InputFieldDescriptor holds the information about a field in the input type. It's shared between GQL and Go types.

func (*InputFieldDescriptor) IsPointer

func (f *InputFieldDescriptor) IsPointer() bool

IsPointer returns true if the Go type should be a pointer

type MultiCursorsOptions

type MultiCursorsOptions struct {
	FieldID     string           // ID field name.
	DirectionID OrderDirection   // ID field direction.
	Fields      []string         // OrderBy fields used by the cursor.
	Directions  []OrderDirection // OrderBy directions used by the cursor.
}

MultiCursorOptions are the options for building the cursor predicates.

type MutationConfig

type MutationConfig struct {
	IsCreate    bool   `json:"IsCreate,omitempty"`
	Description string `json:"Description,omitempty"`
}

MutationConfig hold config for mutation

type MutationDescriptor

type MutationDescriptor struct {
	*gen.Type
	IsCreate bool
}

MutationDescriptor holds information about a GraphQL mutation input.

func (*MutationDescriptor) Builders

func (m *MutationDescriptor) Builders() []string

Builders return the builder's names to apply the input.

func (*MutationDescriptor) Input

func (m *MutationDescriptor) Input() (string, error)

Input returns the input's name.

func (*MutationDescriptor) InputEdges

func (m *MutationDescriptor) InputEdges() ([]*gen.Edge, error)

InputEdges returns the list of fields in the input type.

NOTE(giautm): This method should refactor to return a list of InputFieldDescriptor.

func (*MutationDescriptor) InputFields

func (m *MutationDescriptor) InputFields() ([]*InputFieldDescriptor, error)

InputFields returns the list of fields in the input type.

type MutationOption

type MutationOption interface {
	IsCreate() bool
	GetDescription() string

	// Description allows you to customize the comment of the auto-generated Mutation Input
	//
	// For example,
	//
	//   entgql.Mutations(
	//       entgql.MutationCreate().
	// 		     Description("The fields used in the creation of a TodoItem"),
	//   ),
	//
	// Creates
	//
	//  """The fields used in the creation of a TodoItem"""
	//  input CreateTodoItem {
	//  	"""fields omitted"""
	//  }
	Description(string) MutationOption
}

func MutationCreate

func MutationCreate() MutationOption

func MutationUpdate

func MutationUpdate() MutationOption

type OrderDirection

type OrderDirection string

OrderDirection defines the directions in which to order a list of items.

const (
	// OrderDirectionAsc specifies an ascending order.
	OrderDirectionAsc OrderDirection = "ASC"
	// OrderDirectionDesc specifies a descending order.
	OrderDirectionDesc OrderDirection = "DESC"
)

func (OrderDirection) MarshalGQL

func (o OrderDirection) MarshalGQL(w io.Writer)

MarshalGQL implements graphql.Marshaler interface.

func (OrderDirection) Reverse

func (o OrderDirection) Reverse() OrderDirection

Reverse the direction.

func (OrderDirection) String

func (o OrderDirection) String() string

String implements fmt.Stringer interface.

func (*OrderDirection) UnmarshalGQL

func (o *OrderDirection) UnmarshalGQL(val interface{}) error

UnmarshalGQL implements graphql.Unmarshaler interface.

func (OrderDirection) Validate

func (o OrderDirection) Validate() error

Validate the order direction value.

type PageInfo

type PageInfo[T any] struct {
	HasNextPage     bool       `json:"hasNextPage"`
	HasPreviousPage bool       `json:"hasPreviousPage"`
	StartCursor     *Cursor[T] `json:"startCursor"`
	EndCursor       *Cursor[T] `json:"endCursor"`
}

PageInfo of a connection type.

type PaginationNames

type PaginationNames struct {
	Connection string
	Edge       string
	Node       string
	Order      string
	OrderField string
	WhereInput string
}

PaginationNames holds the names of the pagination fields.

func (*PaginationNames) ConnectionField

func (p *PaginationNames) ConnectionField(name string, hasOrderBy, multiOrder, hasWhereInput bool) *ast.FieldDefinition

func (*PaginationNames) OrderInputDef

func (p *PaginationNames) OrderInputDef() *ast.Definition

func (*PaginationNames) TypeDefs

func (p *PaginationNames) TypeDefs() []*ast.Definition

type SchemaHook

type SchemaHook func(*gen.Graph, *ast.Schema) error

SchemaHook is the hook that run after the GQL schema generation.

type SkipMode

type SkipMode int

SkipMode is a bit flag for the Skip annotation.

const (
	// SkipType skips generating GraphQL types or fields in the schema.
	SkipType SkipMode = 1 << iota
	// SkipEnumField skips generating GraphQL enums for enum fields in the schema.
	SkipEnumField
	// SkipOrderField skips generating GraphQL order inputs and enums for ordered-fields in the schema.
	SkipOrderField
	// SkipWhereInput skips generating GraphQL WhereInput types.
	// If defined on a field, the type will be generated without the field.
	SkipWhereInput
	// SkipMutationCreateInput skips generating GraphQL Create<Type>Input types.
	// If defined on a field, the type will be generated without the field.
	SkipMutationCreateInput
	// SkipMutationUpdateInput skips generating GraphQL Update<Type>Input types.
	// If defined on a field, the type will be generated without the field.
	SkipMutationUpdateInput

	// SkipAll is default mode to skip all.
	SkipAll = SkipType |
		SkipEnumField |
		SkipOrderField |
		SkipWhereInput |
		SkipMutationCreateInput |
		SkipMutationUpdateInput
)

func (SkipMode) Any

func (f SkipMode) Any() bool

Any returns true if the skip annotation was set.

func (SkipMode) Is

func (f SkipMode) Is(mode SkipMode) bool

Is checks if the skip annotation has a specific flag.

type Transactioner

type Transactioner struct{ TxOpener }

Transactioner for graphql mutations.

func (Transactioner) ExtensionName

func (Transactioner) ExtensionName() string

ExtensionName returns the extension name.

func (Transactioner) InterceptResponse

func (t Transactioner) InterceptResponse(ctx context.Context, next graphql.ResponseHandler) *graphql.Response

InterceptResponse runs graphql mutations under a transaction.

func (Transactioner) MutateOperationContext

func (Transactioner) MutateOperationContext(_ context.Context, oc *graphql.OperationContext) *gqlerror.Error

MutateOperationContext serializes field resolvers during mutations.

func (Transactioner) Validate

Validate is called when adding an extension to the server, it allows validation against the servers schema.

type TxOpener

type TxOpener interface {
	OpenTx(ctx context.Context) (context.Context, driver.Tx, error)
}

TxOpener represents types than can open transactions.

type TxOpenerFunc

type TxOpenerFunc func(ctx context.Context) (context.Context, driver.Tx, error)

The TxOpenerFunc type is an adapter to allow the use of ordinary functions as tx openers.

func (TxOpenerFunc) OpenTx

OpenTx returns f(ctx).

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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