handler

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Sep 22, 2026 License: Apache-2.0 Imports: 9 Imported by: 150

Documentation

Overview

Package handler holds the stabilized public custom-handler contract surface for Datly 1.0.

Its core is intentionally small:

  • Func[I,O] for simple pure handlers
  • Contract[I,O] for explicit runtime-aware handlers
  • Binder plus InputKey for invocation-scoped value access
  • Session as the reduced binder/response facade; logger, validator, message bus, and data services are binder-scoped capabilities rather than session APIs
  • generic session and pre-invoke hook context carriers
  • plain public lifecycle hooks

It must not regrow Datly runtime internals such as SQL execution, transaction/state managers, route execution, or transport-specific hooks.

Index

Constants

View Source
const DataSyncKey = syncKey("dataSync")

DataSyncKey is the context key used to carry *DataSync through hooks that coordinate sibling view readiness.

Variables

This section is empty.

Functions

func HookApplied

func HookApplied(ctx context.Context) bool

HookApplied reports whether ctx already carries the pre-invoke hook-applied marker.

func InvokeWithSession

func InvokeWithSession(
	ctx context.Context,
	sess Session,
	input any,
	invoke func(context.Context, any) (any, error),
) (any, error)

InvokeWithSession marks the hook as already applied, attaches sess to the invocation context, and then delegates to invoke.

func IsCacheWarmup

func IsCacheWarmup(ctx context.Context) bool

func RunPreInvokeHook

func RunPreInvokeHook(ctx context.Context, input any, hook func(context.Context, any) error) error

RunPreInvokeHook runs hook unless the context already carries the hook-applied marker.

func WithCacheWarmup

func WithCacheWarmup(ctx context.Context, phase WarmupPhase) context.Context

WithCacheWarmup marks a trusted runtime-owned warmup phase. Transport values must never be converted into this context capability.

func WithHookApplied

func WithHookApplied(ctx context.Context) context.Context

WithHookApplied marks ctx so a pre-invoke hook can recognize that it has already run for the current invocation.

func WithReadMetadata

func WithReadMetadata(ctx context.Context, value ReadMetadata) context.Context

WithReadMetadata installs invocation-local read-only evidence. A nil value shadows inherited evidence so nested components cannot borrow parent fields.

func WithSession

func WithSession(ctx context.Context, sess Session) context.Context

WithSession attaches one public handler Session to ctx.

Types

type AfterQueueHook

type AfterQueueHook[T, P, O any] interface {
	AfterQueue(context.Context, *T, LifecycleContext[T, P, O]) error
}

AfterQueueHook observes successfully queued mutation work. Queueing is not a commit: publishing commit-dependent messages belongs to outcome-aware finalization, not this hook. The same object also serves Init and Validate.

type AfterSequenceHook

type AfterSequenceHook[T, P, O any] interface {
	AfterSequence(context.Context, *T, LifecycleContext[T, P, O]) error
}

AfterSequenceHook is an optional capability of the same invocation-scoped EntityHooks object. The generated program calls it after sequencing and before diffing. Validated business values and their markers must remain unchanged; only identity/link processing allowed by the compiled policy may adjust rows.

type Binder

type Binder interface {
	Bind(ctx context.Context, target any) error
	Lookup(ctx context.Context, key ValueKey) (any, bool, error)
}

Binder resolves and binds values for one invocation scope. It is intentionally narrow and does not expose service construction.

Lookup returns (nil, false, nil) for an unknown key. An error is reserved for resolution failures of a known key.

type Capabilities

type Capabilities struct {
	Differ     differ.Differ
	Logger     Logger
	Validator  Validator
	MessageBus MessageBus
	// Connector is absent unless the application explicitly grants DB access.
	// It is not part of managed Data and never provides a transaction implicitly.
	Connector connector.Provider
}

Capabilities groups fixed handler primitives supplied by an invocation. Database Data remains invocation-owned and is exposed independently by DataKey.

type Conflict

type Conflict struct {
	Entity string
	Field  string
	Reason string
}

Conflict reports a failed comparison with the authorized Previous projection. It is a validation result; it does not imply database locking or an atomic compare-and-write operation.

func (*Conflict) Error

func (e *Conflict) Error() string

func (*Conflict) StatusCode

func (e *Conflict) StatusCode() int

