Class: Ace::Core::ConfigDiscovery

Inherits:
Object
  • Object
show all
Defined in:
lib/ace/core/config_discovery.rb

Overview

Public API for configuration discovery across the project hierarchy Wraps ace-config with ace-specific defaults (.ace config directory)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(start_path: nil) ⇒ ConfigDiscovery

Initialize config discovery

Parameters:

  • start_path (String) (defaults to: nil)

    Starting path for discovery (default: current directory)



15
16
17
18
19
20
21
22
23
# File 'lib/ace/core/config_discovery.rb', line 15

def initialize(start_path: nil)
  @start_path = start_path || Dir.pwd
  @finder = ::Ace::Support::Config::Molecules::ConfigFinder.new(
    config_dir: ".ace",
    defaults_dir: ".ace-defaults",
    use_traversal: true,
    start_path: @start_path
  )
end

Instance Attribute Details

#start_pathObject (readonly)

Returns the value of attribute start_path.



11
12
13
# File 'lib/ace/core/config_discovery.rb', line 11

def start_path
  @start_path
end

Class Method Details

.find(filename) ⇒ String?

Find a config file from current directory

Parameters:

  • filename (String)

    Config filename to find

Returns:

  • (String, nil)

    Path to config file



107
108
109
# File 'lib/ace/core/config_discovery.rb', line 107

def find(filename)
  new.find_config_file(filename)
end

.find_all(filename) ⇒ Array<String>

Find all config files from current directory

Parameters:

  • filename (String)

    Config filename to find

Returns:

  • (Array<String>)

    All matching file paths



114
115
116
# File 'lib/ace/core/config_discovery.rb', line 114

def find_all(filename)
  new.find_all_config_files(filename)
end

.load(filename) ⇒ Hash?

Load merged configuration

Parameters:

  • filename (String)

    Config file to load

Returns:

  • (Hash, nil)

    Merged configuration



127
128
129
# File 'lib/ace/core/config_discovery.rb', line 127

def load(filename)
  new.load_config(filename)
end

.project_rootString?

Get project root from current directory

Returns:

  • (String, nil)

    Project root path



120
121
122
# File 'lib/ace/core/config_discovery.rb', line 120

def project_root
  new.project_root
end

Instance Method Details

#config_search_pathsArray<String>

Get all configuration search paths in order

Returns:

  • (Array<String>)

    Ordered list of config directories being searched



53
54
55
# File 'lib/ace/core/config_discovery.rb', line 53

def config_search_paths
  @finder.search_paths
end

#find_all_config_files(filename) ⇒ Array<String>

Find all matching config files in cascade order

Parameters:

  • filename (String)

    Config filename to find

Returns:

  • (Array<String>)

    All matching file paths in priority order



35
36
37
# File 'lib/ace/core/config_discovery.rb', line 35

def find_all_config_files(filename)
  @finder.find_all_files(filename)
end

#find_config_file(filename) ⇒ String?

Find the first matching config file in the cascade

Parameters:

  • filename (String)

    Config filename to find

Returns:

  • (String, nil)

    Path to the config file or nil if not found



28
29
30
# File 'lib/ace/core/config_discovery.rb', line 28

def find_config_file(filename)
  @finder.find_file(filename)
end

#in_project?Boolean

Check if we’re in a project

Returns:

  • (Boolean)

    true if project root is found



47
48
49
# File 'lib/ace/core/config_discovery.rb', line 47

def in_project?
  !project_root.nil?
end

#load_config(filename, resolve_paths: true) ⇒ Hash?

Load configuration from the cascade for a specific file

Parameters:

  • filename (String)

    Config file to load

  • resolve_paths (Boolean) (defaults to: true)

    Whether to resolve relative paths (default: true)

Returns:

  • (Hash, nil)

    Merged configuration or nil if no files found



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/ace/core/config_discovery.rb', line 75

def load_config(filename, resolve_paths: true)
  files = find_all_config_files(filename)
  return nil if files.empty?

  require "yaml"
  config = {}

  # Load in reverse order so higher priority overwrites lower
  files.reverse_each do |file|
    file_config = YAML.load_file(file)
    if file_config.is_a?(Hash)
      # Resolve relative paths if requested
      if resolve_paths
        base_dir = File.dirname(file)
        # Determine project root for resolving plain paths
        proj_root = project_root
        file_config = resolve_relative_paths(file_config, base_dir, proj_root)
      end
      config = ::Ace::Support::Config::Atoms::DeepMerger.merge(config, file_config)
    end
  rescue => e
    warn "Error loading config from #{file}: #{e.message}"
  end

  config
end

#project_rootString?

Get the project root directory

Returns:

  • (String, nil)

    Project root path or nil if not in a project



41
42
43
# File 'lib/ace/core/config_discovery.rb', line 41

def project_root
  ::Ace::Support::Fs::Molecules::ProjectRootFinder.find(start_path: @start_path)
end

#relative_path(path) ⇒ String?

Get relative path from project root

Parameters:

  • path (String)

    Path to make relative

Returns:

  • (String, nil)

    Relative path or nil if not in project



60
61
62
63
64
65
66
67
68
69
# File 'lib/ace/core/config_discovery.rb', line 60

def relative_path(path)
  root = project_root
  return nil unless root

  expanded = File.expand_path(path)
  return nil unless expanded.start_with?(root)

  require "pathname"
  Pathname.new(expanded).relative_path_from(Pathname.new(root)).to_s
end