Class: Browserctl::FlowRegistry

Inherits:
Object
  • Object
show all
Defined in:
lib/browserctl/flow_registry.rb

Overview

Discovers and loads flow files from project, user, and bundled stdlib locations. Project flows shadow user flows, which shadow stdlib flows.

Files are plain Ruby; loading them is expected to invoke ‘Browserctl.flow(name) { … }`, which registers the flow in the global registry. Filename should match the registered name (validated lazily —mismatches are allowed but discouraged).

Constant Summary collapse

SAFE_NAME =
/\A[a-zA-Z0-9_-]+\z/

Class Method Summary collapse

Class Method Details

.bundled_dirObject

Search order: highest-precedence last so later registrations overwrite earlier ones in the global registry.



18
# File 'lib/browserctl/flow_registry.rb', line 18

def self.bundled_dir = File.expand_path("flows/stdlib", __dir__)

.listObject



56
57
58
# File 'lib/browserctl/flow_registry.rb', line 56

def self.list
  load_all.map { |n, f| { name: n, desc: f.description, version: f.version_string } }
end

.load_allObject

Loads every flow file from every search path. Lower-precedence dirs run first; project files load last and win on name collisions.



28
29
30
31
32
33
34
35
# File 'lib/browserctl/flow_registry.rb', line 28

def self.load_all
  search_paths.each do |dir|
    next unless Dir.exist?(dir)

    Dir.glob(File.join(dir, "*.rb")).each { |f| load f }
  end
  Browserctl.flow_registry_snapshot
end

.project_dirObject



20
# File 'lib/browserctl/flow_registry.rb', line 20

def self.project_dir = "./.browserctl/flows"

.resolve(name) ⇒ Object

Resolves a name to a registered flow, loading from disk on demand. Searches in precedence order: project → user → stdlib. The first matching file is loaded and the flow returned via the global registry.



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/browserctl/flow_registry.rb', line 40

def self.resolve(name)
  validate_name!(name)
  existing = Browserctl.lookup_flow(name)
  return existing if existing

  search_paths.reverse_each do |dir|
    candidate = File.join(dir, "#{name}.rb")
    next unless File.exist?(candidate)

    load candidate
    flow = Browserctl.lookup_flow(name)
    return flow if flow
  end
  nil
end

.search_pathsObject



22
23
24
# File 'lib/browserctl/flow_registry.rb', line 22

def self.search_paths
  [bundled_dir, user_dir, project_dir]
end

.user_dirObject



19
# File 'lib/browserctl/flow_registry.rb', line 19

def self.user_dir    = File.expand_path("~/.browserctl/flows")

.validate_name!(name) ⇒ Object

Raises:

  • (ArgumentError)


60
61
62
63
64
# File 'lib/browserctl/flow_registry.rb', line 60

def self.validate_name!(name)
  return if SAFE_NAME.match?(name.to_s)

  raise ArgumentError, "invalid flow name: #{name.inspect} — use letters, digits, _ and - only"
end