Class: Rigor::Plugin::Manifest

Inherits:
Object
  • Object
show all
Defined in:
lib/rigor/plugin/manifest.rb

Overview

Value object describing one plugin’s identity and metadata. Constructed once per plugin class through Base.manifest; consumed by Loader when matching project configuration entries to registered plugins and by Cache::Descriptor::PluginEntry when deriving cache keys.

The fields are pinned by ADR-2 § “Registration, Configuration, and Caching”; the v0.1.0 plugin contract surface treats this struct as the public manifest shape.

Constant Summary collapse

VALID_ID =

Same regex Cache::Store::VALID_PRODUCER_ID uses, so plugin ids round-trip through cache producer ids and ‘plugin.<id>.<rule>` diagnostic identifiers without escape.

/\A[a-z][a-z0-9._-]*\z/
VALID_VALUE_KINDS =

The first-implementation ‘config_schema` accepts these value kinds. Slice 1 only checks key presence and shallow value kind; richer schemas (nested maps, enums) land later when the v0.1.0 protocol slices need them.

%i[string boolean integer array hash any].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(id:, version:, description: nil, protocols: [], config_schema: {}) ⇒ Manifest

Returns a new instance of Manifest.



28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/rigor/plugin/manifest.rb', line 28

def initialize(id:, version:, description: nil, protocols: [], config_schema: {})
  validate_id!(id)
  validate_version!(version)
  validate_protocols!(protocols)
  validate_config_schema!(config_schema)

  @id = id.dup.freeze
  @version = version.dup.freeze
  @description = description.nil? ? nil : description.to_s.dup.freeze
  @protocols = protocols.map(&:to_sym).freeze
  @config_schema = config_schema.to_h { |k, v| [k.to_s.dup.freeze, v.to_sym] }.freeze

  freeze
end

Instance Attribute Details

#config_schemaObject (readonly)

Returns the value of attribute config_schema.



26
27
28
# File 'lib/rigor/plugin/manifest.rb', line 26

def config_schema
  @config_schema
end

#descriptionObject (readonly)

Returns the value of attribute description.



26
27
28
# File 'lib/rigor/plugin/manifest.rb', line 26

def description
  @description
end

#idObject (readonly)

Returns the value of attribute id.



26
27
28
# File 'lib/rigor/plugin/manifest.rb', line 26

def id
  @id
end

#protocolsObject (readonly)

Returns the value of attribute protocols.



26
27
28
# File 'lib/rigor/plugin/manifest.rb', line 26

def protocols
  @protocols
end

#versionObject (readonly)

Returns the value of attribute version.



26
27
28
# File 'lib/rigor/plugin/manifest.rb', line 26

def version
  @version
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?



76
77
78
# File 'lib/rigor/plugin/manifest.rb', line 76

def ==(other)
  other.is_a?(Manifest) && to_h == other.to_h
end

#hashObject



81
82
83
# File 'lib/rigor/plugin/manifest.rb', line 81

def hash
  to_h.hash
end

#to_hObject



66
67
68
69
70
71
72
73
74
# File 'lib/rigor/plugin/manifest.rb', line 66

def to_h
  {
    "id" => id,
    "version" => version,
    "description" => description,
    "protocols" => protocols.map(&:to_s),
    "config_schema" => config_schema.to_h { |k, v| [k, v.to_s] }
  }
end

#validate_config(config) ⇒ Object

Validates the user-supplied plugin config block against this manifest’s ‘config_schema`. Returns an array of human-readable error strings (empty when the config is valid). Slice 1 checks only unknown keys and shallow value kind; nested schemas come with later slices.



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/rigor/plugin/manifest.rb', line 48

def validate_config(config)
  return ["plugin config must be a Hash, got #{config.class}"] unless config.is_a?(Hash)

  errors = []
  config.each do |key, value|
    key_s = key.to_s
    unless config_schema.key?(key_s)
      errors << "unknown config key #{key_s.inspect} for plugin #{id.inspect}"
      next
    end

    kind = config_schema.fetch(key_s)
    errors << "config key #{key_s.inspect} expected #{kind}, got #{value.class}" unless value_matches?(value,
                                                                                                       kind)
  end
  errors
end