node

package
v0.49.0 Latest Latest
Warning

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

Go to latest
Published: Aug 27, 2026 License: MIT Imports: 21 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func EvaluateAssertions

func EvaluateAssertions(
	assertions []CompositeAssertion, rc extractors.ResponseContext,
) ([]spi.AssertionResult, error)

EvaluateAssertions evaluates every assertion against rc, assigning each result its Index. Evaluation stops at the first failing or erroring assertion — that one IS recorded — and the corresponding error is returned. The returned slice holds results for all assertions up to and including the first failure (or all of them on success). This is the single assertion-evaluation implementation; every node delegates to it.

func ExtractOutputs

func ExtractOutputs(
	outputs []Output, rc extractors.ResponseContext,
) (map[string]any, error)

ExtractOutputs runs every output extractor against rc, returning the produced name->value map. It fails fast on the first extractor error. This is the single output-extraction implementation; every node delegates to it.

func NewOutputView

func NewOutputView(outputs map[string]map[string]any) spi.OutputView

func NewSkippedResult

func NewSkippedResult(nodeType spi.Kind, base spi.BaseExecutionResult) (spi.AnyResult, bool)

NewSkippedResult builds the skipped result for nodeType via the registry, reporting false when the type is unregistered.

func RegisterNodeKind

func RegisterNodeKind(nodeType spi.Kind, decode Decoder, newSkipped SkippedResultFactory)

RegisterNodeKind registers how to decode a node type and build its skipped result. Call from an init().

func ValidateOutputs

func ValidateOutputs(outputSchema []string, produced map[string]any) error

ValidateOutputs checks that every name in outputSchema was produced. It returns an error naming the first missing output. This is the single output-validation implementation; every node delegates to it.

Types

type AnyNode

type AnyNode interface {
	spi.Node

	// GetAssertions returns the list of assertions to validate during execution.
	// Assertions should be evaluated before extractions.
	GetAssertions() []CompositeAssertion

	// GetOutputs returns the list of extractions to perform on the response/data.
	// Outputs should be evaluated after assertions pass.
	GetOutputs() []Output
}

AnyNode is the full authoring/engine view of a node: the capability-agnostic core (spi.Node) plus the assertion and output accessors, which carry concrete extractor decode/eval behavior and therefore stay in this package.

func UnmarshalNode

func UnmarshalNode(data []byte) (AnyNode, error)

UnmarshalNode unmarshals JSON into the appropriate typed node via the node-kind registry (see registry.go). Adding a node type is one RegisterNodeKind call, not a new case here.

type AssertData

type AssertData struct {
	// Target is the value the assertions/extractors run against. It may carry
	// {{template}} or {{{raw}}} references that resolve to inputs/flow data. When
	// nil/empty the node falls back to asserting over the flow's initial inputs
	// (ctx.FlowInputs).
	//
	// To assert over an UPSTREAM NODE's output, set an explicit target that
	// references it (e.g. "{{{create-user.payload}}}"); InputSchema surfaces that
	// ref so the engine populates ctx.Inputs and the template resolves to the
	// upstream value. An OMITTED target asserts over the flow's initial inputs
	// (ctx.FlowInputs) — not over upstream node outputs.
	Target any `json:"target,omitempty"`
}

AssertData configures an assert node. Target is the value to assert against; when empty the node asserts over the flow's initial inputs.

type AssertExecutionResult

type AssertExecutionResult struct {
	spi.BaseExecutionResult

	DurationMs int64 `json:"duration_ms"`
	// contains filtered or unexported fields
}

AssertExecutionResult stores assert node execution data: the value asserted over and the full set of assertion outcomes captured during evaluation.

func (*AssertExecutionResult) AssertionContext

func (r *AssertExecutionResult) AssertionContext() extractors.ResponseContext

AssertionContext exposes the ResponseContext the engine-level assertion/output pass evaluates against. It satisfies AssertionContextProvider; a nil context (e.g. an error result built before the target was resolved) signals the engine to skip the pass.

type AssertNode

type AssertNode struct {
	BaseNode

	Data AssertData `json:"data"`
	// contains filtered or unexported fields
}

AssertNode validates upstream or derived data with the standard assertion list. Unlike RequestNode it runs assertions over an in-memory value rather than an HTTP response, making it a first-class way to verify data produced by earlier nodes (transforms, modules, branches) in an API-flow test.

