@@ -30,17 +30,29 @@ class ConfigLoader
3030 # @return [Hash] Merged configuration
3131 def self . load ( config_path : nil )
3232 config = DEFAULT_CONFIG . dup
33+ overrides = [ ]
3334
3435 # Load from file if path provided
3536 if config_path . is_a? ( String ) && File . exist? ( config_path )
3637 file_config = load_config_file ( config_path )
37- config . merge! ( file_config ) if file_config
38- elsif config_path . is_a? ( Hash )
39- config . merge! ( config_path )
38+ if file_config
39+ overrides << "file config"
40+ config . merge! ( file_config )
41+ end
42+ end
43+
44+ # Override with environment variables (before programmatic config)
45+ env_config = load_env_config
46+ if env_config . any?
47+ overrides << "environment variables"
48+ config . merge! ( env_config )
4049 end
4150
42- # Override with environment variables
43- config . merge! ( load_env_config )
51+ # Programmatic config has highest priority
52+ if config_path . is_a? ( Hash )
53+ overrides << "programmatic config"
54+ config . merge! ( config_path )
55+ end
4456
4557 # Convert string keys to symbols for consistency
4658 config = symbolize_keys ( config )
@@ -51,6 +63,13 @@ def self.load(config_path: nil)
5163 config [ :production ] = false
5264 end
5365
66+ # Log overrides if any were made
67+ if overrides . any?
68+ # Use puts for now since logger might not be initialized yet
69+ # This will be replaced with proper logging once the logger is available
70+ puts "INFO: Configuration overrides applied from: #{ overrides . join ( ', ' ) } "
71+ end
72+
5473 return config
5574 end
5675
@@ -93,8 +112,9 @@ def self.load_config_file(file_path)
93112 end
94113
95114 result
96- rescue => _e
97- # In production, we'd log this error
115+ rescue => e
116+ # Log this error with meaningful information
117+ puts "ERROR: Failed to load config file '#{ file_path } ': #{ e . message } "
98118 nil
99119 end
100120
@@ -105,26 +125,35 @@ def self.load_env_config
105125 env_config = { }
106126
107127 env_mappings = {
128+ "HOOKS_HANDLER_DIR" => :handler_dir ,
108129 "HOOKS_HANDLER_PLUGIN_DIR" => :handler_plugin_dir ,
109130 "HOOKS_AUTH_PLUGIN_DIR" => :auth_plugin_dir ,
131+ "HOOKS_LIFECYCLE_PLUGIN_DIR" => :lifecycle_plugin_dir ,
132+ "HOOKS_INSTRUMENTS_PLUGIN_DIR" => :instruments_plugin_dir ,
110133 "HOOKS_LOG_LEVEL" => :log_level ,
111134 "HOOKS_REQUEST_LIMIT" => :request_limit ,
112135 "HOOKS_REQUEST_TIMEOUT" => :request_timeout ,
113136 "HOOKS_ROOT_PATH" => :root_path ,
114137 "HOOKS_HEALTH_PATH" => :health_path ,
115138 "HOOKS_VERSION_PATH" => :version_path ,
116139 "HOOKS_ENVIRONMENT" => :environment ,
117- "HOOKS_ENDPOINTS_DIR" => :endpoints_dir
140+ "HOOKS_ENDPOINTS_DIR" => :endpoints_dir ,
141+ "HOOKS_USE_CATCHALL_ROUTE" => :use_catchall_route ,
142+ "HOOKS_SYMBOLIZE_PAYLOAD" => :symbolize_payload ,
143+ "HOOKS_NORMALIZE_HEADERS" => :normalize_headers
118144 }
119145
120146 env_mappings . each do |env_key , config_key |
121147 value = ENV [ env_key ]
122148 next unless value
123149
124- # Convert numeric values
150+ # Convert values to appropriate types
125151 case config_key
126152 when :request_limit , :request_timeout
127153 env_config [ config_key ] = value . to_i
154+ when :use_catchall_route , :symbolize_payload , :normalize_headers
155+ # Convert string to boolean
156+ env_config [ config_key ] = %w[ true 1 yes on ] . include? ( value . downcase )
128157 else
129158 env_config [ config_key ] = value
130159 end
0 commit comments