StatusCode exposes the validation conflict through the standard response contract.

type Contract

type Contract[I any, O any] interface {
	Exec(ctx context.Context, sess Session, input *I, output *O) error
}

Contract is the minimal public custom-handler contract. Metadata remains the canonical source of handler identity; this is conformance-facing only.

type ContractFunc

type ContractFunc[I any, O any] func(ctx context.Context, sess Session, input *I, output *O) error

ContractFunc adapts a function to Contract.

func (ContractFunc[I, O]) Exec

func (f ContractFunc[I, O]) Exec(ctx context.Context, sess Session, input *I, output *O) error

type DML

type DML interface {
	Insert(table string, value any) error
	Update(table string, value any) error
	Delete(table string, value any) error
	Execute(statement string, args ...any) error
}

DML is the narrow buffered write contract available to handlers. Transaction completion is available separately through Flusher and Data.

type Data

type Data interface {
	DML
	Sequencer
	Flusher
}

Data is the complete handler data capability. Focused consumers may request DML, Sequencer, or Flusher independently.

type DataSync

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

DataSync coordinates cross-view hook ordering. A relation registers its Holder key before fetching begins (Put), releases it when data is ready (Delete), and dependents block in Wait until the lock is released. Ported faithfully from xdatly/handler/sync.go.

func NewDataSync

func NewDataSync() *DataSync

func (*DataSync) Delete

func (d *DataSync) Delete(key string)

func (*DataSync) Get

func (d *DataSync) Get(key string) *sync.RWMutex

func (*DataSync) Put

func (d *DataSync) Put(key string)

func (*DataSync) Wait

func (d *DataSync) Wait(key string) bool

Wait blocks until the named relation's data is available. Returns false when the key was never Put (no-op is safe).

type EntityHooks

type EntityHooks[T, P, O any] interface {
	Init(context.Context, *T, LifecycleContext[T, P, O]) error
	Validate(context.Context, *T, LifecycleContext[T, P, O]) error
}

EntityHooks is implemented by a reusable, invocation-scoped hook object. Init runs after initial presence synchronization and invariant backfill; it uses marker-aware setters when changing business values. Validate then runs on the same object and must not mutate values, markers or the previous snapshot. Component adapters supply input-specific configuration, scoped services and the invocation-owned typed output without coupling entity types themselves to an application contract.

type EntitySnapshot

type EntitySnapshot[T any] interface {
	OriginalPresence
	SyncPresence(current *T) error
}

EntitySnapshot retains an entity's pre-Init/InitMCP processing baseline and original presence. It is not the previous database row used for backfill. Generated implementations keep captured values, identities and associations private and may describe a particular relation path or selected projection.

SyncPresence traverses the captured entity graph, marking changed non-identity values while preserving explicit working markers. It reads business values without changing them and never mutates the snapshot or reinterprets later IDs as original identity. Nil current is a no-op. On error, all working markers remain unchanged; implementations validate associations before applying marks. Ambiguous entity associations return an error rather than guessing a match.

These are two separate methods: generated owned entities expose entity.SyncPresence(snapshot EntitySnapshot[T]) error, which delegates to this interface's snapshot.SyncPresence(entity *T) error. Linked entities use the latter directly without adding methods to a foreign Go type.

type EntityState

type EntityState[T, P any] struct {
	Previous       *T
	Parent         *P
	Original       OriginalPresence
	PreviousFields FieldSet
	SelfParent     *T
}

EntityState contains the typed context of one entity-processing operation. Previous must be detached from working values and treated as read-only by hooks. PreviousFields identifies loaded fields when previous rows are a projection; a missing field must not be interpreted as a known zero value. Parent is the declared enclosing relation parent and is nil for a root role. SelfParent is the immediate parent through a recursive self edge; it is nil at the self-tree root. A self descendant retains the enclosing Parent, so a single typed hook contract can observe both contexts without using any. Original identity presence is independent from any identifier assigned later by initialization or sequencing.

type ErrorFinalizer

type ErrorFinalizer interface {
	Finalize(ctx context.Context, err error) error
}

ErrorFinalizer is the reduced public error-aware lifecycle hook for outputs that need the terminal handler error when finalizing.

type FieldSet

type FieldSet interface {
	Has(field string) bool
}