To assert over an UPSTREAM NODE's output, set an explicit target referencing it (e.g. "{{{node.output}}}"); the omitted-target default instead asserts over the flow's initial inputs.

func AsAssertNode

func AsAssertNode(node AnyNode) (*AssertNode, bool)

AsAssertNode safely casts an AnyNode to an AssertNode. Returns the AssertNode and true if the cast succeeds, nil and false otherwise.

func (*AssertNode) Execute

func (n *AssertNode) Execute(ctx spi.ExecutionContext) (spi.AnyResult, error)

Execute resolves the target value and returns an AssertExecutionResult that exposes it as a ResponseContext (via AssertionContext). It does NOT run assertions or extract outputs itself: the engine-level pass drives those uniformly for every node that implements AssertionContextProvider (see engine.applyAssertionsAndOutputs), filling AssertionResults, merging outputs, and flipping the result to failed on a miss. Keeping the node thin means a single shared seam owns assertion/output evaluation and retry behavior.

func (*AssertNode) GetData

func (n *AssertNode) GetData() AssertData

GetData returns the node's typed data.

func (*AssertNode) InputSchema

func (n *AssertNode) InputSchema() []string

InputSchema infers inputs from template variables referenced in the target.

func (*AssertNode) OutputSchema

func (n *AssertNode) OutputSchema() []string

OutputSchema returns the names of the declared output extractors.

type AssertionContextProvider

type AssertionContextProvider interface {
	AssertionContext() extractors.ResponseContext
}

AssertionContextProvider is the optional interface a node RESULT implements to expose the ResponseContext its assertions and outputs evaluate against. The engine drives the assertion/output pass uniformly for any result that implements it; results that do not (delay, module) are left untouched.

type BaseNode

type BaseNode struct {
	ID          string               `json:"id"`
	DisplayName string               `json:"display_name"`
	NodeType    spi.Kind             `json:"type"`
	RunWhen     spi.RunWhen          `json:"run_when,omitempty"`
	Assertions  []CompositeAssertion `json:"assertions"`
	Outputs     []Output             `json:"outputs"`
}

BaseNode contains common fields and behavior shared across all node types. All specific node types (RequestNode, DelayNode, AssertionNode, etc.) should embed BaseNode.

func (*BaseNode) GetAssertions

func (bn *BaseNode) GetAssertions() []CompositeAssertion

GetAssertions returns the list of assertions to validate during execution Assertions should be evaluated before extractions.

func (*BaseNode) GetDisplayName

func (bn *BaseNode) GetDisplayName() string

GetDisplayName returns the display name for this node.

func (*BaseNode) GetID

func (bn *BaseNode) GetID() string

GetID returns the unique identifier for this node.

func (*BaseNode) GetOutputs

func (bn *BaseNode) GetOutputs() []Output

GetOutputs returns the list of extractions to perform on the response/data Outputs should be evaluated after assertions pass.

func (*BaseNode) GetRunWhen

func (bn *BaseNode) GetRunWhen() spi.RunWhen

func (*BaseNode) GetType

func (bn *BaseNode) GetType() spi.Kind

GetType returns the type of this node (request, delay, assertion, etc.)

func (*BaseNode) InputSchema

func (bn *BaseNode) InputSchema() []string

InputSchema returns the list of required inputs for this node This method must be overridden by concrete node types to provide computed schemas Format: "nodeId.outputKey" (e.g., "create-user.userId") or plain variable name.

func (*BaseNode) OutputSchema

func (bn *BaseNode) OutputSchema() []string

OutputSchema returns the list of outputs this node produces This method must be overridden by concrete node types to provide computed schemas Examples: []string{"statusCode", "userId", "responseBody"}.

type BranchCase

type BranchCase struct {
	When   CompositeAssertion `json:"when"`
	Target string             `json:"target"`
}

BranchCase pairs a condition with the successor node ID to route to when the condition holds. When evaluates against the resolved branch target value (an in-memory value, not an HTTP response).

type BranchData

type BranchData struct {
	Target  any          `json:"target,omitempty"`
	Cases   []BranchCase `json:"cases"`
	Default string       `json:"default,omitempty"`
}

