Class: Inquirex::DSL::FlowBuilder

Inherits:
Object
  • Object
show all
Includes:
RuleHelpers
Defined in:
lib/inquirex/dsl/flow_builder.rb

Overview

Builds a Definition from the declarative DSL block used in Inquirex.define. Provides start, meta, and all verb methods (ask, say, header, btw, warning, confirm).

Constant Summary collapse

THEME_KEY_ALIASES =

Maps snake_case theme keys (idiomatic in Ruby) to the camelCase names the JS widget (inquirex-js ThemeOverrides) expects on the wire.

{
  on_brand:    :onBrand,
  text_muted:  :textMuted,
  header_font: :headerFont
}.freeze

Instance Method Summary collapse

Methods included from RuleHelpers

#all, #any, #contains, #equals, #greater_than, #less_than, #not_empty

Constructor Details

#initialize(id: nil, version: "1.0.0") ⇒ FlowBuilder

Returns a new instance of FlowBuilder.

Parameters:

  • id (String, nil) (defaults to: nil)

    optional flow identifier

  • version (String) (defaults to: "1.0.0")

    semver



12
13
14
15
16
17
18
19
20
21
# File 'lib/inquirex/dsl/flow_builder.rb', line 12

def initialize(id: nil, version: "1.0.0")
  @flow_id = id
  @flow_version = version
  @start_step_id = nil
  @nodes = {}
  @meta = {}
  @accumulators = {}
  @actions = []
  @allowed_domains = []
end

Instance Method Details

#accumulator(name, type: :decimal, default: 0) ⇒ Object

Declares a named running total the flow accumulates into as answers come in. The :price accumulator is the common lead-qualification use case; others (e.g. :complexity, :credit_score) work identically.

Parameters:

  • name (Symbol)

    e.g. :price

  • type (Symbol) (defaults to: :decimal)

    one of Node::TYPES (default :currency-ish: :decimal)

  • default (Numeric) (defaults to: 0)

    starting value (default: 0)



40
41
42
43
# File 'lib/inquirex/dsl/flow_builder.rb', line 40

def accumulator(name, type: :decimal, default: 0)
  sym = name.to_sym
  @accumulators[sym] = Accumulator.new(name: sym, type:, default:)
end

#action(id, **opts) { ... } ⇒ Object

Declares a named post-completion action: effects (send_email, run, ...) executed server-side after the flow finishes, with the collected answers. Runs in declaration order; gate with a serializable rule via the if: option.

Examples:

Email the collected answers when business income was selected

action :notify_sales, if: Rules::Contains.new(:income_types, "Business") do
  send_email to: "sales@example.com",
             subject: "New lead: {{name}}",
             html: "{{answers_summary}}"
end

Parameters:

  • id (Symbol)

    action identifier

  • opts (Hash)

    only if: is recognized — a Rules::Base gate

Yields:

  • block evaluated in ActionBuilder (send_email, run, ...)

Raises:



134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/inquirex/dsl/flow_builder.rb', line 134

def action(id, **opts, &block)
  rule = opts.delete(:if)
  raise Errors::DefinitionError, "Unknown action options: #{opts.keys.inspect}" unless opts.empty?

  sym = id.to_sym
  if @actions.any? { |a| a.id == sym }
    raise Errors::DefinitionError, "Duplicate action id: #{sym.inspect}"
  end

  builder = ActionBuilder.new
  builder.instance_eval(&block) if block
  @actions << builder.build(sym, rule:)
end

#allowed_domains(*domains) ⇒ Object

Declares the domains outbound effects (webhook) may send answers to. Conventionally the first declaration in a definition, so the flow's egress surface is auditable at a glance. "example.com" matches that host exactly; "*.example.com" matches its subdomains.

Parameters:

  • domains (Array<String>)


29
30
31
# File 'lib/inquirex/dsl/flow_builder.rb', line 29

def allowed_domains(*domains)
  @allowed_domains.concat(domains.flatten)
end

#ask(id) { ... } ⇒ Object