FieldSet is a read-only view of canonical Go field names. Has returns false for unknown fields; it does not resolve JSON names or SQL aliases.

type Finalizer

type Finalizer interface {
	Finalize(ctx context.Context) error
}

Finalizer is the reduced public success-path lifecycle hook for outputs or other handler-bound values that need post-execution cleanup/follow-up without exposing transport- or runtime-specific finalization concerns.

type Flusher

type Flusher interface {
	Flush(ctx context.Context, table string) error
}

Flusher executes buffered writes. Implementations complete transactions they open themselves and leave supplied transactions to their owner.

type Func

type Func[I any, O any] func(ctx context.Context, input *I) (*O, error)

Func is the typed pure-function handler contract. Use Contract when a custom handler needs scoped DI or response control.

type Initializer

type Initializer interface {
	Init(ctx context.Context) error
}

Initializer is the reduced public pre-execution lifecycle hook for inputs or other handler-bound values that need request-context initialization without binding themselves to Datly runtime internals.

type InjectorFinalizer

type InjectorFinalizer interface {
	Finalize(context.Context, InjectorLookup) error
}

InjectorFinalizer composes conditional dependencies before transaction completion. Its child work participates in the root unit of work. Errors prevent owned commit; an existing operation error is never discarded. It takes precedence over ordinary output finalizers. OutcomeFinalizer handlers retain ownership of their separate result-aware completion lifecycle.

type InjectorLookup

type InjectorLookup = func(context.Context, Route) (Binder, error)

InjectorLookup resolves a route without executing it. The returned Binder executes that component once on its first Bind or ResultKey lookup. Bind uses native binding tags to match the component result to the destination. Both lookup and binders are valid only during the Finalize call; calls must be awaited. Call contexts supply cancellation while retaining invocation values.

type InputCapturer

type InputCapturer[I any] interface {
	CaptureInput(context.Context, *I) (any, error)
}

InputCapturer optionally captures bound input before Init and InitMCP run. CaptureInput must not mutate input. It returns an invocation-local snapshot with detached original values/markers, or nil when no capture is needed. The runtime treats the result as opaque rather than implementing mutation policy or exposing a second binding model.

type InvocationInfo

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

InvocationInfo is immutable execution metadata propagated through context. Private fields prevent consumers from changing the capability selected by the runtime after retrieving it.

func InvocationFromContext

func InvocationFromContext(ctx context.Context) *InvocationInfo

InvocationFromContext returns request metadata when no explicit invocation descriptor has been installed.

func (*InvocationInfo) IsCacheWarmup

func (i *InvocationInfo) IsCacheWarmup() bool

func (*InvocationInfo) MayBypassRowAuthorization

func (i *InvocationInfo) MayBypassRowAuthorization() bool

MayBypassRowAuthorization reports an explicit runtime capability. Consumers should not infer authorization policy from IsCacheWarmup alone.

func (*InvocationInfo) Purpose

func (i *InvocationInfo) Purpose() InvocationPurpose

func (*InvocationInfo) WarmupPhase

func (i *InvocationInfo) WarmupPhase() WarmupPhase

type InvocationPurpose

type InvocationPurpose uint8

InvocationPurpose identifies why a handler or predicate is executing.

const (
	InvocationPurposeRequest InvocationPurpose = iota
	InvocationPurposeCacheWarmup
)

type LifecycleContext

type LifecycleContext[T, P, O any] struct {
	EntityState[T, P]
	Output *O
}

LifecycleContext contains the typed state and component output available to one entity lifecycle callback. Output is the invocation-owned response value allocated before lifecycle processing begins. Hooks may use it to accumulate validation violations, warnings and other response metadata. Hooks must not retain Output after the callback or use it concurrently.

EntityState is embedded so existing state access remains direct: callbacks continue to use state.Previous, state.Parent, state.Original and state.SelfParent while gaining state.Output.

type Logger

type Logger = xlogger.Logger

type MessageBus

type MessageBus = xmbus.Service

type NoParent

type NoParent struct{}

NoParent is the typed parent parameter for a root entity's hook state. EntityState[T, NoParent].Parent is nil.

type OnFetcher

type OnFetcher interface {
	OnFetch(ctx context.Context) error
}

OnFetcher is implemented by typed rows that need initialization immediately after SQLx has populated the row and before Datly indexes or relates it.