BranchData configures value-based routing.

  • Target is an optional template; its resolved value is what the case conditions test. When omitted (nil), the branch tests the map of the node's resolved inputs (ctx.Inputs).
  • Cases are evaluated in order; the first whose When passes selects its Target as the routed successor.
  • Default is an optional successor node ID used when no case matches.

type BranchExecutionResult

type BranchExecutionResult struct {
	spi.BaseExecutionResult

	// MatchedTarget is the successor node ID execution was routed to, or "" when
	// no case matched and no default was configured.
	MatchedTarget string `json:"matched_target"`
	// RoutedTargetIDs holds the chosen successor node IDs (one element when a
	// case/default matched, empty otherwise).
	RoutedTargetIDs []string `json:"routed_targets"`
	DurationMs      int64    `json:"duration_ms"`
}

BranchExecutionResult stores value-based routing decision data. It implements spi.RoutingResult so the engine skips the successor subtrees the branch routed away from.

func (*BranchExecutionResult) RoutedTargets

func (r *BranchExecutionResult) RoutedTargets() []string

RoutedTargets implements spi.RoutingResult, returning the successor node IDs this branch routed execution to.

type BranchNode

type BranchNode struct {
	BaseNode

	Data BranchData `json:"data"`
	// contains filtered or unexported fields
}

BranchNode routes execution down exactly one downstream path based on a condition evaluated over upstream data. Unlike spi.RunWhen (which gates on success/failure), a branch performs value-based routing: the chosen successor runs and the others are skipped by the engine.

func AsBranchNode

func AsBranchNode(candidate AnyNode) (*BranchNode, bool)

AsBranchNode safely casts an AnyNode to a BranchNode.

func (*BranchNode) Execute

func (n *BranchNode) Execute(ctx spi.ExecutionContext) (spi.AnyResult, error)

Execute evaluates the branch cases against the resolved target value and selects exactly one successor (or none). It never fails on a "no match" outcome — that is a valid routing decision recorded in the result.

func (*BranchNode) GetData

func (n *BranchNode) GetData() BranchData

GetData returns the branch configuration.

func (*BranchNode) InputSchema

func (n *BranchNode) InputSchema() []string

InputSchema infers inputs from template variables referenced in the optional target template.

func (*BranchNode) OutputSchema

func (n *BranchNode) OutputSchema() []string

OutputSchema exposes the routing decision keys this node produces.

type CompositeAssertion

type CompositeAssertion struct {
	Extractor     extractors.AnyExtractor `json:"-"`             // The actual extractor instance
	ExtractorType string                  `json:"extractorType"` // jsonPath, xmlPath, statusCode, header, body
	OperatorType  operators.OperatorType  `json:"operatorType"`  // equals, contains, greaterThan, etc.
	ExpectedValue any                     `json:"-"`             // Resolved expected value (operator_data.value)
}

CompositeAssertion combines an extractor with an operator for validation.

func (*CompositeAssertion) Evaluate

Evaluate runs the assertion against the response and returns a full result record. Index is left zero for the caller to assign. Passed is true only when the extractor succeeds and the operator holds; Error is set (and Passed false, Actual possibly nil) when the extractor or operator errors. This is the single evaluation entry point — it both decides pass/fail and captures what was compared, so callers never re-derive the outcome.

func (*CompositeAssertion) UnmarshalJSON

func (ca *CompositeAssertion) UnmarshalJSON(data []byte) error

UnmarshalJSON implements custom unmarshaling for CompositeAssertion.

type Decoder

type Decoder func([]byte) (AnyNode, error)

Decoder builds a typed node from its raw JSON.

type DelayData

type DelayData struct {
	Duration int `json:"duration"` // Duration in milliseconds
}

type DelayExecutionResult

type DelayExecutionResult struct {
	spi.BaseExecutionResult

	DelayMs    int64     `json:"delay_ms"`
	DelayUntil time.Time `json:"delay_until"`
}

DelayExecutionResult stores delay node execution data.

type DelayNode

type DelayNode struct {
	BaseNode

	Data DelayData `json:"data"`
}

DelayNode is a typed node for delays.

func NewDelay

func NewDelay(id string, durationMs int) *DelayNode

NewDelay starts a delay node that waits durationMs milliseconds.