Defines a question step that collects typed input from the user.

Parameters:

  • id (Symbol)

    step id

Yields:

  • block evaluated in StepBuilder (type, question, options, transition, etc.)



80
81
82
# File 'lib/inquirex/dsl/flow_builder.rb', line 80

def ask(id, &)
  add_step(id, :ask, &)
end

#btw(id) ⇒ Object

Defines an admonition or sidebar note step (no input collected).

Parameters:

  • id (Symbol)

    step id



101
102
103
# File 'lib/inquirex/dsl/flow_builder.rb', line 101

def btw(id, &)
  add_step(id, :btw, &)
end

#buildDefinition

Produces the frozen Definition.

Returns:

Raises:



152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/inquirex/dsl/flow_builder.rb', line 152

def build
  raise Errors::DefinitionError, "No start step defined" if @start_step_id.nil?
  raise Errors::DefinitionError, "No steps defined" if @nodes.empty?

  Definition.new(
    start_step_id:   @start_step_id,
    nodes:           @nodes,
    id:              @flow_id,
    version:         @flow_version,
    meta:            @meta,
    accumulators:    @accumulators,
    actions:         @actions,
    allowed_domains: @allowed_domains
  )
end

#confirm(id) ⇒ Object

Defines a yes/no confirmation gate (collects a boolean answer).

Parameters:

  • id (Symbol)

    step id



115
116
117
# File 'lib/inquirex/dsl/flow_builder.rb', line 115

def confirm(id, &)
  add_step(id, :confirm, &)
end

#header(id) ⇒ Object

Defines a section heading step (no input collected).

Parameters:

  • id (Symbol)

    step id



94
95
96
# File 'lib/inquirex/dsl/flow_builder.rb', line 94

def header(id, &)
  add_step(id, :header, &)
end

#meta(title: nil, subtitle: nil, brand: nil, theme: nil) ⇒ Object

Sets frontend metadata: title, subtitle, brand, and theme.

Examples:

meta title: "Tax Intake",
  subtitle: "Let's get started",
  brand: { name: "Agentica", logo: "https://cdn.example.com/logo.png" },
  theme: { brand: "#2563eb", radius: "18px", font: "Inter, system-ui" }

Parameters:

  • title (String, nil) (defaults to: nil)
  • subtitle (String, nil) (defaults to: nil)
  • brand (Hash, nil) (defaults to: nil)

    identity — { name: "Acme", logo: "https://..." }. Colors and fonts belong in theme:, not here.

  • theme (Hash, nil) (defaults to: nil)

    visual overrides consumed by the JS widget. Every key maps 1:1 to a CSS custom property on the widget's shadow root. Supported keys: :brand, :on_brand (or :onBrand), :background, :surface, :text, :text_muted (or :textMuted), :border, :radius, :font, :header_font (or :headerFont).



69
70
71
72
73
74
# File 'lib/inquirex/dsl/flow_builder.rb', line 69

def meta(title: nil, subtitle: nil, brand: nil, theme: nil)
  @meta[:title] = title if title
  @meta[:subtitle] = subtitle if subtitle
  @meta[:brand] = brand if brand
  @meta[:theme] = normalize_theme(theme) if theme
end

#say(id) ⇒ Object

Defines an informational message step (no input collected).

Parameters:

  • id (Symbol)

    step id



87
88
89
# File 'lib/inquirex/dsl/flow_builder.rb', line 87

def say(id, &)
  add_step(id, :say, &)
end

#start(step_id) ⇒ Object

Sets the entry step id for the flow.

Parameters:

  • step_id (Symbol)


48
49
50
# File 'lib/inquirex/dsl/flow_builder.rb', line 48

def start(step_id)
  @start_step_id = step_id
end

#warning(id) ⇒ Object

Defines an important alert step (no input collected).

Parameters:

  • id (Symbol)

    step id



108
109
110
# File 'lib/inquirex/dsl/flow_builder.rb', line 108

def warning(id, &)
  add_step(id, :warning, &)
end