Module: Browserctl::Commands::Flow

Extended by:
CliOutput
Defined in:
lib/browserctl/commands/flow.rb

Constant Summary collapse

USAGE =
"Usage: browserctl flow <run|list|describe> [args]"

Constants included from CliOutput

CliOutput::AUTH_REQUIRED_EXIT_CODE

Class Method Summary collapse

Methods included from CliOutput

exit_code_for, print_result, structured_error_line

Class Method Details

.format_params(flow) ⇒ Object



108
109
110
111
112
113
114
# File 'lib/browserctl/commands/flow.rb', line 108

def self.format_params(flow)
  flow.param_defs.transform_values do |p|
    entry = { required: p.required, secret: p.secret, default: p.default }
    entry[:secret_ref] = p.secret_ref if p.secret_ref
    entry
  end
end

.load_params_file(path) ⇒ Object



94
95
96
97
98
# File 'lib/browserctl/commands/flow.rb', line 94

def self.load_params_file(path)
  Browserctl::Runner.load_params_file(path)
rescue StandardError => e
  abort "Error loading params file: #{e.message}"
end

.pair_args(args) ⇒ Object



100
101
102
103
104
105
106
# File 'lib/browserctl/commands/flow.rb', line 100

def self.pair_args(args)
  out = {}
  args.each_slice(2) do |flag, val|
    out[flag.sub(/\A--/, "").to_sym] = val
  end
  out
end

.parse_run_args(args) ⇒ Object



77
78
79
80
81
82
83
# File 'lib/browserctl/commands/flow.rb', line 77

def self.parse_run_args(args)
  page_name = take_option(args, "--page")
  params_path = take_option(args, "--params")
  file_params = params_path ? load_params_file(params_path) : {}
  cli_params = pair_args(args)
  [page_name, file_params.merge(cli_params)]
end

.resolve(name_or_path) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/browserctl/commands/flow.rb', line 64

def self.resolve(name_or_path)
  if File.exist?(name_or_path)
    before = Browserctl.flow_registry_snapshot.keys
    load File.expand_path(name_or_path)
    new_name = (Browserctl.flow_registry_snapshot.keys - before).first
    new_name ||= File.basename(name_or_path, ".rb")
    flow = Browserctl.lookup_flow(new_name)
  else
    flow = Browserctl::FlowRegistry.resolve(name_or_path)
  end
  flow or abort "flow '#{name_or_path}' not found"
end

.run(client, args) ⇒ Object



16
17
18
19
20
21
22
23
24
# File 'lib/browserctl/commands/flow.rb', line 16

def self.run(client, args)
  sub = args.shift or abort USAGE
  case sub
  when "run"      then run_flow(client, args)
  when "list"     then run_list
  when "describe" then run_describe(args)
  else abort "unknown flow subcommand '#{sub}'\n#{USAGE}"
  end
end

.run_describe(args) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/browserctl/commands/flow.rb', line 47

def self.run_describe(args)
  name = args.shift or abort "usage: browserctl flow describe <name>"
  flow = resolve(name)
  payload = {
    name: flow.name,
    desc: flow.description,
    version: flow.version_string,
    requires_browserctl: flow.min_browserctl_version,
    params: format_params(flow),
    preconditions: flow.preconditions.map(&:label),
    steps: flow.steps.map(&:label),
    postconditions: flow.postconditions.map(&:label),
    produces_state: !flow.produces_state_block.nil?
  }
  OutputFormat.current.emit(payload, JSON.pretty_generate(payload))
end

.run_flow(client, args) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/browserctl/commands/flow.rb', line 26

def self.run_flow(client, args)
  name = args.shift or
    abort "usage: browserctl flow run <name|file> [--page NAME] [--params FILE] [--key value ...]"

  flow = resolve(name)
  page_name, params = parse_run_args(args)
  page_proxy = page_name ? Browserctl::PageProxy.new(page_name, client) : nil

  result = flow.run(page: page_proxy, client: client, **params)
  OutputFormat.current.emit({ ok: true, flow: flow.name, result: serialisable(result) })
rescue Browserctl::FlowError => e
  warn "Error: #{e.message}"
  OutputFormat.current.emit({ ok: false, code: e.code, error: e.message }) unless OutputFormat.current.silent?
  exit 1
end

.run_listObject



42
43
44
45
# File 'lib/browserctl/commands/flow.rb', line 42

def self.run_list
  entries = Browserctl::FlowRegistry.list
  OutputFormat.current.emit({ flows: entries })
end

.serialisable(value) ⇒ Object



116
117
118
119
120
121
122
# File 'lib/browserctl/commands/flow.rb', line 116

def self.serialisable(value)
  case value
  when nil, true, false, Numeric, String, Hash, Array then value
  when Symbol then value.to_s
  else value.respond_to?(:to_h) ? value.to_h : value.to_s
  end
end

.take_option(args, flag) ⇒ Object



85
86
87
88
89
90
91
92
# File 'lib/browserctl/commands/flow.rb', line 85

def self.take_option(args, flag)
  idx = args.index(flag)
  return nil unless idx

  value = args.delete_at(idx + 1)
  args.delete_at(idx)
  value
end