Class: RailsAiBridge::Registry::RegistryManifest

Inherits:
Data
  • Object
show all
Defined in:
lib/rails_ai_bridge/registry/registry_manifest.rb,
lib/rails_ai_bridge/registry/registry_manifest.rb

Overview

Validation API lives in a reopened class body rather than in the Data.define block: constant declarations inside a Data.define block resolve lexically into the surrounding Registry module, so a nested ValidationError could neither be defined on the Data class nor referenced by bare name from methods defined in that block.

Defined Under Namespace

Classes: ValidationError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(version:, packs:, default_stack:, context_providers: {}) ⇒ RegistryManifest

Backward-compatible constructor: context_providers defaults to an empty hash so manifests built before context provider support keep working.



18
19
20
# File 'lib/rails_ai_bridge/registry/registry_manifest.rb', line 18

def initialize(version:, packs:, default_stack:, context_providers: {})
  super
end

Instance Attribute Details

#context_providersHash{String => ContextProviderDefinition} (readonly)

Returns context providers keyed by name.

Returns:



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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
# File 'lib/rails_ai_bridge/registry/registry_manifest.rb', line 15

RegistryManifest = Data.define(:version, :packs, :default_stack, :context_providers) do
  # Backward-compatible constructor: +context_providers+ defaults to an empty
  # hash so manifests built before context provider support keep working.
  def initialize(version:, packs:, default_stack:, context_providers: {})
    super
  end

  # Builds a {RegistryManifest} from a parsed JSON hash.
  #
  # @param hash [Hash] parsed JSON object
  # @return [RegistryManifest]
  def self.from_json(hash)
    packs = (hash['packs'] || {}).transform_values do |pack_hash|
      PackDefinition.new(
        source: pack_hash.fetch('source'),
        tile: pack_hash.fetch('tile', 'directory.json'),
        always_loaded: pack_hash.fetch('always_loaded', false),
        depends_on: pack_hash.fetch('depends_on', []),
        ref: pack_hash.fetch('ref', nil)
      )
    end

    new(
      version: hash.fetch('version'),
      packs: packs,
      default_stack: hash.fetch('default_stack', []),
      context_providers: parse_context_providers(hash['context_providers'] || {})
    )
  rescue KeyError => error
    raise ArgumentError, "Registry manifest missing required field: #{error.key}"
  end

  # Loads and parses a registry manifest from a JSON file on disk.
  #
  # @param path [String] absolute or relative path to the registry JSON file
  # @return [RegistryManifest]
  # @raise [ArgumentError] if the file does not exist, cannot be read, or contains malformed JSON
  def self.from_file(path)
    from_json(JSON.parse(File.read(path)))
  rescue JSON::ParserError => error
    raise ArgumentError, "Registry manifest at '#{path}' contains invalid JSON: #{error.message}"
  rescue SystemCallError => error
    raise ArgumentError, "Registry manifest at '#{path}' could not be read: #{error.message}"
  end

  # @api private
  def self.parse_context_providers(providers_hash)
    providers_hash.transform_values { |provider_data| ContextProviderDefinition.from_json(provider_data) }
  end

  private_class_method :parse_context_providers
end

#default_stackArray<String> (readonly)

Returns pack names loaded when no framework is detected.

Returns:

  • (Array<String>)

    pack names loaded when no framework is detected



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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
# File 'lib/rails_ai_bridge/registry/registry_manifest.rb', line 15