func (*DelayNode) Always

func (n *DelayNode) Always() *DelayNode

Always marks the delay to run in the cleanup phase.

func (*DelayNode) DisplayName

func (n *DelayNode) DisplayName(name string) *DelayNode

DisplayName sets the delay node's name.

func (*DelayNode) Execute

func (n *DelayNode) Execute(ctx spi.ExecutionContext) (spi.AnyResult, error)

Execute sleeps for the specified duration and returns a DelayExecutionResult.

func (*DelayNode) GetData

func (n *DelayNode) GetData() DelayData

func (*DelayNode) InputSchema

func (n *DelayNode) InputSchema() []string

InputSchema returns empty as DelayNode doesn't need inputs.

func (*DelayNode) OutputSchema

func (n *DelayNode) OutputSchema() []string

OutputSchema returns empty as DelayNode doesn't produce outputs.

type LoopData

type LoopData struct {
	// Items is a template (or literal) that resolves to a []any. Each element is
	// iterated over and the body sub-flow is run once per element.
	Items any `json:"items"`
	// Body is an inline flow definition ({"nodes":[...],"edges":[...]}) executed
	// once per iteration via the shared spi.ModuleExecutor.
	Body json.RawMessage `json:"body"`
	// ItemVar is the FlowInputs key the current item is injected under (default "item").
	ItemVar string `json:"item_var"`
	// IndexVar is the FlowInputs key the current zero-based index is injected under
	// (default "index").
	IndexVar string `json:"index_var"`
	// MaxIterations, when > 0, caps how many items are iterated as a safety bound.
	MaxIterations int `json:"max_iterations"`
	// ContinueOnError keeps the loop running when an iteration fails, recording the
	// error in that iteration's result instead of failing the whole node.
	ContinueOnError bool `json:"continue_on_error"`
}

LoopData configures a foreach loop node.

type LoopExecutionResult

type LoopExecutionResult struct {
	spi.BaseExecutionResult

	// Iterations is the number of body executions that were attempted
	// (after applying any max_iterations cap).
	Iterations int   `json:"iterations"`
	DurationMs int64 `json:"duration_ms"`
	// contains filtered or unexported fields
}

LoopExecutionResult stores foreach loop node execution data.

func (*LoopExecutionResult) AssertionContext

func (r *LoopExecutionResult) AssertionContext() extractors.ResponseContext

AssertionContext exposes the ResponseContext the engine-level assertion/output pass evaluates against — the loop's aggregate outputs ({results, count}). It satisfies AssertionContextProvider; a nil context (e.g. an error result built before the loop completed) signals the engine to skip the pass.

type LoopNode

type LoopNode struct {
	BaseNode

	Data LoopData `json:"data"`
}

LoopNode iterates a body sub-flow once per item in a resolved array (foreach), injecting the per-iteration item and index into the child flow inputs and collecting each iteration's final outputs into an array.

func AsLoopNode

func AsLoopNode(candidate AnyNode) (*LoopNode, bool)

AsLoopNode safely casts an AnyNode to a LoopNode.

func (*LoopNode) Execute

func (n *LoopNode) Execute(ctx spi.ExecutionContext) (spi.AnyResult, error)

Execute resolves the items array and runs the body sub-flow once per item, injecting item/index into the child flow inputs and aggregating per-iteration final outputs into a results array.

func (*LoopNode) GetData

func (n *LoopNode) GetData() LoopData

func (*LoopNode) GetOutputs

func (n *LoopNode) GetOutputs() []Output

GetOutputs returns the loop's default aggregate extractors (results, count) followed by any user-declared outputs. A user-declared output with the same name overrides the default, so the loop's intrinsic outputs stay referenceable while remaining customizable.

func (*LoopNode) InputSchema

func (n *LoopNode) InputSchema() []string

InputSchema infers inputs from the items template only. Body references are validated inside the child flow parse, not by the parent loop node.

func (*LoopNode) OutputSchema

func (n *LoopNode) OutputSchema() []string

OutputSchema lists every output the loop node produces: its intrinsic aggregates (results, count) plus any user-declared outputs.

type ModuleData

type ModuleData struct {
	FlowID         string            `json:"flow_id"`
	InputBindings  map[string]any    `json:"input_bindings,omitempty"`
	OutputBindings map[string]string `json:"output_bindings,omitempty"`
}

