Class: Rigor::Plugin::Loader

Inherits:
Object
  • Object
show all
Defined in:
lib/rigor/plugin/loader.rb,
sig/rigor/plugin/loader.rbs

Overview

Resolves the project's .rigor.yml plugins: entries into instantiated plugin instances. The other Plugin namespaces (Services, Registry, Base, etc.) are not yet sig-covered, so reference them as untyped for now. The critical declaration here is self.load: without it, Steep matches against Kernel#load's (::String, ?(::Module | bool)) -> bool signature and reports MethodParameterMismatch for the keyword-only shape.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(services:, requirer: ->(name) { require name }) ⇒ Loader

Returns a new instance of Loader.

Parameters:

  • services (Rigor::Plugin::Services)
  • requirer (#call) (defaults to: ->(name) { require name })

    takes a gem name and returns truthy on successful require. Defaulted to Kernel.require via a lambda; the spec injects a fake to avoid touching the real load path.

  • services: (Object)
  • requirer: (^(String) -> untyped) (defaults to: ->(name) { require name })


30
31
32
33
# File 'lib/rigor/plugin/loader.rb', line 30

def initialize(services:, requirer: ->(name) { require name })
  @services = services
  @requirer = requirer
end

Instance Attribute Details

#requirer^(String) -> untyped (readonly)

rubocop:disable Metrics/ClassLength

Returns:

  • (^(String) -> untyped)


25
26
27
# File 'lib/rigor/plugin/loader.rb', line 25

def requirer
  @requirer
end

#servicesObject (readonly)

rubocop:disable Metrics/ClassLength

Returns:

  • (Object)


25
26
27
# File 'lib/rigor/plugin/loader.rb', line 25

def services
  @services
end

Class Method Details

.load(configuration:, services:, requirer: ->(name) { require name }) ⇒ Object

Parameters:

  • configuration: (Configuration)
  • services: (Object)
  • requirer: (^(String) -> untyped) (defaults to: ->(name) { require name })

Returns:

  • (Object)


35
36
37
# File 'lib/rigor/plugin/loader.rb', line 35

def self.load(configuration:, services:, requirer: ->(name) { require name })
  new(services: services, requirer: requirer).load(configuration.plugins)
end

Instance Method Details

#load(entries) ⇒ Registry

Parameters:

  • entries (Array<String, Hash>)

    the raw plugins: list from the configuration.

Returns:



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/rigor/plugin/loader.rb', line 41

def load(entries)
  plugins = []
  load_errors = []
  seen_ids = {}

  Array(entries).each_with_index do |raw, index|
    entry = normalise_entry(raw, index)
  rescue LoadError => e
    load_errors << e
  else
    begin
      plugin = resolve_and_instantiate(entry, seen_ids)
      plugins << plugin if plugin
    rescue LoadError => e
      load_errors << e
    end
  end

  # ADR-9 slice 5 — topological sort by `manifest(consumes:)` so producers run before consumers, plus
  # early `missing-producer` validation. Cycles surface as `dependency-cycle` LoadErrors. When
  # validation fails, the offending plugin(s) drop from the returned plugins list and the LoadError
  # surfaces alongside any earlier failure.
  plugins, sort_errors = topo_sort_plugins(plugins)
  load_errors.concat(sort_errors)

  blueprints = plugins.map { |plugin| Blueprint.new(klass_name: plugin.class.name, config: plugin.config) }
  Registry.new(plugins: plugins, blueprints: blueprints, load_errors: load_errors)
end