RegistryManifest = Data.define(:version, :packs, :default_stack, :context_providers) do
  # Backward-compatible constructor: +context_providers+ defaults to an empty
  # hash so manifests built before context provider support keep working.
  def initialize(version:, packs:, default_stack:, context_providers: {})
    super
  end

  # Builds a {RegistryManifest} from a parsed JSON hash.
  #
  # @param hash [Hash] parsed JSON object
  # @return [RegistryManifest]
  def self.from_json(hash)
    packs = (hash['packs'] || {}).transform_values do |pack_hash|
      PackDefinition.new(
        source: pack_hash.fetch('source'),
        tile: pack_hash.fetch('tile', 'directory.json'),
        always_loaded: pack_hash.fetch('always_loaded', false),
        depends_on: pack_hash.fetch('depends_on', []),
        ref: pack_hash.fetch('ref', nil)
      )
    end

    new(
      version: hash.fetch('version'),
      packs: packs,
      default_stack: hash.fetch('default_stack', []),
      context_providers: parse_context_providers(hash['context_providers'] || {})
    )
  rescue KeyError => error
    raise ArgumentError, "Registry manifest missing required field: #{error.key}"
  end

  # Loads and parses a registry manifest from a JSON file on disk.
  #
  # @param path [String] absolute or relative path to the registry JSON file
  # @return [RegistryManifest]
  # @raise [ArgumentError] if the file does not exist, cannot be read, or contains malformed JSON
  def self.from_file(path)
    from_json(JSON.parse(File.read(path)))
  rescue JSON::ParserError => error
    raise ArgumentError, "Registry manifest at '#{path}' contains invalid JSON: #{error.message}"
  rescue SystemCallError => error
    raise ArgumentError, "Registry manifest at '#{path}' could not be read: #{error.message}"
  end

  # @api private
  def self.parse_context_providers(providers_hash)
    providers_hash.transform_values { |provider_data| ContextProviderDefinition.from_json(provider_data) }
  end

  private_class_method :parse_context_providers
end

#packsHash{String => PackDefinition} (readonly)

Returns map of pack name to definition.

Returns:



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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
# File 'lib/rails_ai_bridge/registry/registry_manifest.rb', line 15

RegistryManifest = Data.define(:version, :packs, :default_stack, :context_providers) do
  # Backward-compatible constructor: +context_providers+ defaults to an empty
  # hash so manifests built before context provider support keep working.
  def initialize(version:, packs:, default_stack:, context_providers: {})
    super
  end

  # Builds a {RegistryManifest} from a parsed JSON hash.
  #
  # @param hash [Hash] parsed JSON object
  # @return [RegistryManifest]
  def self.from_json(hash)
    packs = (hash['packs'] || {}).transform_values do |pack_hash|
      PackDefinition.new(
        source: pack_hash.fetch('source'),
        tile: pack_hash.fetch('tile', 'directory.json'),
        always_loaded: pack_hash.fetch('always_loaded', false),
        depends_on: pack_hash.fetch('depends_on', []),
        ref: pack_hash.fetch('ref', nil)
      )
    end

    new(
      version: hash.fetch('version'),
      packs: packs,
      default_stack: hash.fetch('default_stack', []),
      context_providers: parse_context_providers(hash['context_providers'] || {})
    )
  rescue KeyError => error
    raise ArgumentError, "Registry manifest missing required field: #{error.key}"
  end

  # Loads and parses a registry manifest from a JSON file on disk.
  #
  # @param path [String] absolute or relative path to the registry JSON file
  # @return [RegistryManifest]
  # @raise [ArgumentError] if the file does not exist, cannot be read, or contains malformed JSON
  def self.from_file(path)
    from_json(JSON.parse(File.read(path)))
  rescue JSON::ParserError => error
    raise ArgumentError, "Registry manifest at '#{path}' contains invalid JSON: #{error.message}"
  rescue SystemCallError => error
    raise ArgumentError, "Registry manifest at '#{path}' could not be read: #{error.message}"
  end

  # @api private
  def self.parse_context_providers(providers_hash)
    providers_hash.transform_values { |provider_data| ContextProviderDefinition.from_json(provider_data) }
  end

  private_class_method :parse_context_providers
end

#versionString (readonly)

Returns manifest schema version.

Returns:

  • (String)

    manifest schema version



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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
# File 'lib/rails_ai_bridge/registry/registry_manifest.rb', line 15