type ModuleExecutionResult

type ModuleExecutionResult struct {
	spi.BaseExecutionResult

	FlowID            string         `json:"flow_id"`
	ChildFinalOutputs map[string]any `json:"child_final_outputs,omitempty"`
	DurationMs        int64          `json:"duration_ms"`
}

ModuleExecutionResult stores nested module execution data.

type ModuleNode

type ModuleNode struct {
	BaseNode

	Data ModuleData `json:"data"`
}

ModuleNode executes another flow as a reusable nested module.

func AsModuleNode

func AsModuleNode(candidate AnyNode) (*ModuleNode, bool)

AsModuleNode safely casts an AnyNode to a ModuleNode.

func (*ModuleNode) DisplayName

func (n *ModuleNode) DisplayName(name string) *ModuleNode

DisplayName sets the module node's name.

func (*ModuleNode) Execute

func (n *ModuleNode) Execute(ctx spi.ExecutionContext) (spi.AnyResult, error)

func (*ModuleNode) GetData

func (n *ModuleNode) GetData() ModuleData

func (*ModuleNode) InputBinding

func (n *ModuleNode) InputBinding(key string, value any) *ModuleNode

InputBinding binds a child-flow input to a value/template.

func (*ModuleNode) InputSchema

func (n *ModuleNode) InputSchema() []string

InputSchema infers inputs from binding templates.

func (*ModuleNode) OutputBinding

func (n *ModuleNode) OutputBinding(parentName, childKey string) *ModuleNode

OutputBinding maps a child final output key to a parent-visible output name.

func (*ModuleNode) OutputSchema

func (n *ModuleNode) OutputSchema() []string

OutputSchema exposes the parent-visible outputs exported by the module node.

type Output

type Output struct {
	Name      string                  `json:"name"`
	Extractor extractors.AnyExtractor `json:"extractor"`
}

Output represents a named output with an associated extractor.

func (*Output) UnmarshalJSON

func (o *Output) UnmarshalJSON(data []byte) error

UnmarshalJSON implements custom unmarshaling for Output This allows us to properly unmarshal the Extractor field from JSON.

type PollData

type PollData struct {
	// Body is an inline flow definition executed once per attempt. The exit
	// condition (the node's assertions) is evaluated against its FinalOutputs.
	Body json.RawMessage `json:"body"`
	// MaxAttempts is the maximum number of body executions. Defaults to
	// defaultPollMaxAttempts when <= 0.
	MaxAttempts int `json:"max_attempts"`
	// IntervalMs is the wait between attempts, in milliseconds. Defaults to
	// defaultPollIntervalMs when <= 0.
	IntervalMs int `json:"interval_ms"`
	// TimeoutMs, when > 0, caps the overall wall-clock budget for the whole poll
	// (layered on top of the execution context deadline).
	TimeoutMs int `json:"timeout_ms"`
}

PollData configures a poll-until node. The body sub-flow is re-run on an interval until the node's exit-condition assertions (BaseNode.Assertions) all pass against an attempt's child final outputs, or the attempt/deadline budget is exhausted.

type PollExecutionResult

type PollExecutionResult struct {
	spi.BaseExecutionResult

	// Attempts is the number of body executions performed (the attempt on which
	// the poll succeeded, or the total attempts made before giving up).
	//
	// The exit-condition evaluation from the final attempt (the passing attempt on
	// success, or the last attempt on failure) is recorded in the promoted
	// BaseExecutionResult.AssertionResults field.
	Attempts   int   `json:"attempts"`
	DurationMs int64 `json:"duration_ms"`
}

PollExecutionResult stores poll-until node execution data. The poll node re-runs an inline body sub-flow on an interval until all of its exit-condition assertions pass on a single attempt, or it exhausts its attempt/deadline budget.

type PollNode

type PollNode struct {
	BaseNode

	Data PollData `json:"data"`
}

PollNode re-runs an inline body flow on an interval until an exit-condition assertion holds — the canonical async-API pattern (kick off a job, then poll "status == done" before continuing).

func AsPollNode

func AsPollNode(node AnyNode) (*PollNode, bool)

AsPollNode safely casts an AnyNode to a PollNode. Returns the PollNode and true if the cast succeeds, nil and false otherwise.

