FlowRunner.Spec.Block behaviour (flow_runner v6.15.1)

Copy Markdown

A Block is a unit of execution within a flow. It may wait for user input and provide content that should be rendered to the user.

Summary

Callbacks

Evaluate the block we have transitioned to and return updated container, flow, block and context

On leaving a block give the block an opportunity to evaluate the inputs received. This allows the block to fulfill tasks such as validation.

Load the raw config received from the original JSON, validate it and return a map with atom keys with the correct configuration

Types

t()

@type t() :: %FlowRunner.Spec.Block{
  config: map(),
  exits: [FlowRunner.Spec.Exit.t()],
  label: String.t(),
  name: String.t(),
  semantic_label: String.t(),
  tags: [String.t()],
  type: String.t(),
  ui_metadata: map(),
  uuid: String.t(),
  vendor_metadata: map()
}

Callbacks

evaluate_incoming(t, t, t, t)

Evaluate the block we have transitioned to and return updated container, flow, block and context

evaluate_outgoing(t, t, t, t, user_input)

@callback evaluate_outgoing(
  FlowRunner.Spec.Container.t(),
  FlowRunner.Spec.Flow.t(),
  t(),
  FlowRunner.Context.t(),
  user_input :: any()
) ::
  {:ok, user_input :: any()}
  | {:ok, user_input :: any(), opts :: Keyword.t()}
  | {:invalid, reason :: String.t()}

On leaving a block give the block an opportunity to evaluate the inputs received. This allows the block to fulfill tasks such as validation.

Return one of:

  • {:ok, user_input} — default. The validated input is stored in context.vars[block.name] (and context.vars["block"]["value"]) and waiting_for_user_input is cleared. Appropriate for question-shaped blocks whose output is the user's reply.

  • {:ok, user_input, opts} — same as above plus a keyword list of options. Supported options:

    • preserve_vars: true — do NOT overwrite context.vars[block.name] with the user input, but still clear waiting_for_user_input. Use this for blocks that set their own structured vars before pausing and must preserve that structure across the resume so downstream exits can read it.
  • {:invalid, reason} — the flow runner will exit through the block's default response.

validate_config!(map)

@callback validate_config!(map()) :: map()

Load the raw config received from the original JSON, validate it and return a map with atom keys with the correct configuration

Functions

cast!(blocks_module, map)

@spec cast!(module(), map()) :: map()

Cast the received fields to their internal representation

evaluate_default_exit(block)

@spec evaluate_default_exit(t()) ::
  {:error, String.t()} | {:ok, FlowRunner.Spec.Exit.t()}

evaluate_exits(block, context)

@spec evaluate_exits(t(), FlowRunner.Context.t()) ::
  {:ok, FlowRunner.Spec.Exit.t()} | {:error, String.t()}

evaluate_incoming(container, flow, block, context)

evaluate_outgoing(container, flow, block, context, user_input)

@spec evaluate_outgoing(
  FlowRunner.Spec.Container.t(),
  FlowRunner.Spec.Flow.t(),
  t(),
  FlowRunner.Context.t(),
  user_input :: any()
) :: {:ok, FlowRunner.Context.t(), t()} | {:invalid, reason :: String.t()}

evaluate_user_input(block, context, user_input)

@spec evaluate_user_input(t(), FlowRunner.Context.t(), iodata()) ::
  {:ok, FlowRunner.Context.t()} | {:error, String.t()}

evaluate_user_input(block, context, user_input, opts)

@spec evaluate_user_input(t(), FlowRunner.Context.t(), iodata(), Keyword.t()) ::
  {:ok, FlowRunner.Context.t()} | {:error, String.t()}

fetch_default_block(block, flow, context)

@spec fetch_default_block(t(), FlowRunner.Spec.Flow.t(), FlowRunner.Context.t()) ::
  {:error, String.t()} | {:ok, FlowRunner.Context.t(), t() | nil}

fetch_next_block(block, flow, context)

@spec fetch_next_block(t(), FlowRunner.Spec.Flow.t(), FlowRunner.Context.t()) ::
  {:error, String.t()} | {:ok, FlowRunner.Context.t(), t()}

get_block(blocks_module, type)

load!(blocks_module, list)

@spec load!(module(), map()) :: t()
@spec load!(module(), [map()]) :: [t()]

Load the map or list of maps into Elixir.FlowRunner.Spec.Block structs.

load_config_for_set_contact_property!(arg1)

load_config_for_type!(blocks_module, type, config)

valid?(self)

validate!(blocks_module, impl)

@spec validate!(blocks_module :: module(), t()) :: t()

Validate a Elixir.FlowRunner.Spec.Block struct using Vex.validate