type OnRelationer

type OnRelationer interface {
	OnRelation(ctx context.Context)
}

OnRelationer is implemented by typed rows that need notification after all selected child relations have been assembled.

type OriginalPresence

type OriginalPresence interface {
	FieldSet
	Available() bool
}

OriginalPresence exposes copied pre-initialization marker bits. Available distinguishes a missing marker from a known marker whose bits are all false. Implementations must not read from the working entity's mutable marker.

type Outcome

type Outcome struct {
	Error        error
	Transactions []TransactionOutcome
}

Outcome is a detached completion snapshot for one root invocation. Error is the operation/completion error. A later finalizer/publication error does not change a reported database commit into a rollback.

func (Outcome) Clone

func (o Outcome) Clone() Outcome

func (Outcome) CommitConfirmed

func (o Outcome) CommitConfirmed() bool

CommitConfirmed is safe for post-commit publication only when every actual managed transaction committed, at least one exists, and completion succeeded. No transaction, caller ownership and unsupported custom Data are not proof.

func (Outcome) State

func (o Outcome) State() TransactionState

State summarizes unit reports without flattening mixed multi-database work into a misleading success or rollback. Transactions retain the full detail.

type ReadMetadata

type ReadMetadata interface {
	Projection(inputField string) (ReadProjection, error)
}

ReadMetadata resolves evidence by the canonical Go field path on the bound component input. It describes the successful binding, not a later reread of a similarly named view. It contains no database handles or mutable row data.

func ReadMetadataFromContext

func ReadMetadataFromContext(ctx context.Context) (ReadMetadata, bool)

type ReadMetadataConsumer

type ReadMetadataConsumer interface {
	RequiresReadMetadata() bool
}

ReadMetadataConsumer opts a handler/definition into input read evidence. Ordinary handlers that do not request it retain their normal read path.

type ReadOutputProjection

type ReadOutputProjection interface {
	Output(holder string) (ReadProjection, error)
}

ReadOutputProjection optionally addresses additional output-envelope slots such as independent derived aggregates. It is separate from ReadProjection so existing implementations keep their root-only contract unchanged.

type ReadProjection

type ReadProjection interface {
	RootHolder() string
	DirectOutput() bool
	Fields(rootOrdinal int, relations ...ReadStep) (FieldSet, error)
}

ReadProjection exposes evidence from one completed typed read. Fields uses the final root ordinal followed by optional relation steps. Unknown evidence and invalid paths return errors; nil must never mean all fields were loaded. RootHolder describes an output envelope; it is empty for direct outputs.

type ReadStep

type ReadStep struct {
	Holder string
	Index  int
}

ReadStep addresses a relation holder and its final row ordinal. Holder is a canonical Go holder path, not a SQL alias or a client-supplied field name.

type Route

type Route struct {
	Method string
	URL    string
	Scope  string
	Name   string
}

Route selects a component by its method and concrete URL (including query parameters). Scope and Name optionally require an exact registered component identity; route lookup still enforces the runtime's exposed route catalog.

type Sequencer

type Sequencer interface {
	Allocate(ctx context.Context, table string, dest any, selector string) error
}

Sequencer allocates identifiers before buffered writes are flushed.

type Session

type Session interface {
	Binder() Binder
	Response() response.Writer
}

Session is the reduced per-invocation custom-handler facade. It stays intentionally small to avoid recreating the old fat session surface.

func SessionFromContext

func SessionFromContext(ctx context.Context) (Session, bool)

SessionFromContext resolves the public handler Session from ctx when one was previously attached with WithSession.

type TransactionOutcome

type TransactionOutcome struct {
	// Unit is an invocation-local ordinal, not a database or transaction handle.
	Unit  int
	State TransactionState
	// Error is a unit-local preparation/completion error, when available.
	Error error
}

type TransactionStarter

type TransactionStarter interface {
	Start(context.Context) error
}

TransactionStarter starts or joins the existing managed Data transaction. Repeated calls and downstream components join the same database unit. The invocation owner completes it; a caller-supplied transaction remains owned by the caller. Distinct databases remain distinct units, not one distributed transaction.

type TransactionState

type TransactionState string

TransactionState reports managed transaction completion, never a planned action. Unknown states deliberately do not imply rollback or commit.