func MustAsPollNode

func MustAsPollNode(node AnyNode) *PollNode

MustAsPollNode casts an AnyNode to a PollNode, panicking if it fails. Use this when you're certain the node is a PollNode.

func (*PollNode) Execute

func (n *PollNode) Execute(ctx spi.ExecutionContext) (spi.AnyResult, error)

Execute runs the body sub-flow up to max_attempts times, evaluating the exit-condition assertions against each attempt's child final outputs. It succeeds on the first attempt where all assertions pass; otherwise it waits interval_ms and retries until the attempt budget, timeout, or context deadline is exhausted.

func (*PollNode) GetData

func (n *PollNode) GetData() PollData

func (*PollNode) InputSchema

func (n *PollNode) InputSchema() []string

InputSchema returns empty: the poll node feeds the parent flow inputs into the body sub-flow rather than declaring named upstream dependencies.

func (*PollNode) OutputSchema

func (n *PollNode) OutputSchema() []string

OutputSchema exposes the keys the poll node produces on success.

type RequestData

type RequestData struct {
	Method      string            `json:"method"`
	URL         string            `json:"url"`
	Headers     map[string]string `json:"headers"`
	QueryParams map[string]any    `json:"queryParams"`
	Body        any               `json:"body"`
	Timeout     int               `json:"timeout"`
}

type RequestExecutionResult

type RequestExecutionResult struct {
	spi.BaseExecutionResult

	// HTTP Request fields
	RequestMethod  string            `json:"request_method"`
	RequestURL     string            `json:"request_url"`
	RequestHeaders map[string]string `json:"request_headers"`
	RequestBody    any               `json:"request_body,omitempty"`

	// HTTP Response fields
	ResponseStatusCode int                 `json:"response_status_code"`
	ResponseHeaders    map[string][]string `json:"response_headers"`
	ResponseBody       []byte              `json:"response_body,omitempty"`
	ResponseBodyParsed any                 `json:"response_body_parsed,omitempty"`

	// Timing
	DurationMs int64 `json:"duration_ms"`
	// contains filtered or unexported fields
}

RequestExecutionResult stores HTTP request node execution data.

func (*RequestExecutionResult) AssertionContext

func (r *RequestExecutionResult) AssertionContext() extractors.ResponseContext

AssertionContext exposes the ResponseContext the engine-level assertion/output pass evaluates against. It satisfies AssertionContextProvider; a nil context (e.g. an error result built before the HTTP exchange completed) signals the engine to skip the pass.

type RequestNode

type RequestNode struct {
	BaseNode

	Data RequestData `json:"data"`
	// contains filtered or unexported fields
}

RequestNode is a typed node for HTTP requests.

func AsRequestNode

func AsRequestNode(node AnyNode) (*RequestNode, bool)

AsRequestNode safely casts an AnyNode to a RequestNode Returns the RequestNode and true if the cast succeeds, nil and false otherwise.

func NewRequest

func NewRequest(id string) *RequestNode

NewRequest starts a request node with the given id.

func (*RequestNode) Always

func (n *RequestNode) Always() *RequestNode

Always marks the node to run in the cleanup phase even after a main-phase failure.

func (*RequestNode) Assert

func (n *RequestNode) Assert(assertion CompositeAssertion) *RequestNode

Assert appends a validation assertion.

func (*RequestNode) Body

func (n *RequestNode) Body(body any) *RequestNode

Body sets the request body (any JSON-serializable value, with {{var}} support).

func (*RequestNode) DELETE

func (n *RequestNode) DELETE(url string) *RequestNode

DELETE is a shorthand for Method("DELETE", url).

func (*RequestNode) DisplayName

func (n *RequestNode) DisplayName(name string) *RequestNode

DisplayName sets the human-readable name.

func (*RequestNode) Execute

func (n *RequestNode) Execute(ctx spi.ExecutionContext) (spi.AnyResult, error)

func (*RequestNode) GET

func (n *RequestNode) GET(url string) *RequestNode

GET is a shorthand for Method("GET", url).

func (*RequestNode) GetAssertions

func (n *RequestNode) GetAssertions() []CompositeAssertion

func (*RequestNode) GetData

func (n *RequestNode) GetData() RequestData