RegistryManifest = Data.define(:version, :packs, :default_stack, :context_providers) do
  # Backward-compatible constructor: +context_providers+ defaults to an empty
  # hash so manifests built before context provider support keep working.
  def initialize(version:, packs:, default_stack:, context_providers: {})
    super
  end

  # Builds a {RegistryManifest} from a parsed JSON hash.
  #
  # @param hash [Hash] parsed JSON object
  # @return [RegistryManifest]
  def self.from_json(hash)
    packs = (hash['packs'] || {}).transform_values do |pack_hash|
      PackDefinition.new(
        source: pack_hash.fetch('source'),
        tile: pack_hash.fetch('tile', 'directory.json'),
        always_loaded: pack_hash.fetch('always_loaded', false),
        depends_on: pack_hash.fetch('depends_on', []),
        ref: pack_hash.fetch('ref', nil)
      )
    end

    new(
      version: hash.fetch('version'),
      packs: packs,
      default_stack: hash.fetch('default_stack', []),
      context_providers: parse_context_providers(hash['context_providers'] || {})
    )
  rescue KeyError => error
    raise ArgumentError, "Registry manifest missing required field: #{error.key}"
  end

  # Loads and parses a registry manifest from a JSON file on disk.
  #
  # @param path [String] absolute or relative path to the registry JSON file
  # @return [RegistryManifest]
  # @raise [ArgumentError] if the file does not exist, cannot be read, or contains malformed JSON
  def self.from_file(path)
    from_json(JSON.parse(File.read(path)))
  rescue JSON::ParserError => error
    raise ArgumentError, "Registry manifest at '#{path}' contains invalid JSON: #{error.message}"
  rescue SystemCallError => error
    raise ArgumentError, "Registry manifest at '#{path}' could not be read: #{error.message}"
  end

  # @api private
  def self.parse_context_providers(providers_hash)
    providers_hash.transform_values { |provider_data| ContextProviderDefinition.from_json(provider_data) }
  end

  private_class_method :parse_context_providers
end

Class Method Details

.from_file(path) ⇒ RegistryManifest

Loads and parses a registry manifest from a JSON file on disk.

Parameters:

  • path (String)

    absolute or relative path to the registry JSON file

Returns:

Raises:

  • (ArgumentError)

    if the file does not exist, cannot be read, or contains malformed JSON



52
53
54
55
56
57
58
# File 'lib/rails_ai_bridge/registry/registry_manifest.rb', line 52

def self.from_file(path)
  from_json(JSON.parse(File.read(path)))
rescue JSON::ParserError => error
  raise ArgumentError, "Registry manifest at '#{path}' contains invalid JSON: #{error.message}"
rescue SystemCallError => error
  raise ArgumentError, "Registry manifest at '#{path}' could not be read: #{error.message}"
end

.from_json(hash) ⇒ RegistryManifest

Builds a RailsAiBridge::Registry::RegistryManifest from a parsed JSON hash.

Parameters:

  • hash (Hash)

    parsed JSON object

Returns:



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/rails_ai_bridge/registry/registry_manifest.rb', line 26

def self.from_json(hash)
  packs = (hash['packs'] || {}).transform_values do |pack_hash|
    PackDefinition.new(
      source: pack_hash.fetch('source'),
      tile: pack_hash.fetch('tile', 'directory.json'),
      always_loaded: pack_hash.fetch('always_loaded', false),
      depends_on: pack_hash.fetch('depends_on', []),
      ref: pack_hash.fetch('ref', nil)
    )
  end

  new(
    version: hash.fetch('version'),
    packs: packs,
    default_stack: hash.fetch('default_stack', []),
    context_providers: parse_context_providers(hash['context_providers'] || {})
  )
rescue KeyError => error
  raise ArgumentError, "Registry manifest missing required field: #{error.key}"
end

.validate!(data) ⇒ Hash

Validates the structure of a parsed registry manifest hash.

An empty manifest is valid (no required top-level keys). When present, known keys are type-checked: version (String), default_stack (Array of Strings), and packs (Hash of pack name to definition with a required non-empty String source). Unknown keys are ignored so future manifest fields do not break older validators.

Parameters:

  • data (Object)

    parsed JSON value to validate

Returns:

  • (Hash)

    the validated data, unchanged

Raises:



88
89
90
91
92
93
94
95
# File 'lib/rails_ai_bridge/registry/registry_manifest.rb', line 88

def self.validate!(data)
  raise ValidationError, 'Registry manifest root must be a JSON object (Hash)' unless data.is_a?(Hash)

  validate_version!(data) if data.key?('version')
  validate_default_stack!(data) if data.key?('default_stack')
  validate_packs!(data) if data.key?('packs')
  data
end