const (
	TransactionNone            TransactionState = "none"
	TransactionCommitted       TransactionState = "committed"
	TransactionRolledBack      TransactionState = "rolled_back"
	TransactionCallerPending   TransactionState = "caller_pending"
	TransactionCommitUnknown   TransactionState = "commit_unknown"
	TransactionRollbackUnknown TransactionState = "rollback_unknown"
	TransactionUnknown         TransactionState = "unknown"
	// Partial means some units committed while other participating units did not.
	TransactionPartial TransactionState = "partial"
	TransactionMixed   TransactionState = "mixed"
)

type Validation

type Validation struct {
	Failed     bool         `json:"failed,omitempty"`
	Violations []*Violation `json:"violations,omitempty"`
	Code       int          `json:"-"`
}

Validation is the typed result shared by Go and template validation consumers. Either Failed or a nonempty Violations list represents failure.

func (*Validation) Err

func (v *Validation) Err() error

Err preserves the typed result for errors.As and returns nil for success.

func (*Validation) Error

func (v *Validation) Error() string

func (*Validation) Messages

func (v *Validation) Messages() []string

Messages returns detached human-readable diagnostics. Raw input values are not included automatically in errors or protocol responses.

func (*Validation) ResponseBody

func (v *Validation) ResponseBody() any

func (*Validation) StatusCode

func (v *Validation) StatusCode() int

StatusCode defaults failed validation to 422; applications may select an explicit code, such as 401 for an authorization-related validation result.

type ValidationOptions

type ValidationOptions struct {
	Action WriteAction
	// Previous is the detached typed database row matched using original
	// identity. Inserts require nil; updates require a row with its complete
	// mapped identity. Unique checks exclude that tuple, never working IDs.
	Previous any
	// PreviousFields is actual read provenance for Previous. Updates require
	// it; unknown identity or constraint dependencies cannot be replaced by
	// zero values from a partial projection. Inserts require nil.
	PreviousFields FieldSet
	// Fields is effective validation coverage, not the persistence Has mask.
	// Inserts require nil (complete checks). Updates require explicit coverage;
	// invariant-backfilled fields may be covered without becoming client writes.
	// Names are canonical Go field names, as with EntityState.PreviousFields.
	Fields FieldSet
	// DeferredFields identifies unavailable INSERT inputs for a generated
	// business-validation pass. It is not a sparse write mask. Only compiled
	// producer authority and original absence may supply this set; a mandatory
	// final pass must validate the completed payload with no fields deferred.
	// UPDATE and calls with SatisfiedReferences cannot defer fields.
	DeferredFields FieldSet
	// SatisfiedReferences identifies exact reference-existence checks already
	// proven by the generated pending-write graph for an INSERT payload. Other
	// constraints remain active. The generated owner must prove matching typed
	// parent keys, INSERT action and write order in the same transaction scope.
	// These are trusted framework facts, never request-bindable assertions.
	SatisfiedReferences []ValidationReference
	// Connector selects a configured connector within the invocation scope.
	// Empty selects that scope's configured default, not an arbitrary database.
	Connector string
	Location  string
	Shallow   bool
}

ValidationOptions supplies mutation policy to the scoped Validator capability. It carries no database or transaction handles. The capability rejects unknown connectors, unknown actions and inconsistent options before performing checks. Generated entity validation is shallow: all frames are validated by the program before any custom EntityHooks.Validate method runs. The framework capability accepts either one entity and one ValidationOptions, or a typed entity slice and one []ValidationOptions argument of equal length. Batch policies retain each candidate's matched prior row and diagnostic location; candidates in a batch must share the entity type and connector.

type ValidationReference

type ValidationReference struct {
	Field  string
	Schema string
	Table  string
	Column string
}

ValidationReference identifies one native reference constraint exactly. Empty schema remains empty; field names are canonical candidate Go fields.

type Validator

type Validator interface {
	Validate(ctx context.Context, value any, opts ...any) (*Validation, error)
}

Validator is the injectable validation service available to custom handlers.

type ValueKey