func (*RequestNode) GetOutputs

func (n *RequestNode) GetOutputs() []Output

func (*RequestNode) Header

func (n *RequestNode) Header(key, value string) *RequestNode

Header adds a request header (supports {{var}} templates).

func (*RequestNode) InputSchema

func (n *RequestNode) InputSchema() []string

InputSchema infers inputs from template variables in URL, Headers, QueryParams, and Body.

func (*RequestNode) Method

func (n *RequestNode) Method(method, url string) *RequestNode

Method sets the HTTP method + URL.

func (*RequestNode) Output

func (n *RequestNode) Output(output Output) *RequestNode

Output appends an extracted output (referenced downstream as "id.name").

func (*RequestNode) OutputSchema

func (n *RequestNode) OutputSchema() []string

OutputSchema infers outputs from the Outputs list.

func (*RequestNode) PATCH

func (n *RequestNode) PATCH(url string) *RequestNode

PATCH is a shorthand for Method("PATCH", url).

func (*RequestNode) POST

func (n *RequestNode) POST(url string) *RequestNode

POST is a shorthand for Method("POST", url).

func (*RequestNode) PUT

func (n *RequestNode) PUT(url string) *RequestNode

PUT is a shorthand for Method("PUT", url).

func (*RequestNode) TimeoutMs

func (n *RequestNode) TimeoutMs(ms int) *RequestNode

TimeoutMs sets the per-request timeout in milliseconds.

type SchemaInference

type SchemaInference struct{}

SchemaInference provides utilities to infer input and output schemas from node configurations.

func (*SchemaInference) ExtractTemplateVariables

func (si *SchemaInference) ExtractTemplateVariables(data any) []string

ExtractTemplateVariables extracts all {{variable}} references from a string or nested structure.

func (*SchemaInference) InferRequestNodeInputSchema

func (si *SchemaInference) InferRequestNodeInputSchema(data RequestData) []string

InferRequestNodeInputSchema infers input schema from RequestNode data.

func (*SchemaInference) InferRequestNodeOutputSchema

func (si *SchemaInference) InferRequestNodeOutputSchema(outputs []Output) []string

InferRequestNodeOutputSchema infers output schema from Outputs.

type SetVariableData

type SetVariableData struct {
	Variables map[string]any `json:"variables"`
}

SetVariableData configures a set-variable node. Each entry maps an output name to a template value: a string with {{a.b}} / {{x}} references, a number/bool, or a nested object/array that may contain {{{raw}}} structured references.

type SetVariableExecutionResult

type SetVariableExecutionResult struct {
	spi.BaseExecutionResult

	DurationMs int64 `json:"duration_ms"`
}

SetVariableExecutionResult stores set-variable node execution data. The computed named values are exposed both as the node Outputs (via the embedded base) and as the engine sees them; DurationMs records resolution time.

func (*SetVariableExecutionResult) AssertionContext

AssertionContext exposes the computed variables map (the node Outputs) as the ResponseContext the engine-level assertion/output pass evaluates against. This gives set-variable nodes free assertions over their resolved variables, satisfying AssertionContextProvider. A nil Outputs map (e.g. an error result) signals the engine to skip the pass.

type SetVariableNode

type SetVariableNode struct {
	BaseNode

	Data SetVariableData `json:"data"`
}

SetVariableNode computes named outputs from upstream node outputs and flow inputs via template resolution, without performing any HTTP call. It is used to assemble payloads, derive headers, and reshape values between nodes.

func AsSetVariableNode

func AsSetVariableNode(candidate AnyNode) (*SetVariableNode, bool)

AsSetVariableNode safely casts an AnyNode to a SetVariableNode. Returns the SetVariableNode and true if the cast succeeds, nil and false otherwise.

func (*SetVariableNode) Execute

Execute resolves every configured variable template against the node inputs and dynamic variables, returning the resolved values as the node outputs. No HTTP call or external side effect is performed.

func (*SetVariableNode) GetData

func (n *SetVariableNode) GetData() SetVariableData

func (*SetVariableNode) InputSchema

func (n *SetVariableNode) InputSchema() []string

InputSchema infers required inputs from the template variables referenced in the configured values, mirroring how ModuleNode derives inputs from bindings.

func (*SetVariableNode) OutputSchema

