Documentation
¶
Overview ¶
Package node is the node-authoring seam. A node is a typed Cfg plus a Run function; the framework owns everything else — JSON decode, the result envelope, the assertion/output post-step, and skip handling. Authors write only a Cfg struct (embedding Base) and one Run function, then Register it.
Index ¶
- func CodeOf(err error) string
- func IsUser(err error) bool
- func References(kind spi.Kind) bool
- func Register[Cfg hasBase](kind spi.Kind, fn Run[Cfg])
- func Routes(kind spi.Kind) bool
- func UserErrf(code, format string, args ...any) error
- type Base
- type Bound
- type Clock
- type FlowReferencer
- type HTTPDoer
- type Result
- type Router
- type Run
- type Runtime
- type SubflowRunner
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func References ¶
References reports whether a kind's config can implement FlowReferencer (module, ...).
func Register ¶
Register binds a kind to its typed Run. Cfg is inferred from fn; the closure erases it so differently-typed nodes share one registry. Call from an init(). Registering a kind twice panics — that is a wiring bug, caught at load.
Types ¶
type Base ¶
type Base struct {
ID string `json:"id"`
Name string `json:"display_name"`
RunWhen spi.RunWhen `json:"run_when,omitempty"`
Assertions []assert.Spec `json:"assertions,omitempty"`
Outputs []output.Spec `json:"outputs,omitempty"`
}
Base is embedded by every node Cfg. It carries identity plus the declared assertions and outputs the framework evaluates after the node runs.
type Bound ¶
type Bound struct {
Base Base
Kind spi.Kind
Run func(ctx context.Context, in value.Value, rt Runtime) (Result, error)
Refs []string // child flow ids (FlowReferencer), for cycle/existence validation
Targets []string // route targets (Router), for branch-target validation
}
Bound is a decoded node ready for the engine: its declared Base, its kind, a type-erased run closure holding the typed Cfg, and any capabilities the Cfg opted into (Refs/Targets), surfaced generically for validation.
type FlowReferencer ¶
type FlowReferencer interface {
ReferencedFlows() []string
}
FlowReferencer is implemented by node configs that reference child flows by id (module, ...), so the engine can validate references and detect cycles without special-casing the kind.
type Result ¶
type Result struct {
// Outputs are the named values the node produces for downstream nodes.
Outputs value.Map
// Assert is the value the node's declared assertions/outputs run against
// when Provided is true. A provider that asserts over its own Outputs leaves
// it zero — the engine boxes Outputs once, and only when assertions or
// outputs are actually declared. Set it only to assert over something else
// (the assert node targets the whole input context).
Assert value.Value
// Provided is set by nodes that expose a value for the framework's uniform
// assertion/output post-step (request, set_variable, assert, loop). Nodes
// that evaluate their own assertions (poll, sse) or route (branch) or have
// none (delay, module) leave it false, and the engine skips the post-step.
Provided bool
// Assertions is set by self-evaluating nodes (poll, sse) to surface the
// assertion outcomes they evaluated internally — the engine records these on
// the node result, since its post-step (which fills them for provider nodes)
// does not run for self-evaluating nodes.
Assertions assert.Results
// Routed is set by routing nodes (branch): the successor ids execution was
// routed to. The engine skips every other successor (and its subtree). Nil
// for ordinary nodes — all successors run.
Routed []string
}
Result is what a node's Run returns.
type Router ¶
type Router interface {
RouteTargets() []string
}
Router is implemented by node configs that route to specific successors (branch, ...), so the engine can validate that every target has an edge.
type Run ¶
type Run[Cfg hasBase] func(ctx context.Context, cfg Cfg, in value.Value, rt Runtime) (Result, error)
Run is the node-author function: typed cfg + the node's input context (flow inputs and upstream outputs, accessible by path) + runtime deps, result out. Most nodes ignore in — templating already filled their cfg; assert/branch use it to evaluate over inputs without naming them.
type Runtime ¶
type Runtime struct {
HTTP HTTPDoer
Clock Clock
Subflow SubflowRunner
Vars spi.DynamicResolver
}
Runtime is the explicit dependency set handed to every node — genuine external effects only, no assert/extract/error sugar. A node touches only the fields it needs; a test builds a Runtime with just those. Vars resolves {{$dyn}} dynamic variables (spi.DynamicResolver, satisfied by pkg/dynamicvars).
type SubflowRunner ¶
type SubflowRunner interface {
RunSubflow(ctx context.Context, flowID string, in value.Map) (value.Map, error)
RunInline(ctx context.Context, f flow.Flow, in value.Map) (value.Map, error)
}
SubflowRunner runs child flows and returns their outputs. The engine satisfies this; injecting it (rather than importing the engine) keeps the node package free of an import cycle and lets tests fake it. module references a flow by id; loop/poll run an inline body flow.