type ValueKey string
const (
	// InputKey is the reserved canonical component input key exposed to hooks,
	// predicates, and compatibility paths that need direct input visibility.
	InputKey ValueKey = "input"
	// SelectorsKey is the invocation-scoped dynamic view-selector capability.
	// Values are resolved through the Binder; readers must not carry a parallel
	// selector input channel.
	SelectorsKey ValueKey = "selectors"
)
const (
	// DifferKey identifies the typed comparison capability.
	DifferKey ValueKey = "differ"
	// LoggerKey identifies the invocation-scoped logger capability.
	LoggerKey ValueKey = "logger"
	// ValidatorKey identifies the invocation-scoped validation capability.
	ValidatorKey ValueKey = "validator"
	// MessageBusKey identifies the invocation-scoped message-bus capability.
	MessageBusKey ValueKey = "mbus"
	// ConnectorKey is an opt-in exact-name DB provider for specialized handlers.
	ConnectorKey ValueKey = "connector"
)
const (
	// DMLKey identifies the invocation-scoped buffered write capability.
	DMLKey ValueKey = "dml"
	// SequencerKey identifies the invocation-scoped identifier allocator.
	SequencerKey ValueKey = "sequencer"
	// FlusherKey identifies explicit execution of buffered writes.
	FlusherKey ValueKey = "flusher"
	// DataKey identifies the complete invocation data capability.
	DataKey ValueKey = "data"
)
const (
	// CallerOutputKey is the declared source for a conditional child's input fields.
	// Only fields authored with this source receive the calling output's values.
	CallerOutputKey ValueKey = "caller_output"
	// ResultKey resolves the complete typed result of a route-specific binder.
	ResultKey ValueKey = "result"
)
const FrameworkValidatorKey ValueKey = "frameworkValidator"

FrameworkValidatorKey is reserved for the mandatory generated validation phase. It uses the same Validator interface, but cannot be replaced by request values or the optional custom-handler Validator capability.

const InputSnapshotKey ValueKey = "inputSnapshot"

InputSnapshotKey exposes an opt-in capture result through the invocation binder. It is runtime-owned and must never be supplied by transport data or component providers. Generated adapters own the concrete snapshot type.

const ReadMetadataKey ValueKey = "readMetadata"
const TransactionStarterKey ValueKey = "transactionStarter"

TransactionStarterKey selects the invocation-owned transaction startup capability. It never grants commit/rollback or raw transaction access.

type Violation

type Violation struct {
	Location string `json:"location,omitempty"`
	Field    string `json:"field,omitempty"`
	Message  string `json:"message,omitempty"`
	Check    string `json:"check,omitempty"`
}

Violation describes a failed validation rule without owning validation execution.

type WarmupPhase

type WarmupPhase uint8

WarmupPhase distinguishes warmup validation from the cache-filling phase.

const (
	WarmupPhaseNone WarmupPhase = iota
	WarmupPhasePrepare
	WarmupPhaseFill
)

type WriteAction

type WriteAction string

WriteAction is a planned operation, not evidence that a write was committed.

const (
	WriteInsert WriteAction = "insert"
	WriteUpdate WriteAction = "update"
	WriteDelete WriteAction = "delete"
)

type WriteHook

type WriteHook[T, P any] interface {
	BeforeWrite(context.Context, *T, EntityState[T, P], WriteAction) error
}

WriteHook optionally customizes business values before validation, using marker-aware setters after initial synchronization. Identity reconciliation after diffing is a separate phase; this hook is not a commit or message-publication callback.

type WriteInitializer

type WriteInitializer interface {
	InitWrite(ctx context.Context) error
}

WriteInitializer is implemented by typed entities that need preparation after generated relation keys and sequences are available but before a generated handler validates or queues the entity for persistence.

type WriteValidator

type WriteValidator interface {
	ValidateWrite(ctx context.Context) error
}

WriteValidator is implemented by typed entities that need validation after write initialization and before a generated handler queues DML.

Directories

Path Synopsis
Package exec provides dependency-light execution context contracts shared by xdatly handlers and runtimes.
Package exec provides dependency-light execution context contracts shared by xdatly handlers and runtimes.
Package mcp defines the MCP capabilities and lifecycle contracts exposed to xdatly handlers without coupling them to a Datly runtime implementation.
Package mcp defines the MCP capabilities and lifecycle contracts exposed to xdatly handlers without coupling them to a Datly runtime implementation.
Package mutation defines the generated, typed policy consumed by the optional mutation handler.
Package mutation defines the generated, typed policy consumed by the optional mutation handler.

Jump to

Keyboard shortcuts

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