func (n *SetVariableNode) OutputSchema() []string

OutputSchema exposes the names of the variables this node produces, sorted.

type SkippedResultFactory

type SkippedResultFactory func(base spi.BaseExecutionResult) spi.AnyResult

SkippedResultFactory builds the kind's skipped execution result from a shared base, so the engine doesn't switch on node type to construct skips.

type SseData

type SseData struct {
	// URL is the event-stream endpoint (templated).
	URL string `json:"url"`
	// Method defaults to GET when empty.
	Method string `json:"method"`
	// Headers are sent on the request (values templated).
	Headers map[string]string `json:"headers"`
	// MaxEvents stops the stream after N events (default defaultSseMaxEvents).
	MaxEvents int `json:"max_events"`
	// TimeoutMs is the overall deadline in milliseconds (default defaultSseTimeoutMs).
	TimeoutMs int `json:"timeout_ms"`
	// CompletionEvent, when set, stops the stream as soon as an event whose
	// "event:" name OR raw data equals this value is dispatched.
	CompletionEvent string `json:"completion_event"`
	// StopOnAssertionFailure stops (and fails) the node on the first failing
	// per-event assertion. Defaults to true.
	StopOnAssertionFailure *bool `json:"stop_on_assertion_failure"`
}

SseData configures a connection to a text/event-stream endpoint that is consumed event-by-event over time.

type SseExecutionResult

type SseExecutionResult struct {
	spi.BaseExecutionResult

	// RequestMethod and RequestURL capture the resolved connection details.
	RequestMethod string `json:"request_method"`
	RequestURL    string `json:"request_url"`

	// Events holds every dispatched event's parsed data (JSON when the data was
	// valid JSON, otherwise the raw string), in arrival order.
	Events []any `json:"events"`
	// EventCount is len(Events).
	EventCount int `json:"event_count"`

	// StopReason records why streaming stopped (max_events, completion_event,
	// timeout, eof, assertion_failure).
	StopReason string `json:"stop_reason,omitempty"`

	// Timing
	DurationMs int64 `json:"duration_ms"`
}

SseExecutionResult stores SSE (Server-Sent Events) node execution data.

type SseNode

type SseNode struct {
	BaseNode

	Data SseData `json:"data"`
	// contains filtered or unexported fields
}

SseNode connects to a Server-Sent Events endpoint, consumes events over time, and runs the node's assertions against each event's parsed data with a cross-event accumulator. Unlike the buffered single-shot request node, it streams: events are processed as they arrive and the connection is closed as soon as a stop condition (max_events, completion_event, timeout, assertion failure, or EOF) is met.

func AsSseNode

func AsSseNode(node AnyNode) (*SseNode, bool)

AsSseNode safely casts an AnyNode to an SseNode. Returns the SseNode and true if the cast succeeds, nil and false otherwise.

func (*SseNode) Execute

func (n *SseNode) Execute(ctx spi.ExecutionContext) (spi.AnyResult, error)

Execute connects to the SSE endpoint and consumes events until a stop condition is met. On any failure it returns a populated result plus the error so the engine records a failed node.

func (*SseNode) GetData

func (n *SseNode) GetData() SseData

func (*SseNode) InputSchema

func (n *SseNode) InputSchema() []string

InputSchema infers inputs from template variables in URL and Headers.

func (*SseNode) OutputSchema

func (n *SseNode) OutputSchema() []string

OutputSchema returns the keys this node always produces.

type TemplateResolver

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

TemplateResolver handles resolution of {{variableName}} templates in strings and objects.

func NewTemplateResolver

func NewTemplateResolver(variables map[string]any) *TemplateResolver

NewTemplateResolver creates a new template resolver with the given variables.

func NewTemplateResolverWithDynamics

func NewTemplateResolverWithDynamics(
	variables map[string]any, dynamic spi.DynamicResolver,
) *TemplateResolver

NewTemplateResolverWithDynamics creates a resolver that also resolves {{$name}} dynamic variables via the given resolver (may be nil).

func (*TemplateResolver) Resolve

func (tr *TemplateResolver) Resolve(value any) (any, error)

Resolve recursively resolves all {{variableName}} templates in the given value Supports strings, maps, slices, and nested structures.

Jump to

Keyboard shortcuts

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