Module: LanguageOperator::Config

Defined in:
lib/language_operator/config.rb,
lib/language_operator/config/tool_registry.rb,
lib/language_operator/config/cluster_config.rb

Overview

Configuration loading helpers for environment variables

Provides utilities for loading, validating, and type-converting configuration from environment variables with support for:

  • Key-to-env-var mappings
  • Prefixes (e.g., SMTP_HOST from prefix: 'SMTP')
  • Default values
  • Type conversion (string, integer, boolean, float, array)
  • Required config validation
  • Multiple fallback keys

Examples:

Load SMTP configuration

config = LanguageOperator::Config.load(
  { host: 'HOST', port: 'PORT', user: 'USER', password: 'PASSWORD' },
  prefix: 'SMTP',
  required: [:host, :user, :password],
  defaults: { port: '587', tls: 'true' },
  types: { port: :integer, tls: :boolean }
)
# => { host: "smtp.example.com", port: 587, user: "[email protected]",
#      password: "secret", tls: true }

Defined Under Namespace

Classes: ClusterConfig, ToolRegistry

Class Method Summary collapse

Class Method Details

.convert_type(value, type, separator: ',') ⇒ Object

Convert a string value to the specified type

For integer and float types, uses strict conversion that raises ArgumentError for invalid input (e.g., non-numeric strings).

Examples:

String conversion

Config.convert_type('hello', :string) # => "hello"

Integer conversion

Config.convert_type('42', :integer) # => 42
Config.convert_type('abc', :integer) # raises ArgumentError

Boolean conversion

Config.convert_type('true', :boolean) # => true
Config.convert_type('1', :boolean) # => true
Config.convert_type('yes', :boolean) # => true
Config.convert_type('false', :boolean) # => false

Float conversion

Config.convert_type('3.14', :float) # => 3.14
Config.convert_type('xyz', :float) # raises ArgumentError

Array conversion

Config.convert_type('a,b,c', :array) # => ["a", "b", "c"]

Parameters:

  • Raw string value from environment

  • Target type (:string, :integer, :boolean, :float, :array)

  • (defaults to: ',')

    Separator for array type (default: ',')

Returns:

  • Converted value

Raises:

  • When integer/float conversion fails



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/language_operator/config.rb', line 106

def self.convert_type(value, type, separator: ',')
  return nil if value.nil?

  case type
  when :string
    value.to_s
  when :integer
    Integer(value)
  when :float
    Float(value)
  when :boolean
    %w[true 1 yes on].include?(value.to_s.downcase)
  when :array
    return [] if value.to_s.empty?

    value.to_s.split(separator).map(&:strip).reject(&:empty?)
  else
    value
  end
end

.from_env(mappings, prefix: nil, defaults: {}, types: {}) ⇒ Hash{Symbol => Object}

Load configuration from environment variables

Examples:

Basic usage

config = Config.from_env(
  { database_url: 'DATABASE_URL' },
  defaults: { database_url: 'sqlite://localhost/db.sqlite3' }
)

With prefix and types

config = Config.from_env(
  { host: 'HOST', port: 'PORT' },
  prefix: 'REDIS',
  defaults: { port: '6379' },
  types: { port: :integer }
)
# Reads REDIS_HOST and REDIS_PORT env vars

Parameters:

  • Map of config keys to env var names

  • (defaults to: nil)

    Optional prefix to prepend to env var names

  • (defaults to: {})

    Default values for optional config

  • (defaults to: {})

    Type conversion (:string, :integer, :boolean, :float)

Returns:

  • Configuration hash with values from env vars or defaults



48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/language_operator/config.rb', line 48

def self.from_env(mappings, prefix: nil, defaults: {}, types: {})
  config = {}

  mappings.each do |key, env_var|
    full_var = prefix ? "#{prefix}_#{env_var}" : env_var
    raw_value = ENV[full_var] || defaults[key]

    config[key] = convert_type(raw_value, types[key] || :string)
  end

  config
end

.get(*keys, default: nil) ⇒ String?

Get environment variable with multiple fallback keys

Examples:

Config.get('SMTP_HOST', 'MAIL_HOST', default: 'localhost')

Parameters:

  • Environment variable names to try

  • (defaults to: nil)

    Default value if none found

Returns:

  • The first non-nil value or default



161
162
163
164
165
166
167
# File 'lib/language_operator/config.rb', line 161

def self.get(*keys, default: nil)
  keys.each do |key|
    value = ENV.fetch(key.to_s, nil)
    return value if value
  end
  default
end

.get_array(*keys, default: [], separator: ',') ⇒ Array<String>

Get environment variable as array (split by separator)

Examples:

Config.get_array('ALLOWED_HOSTS', separator: ',')

Parameters:

  • Environment variable names to try

  • (defaults to: [])

    Default value if none found

  • (defaults to: ',')

    Character to split on (default: ',')

Returns:

  • The value split into array



241
242
243
244
245
246
247
248
249
250
251
# File 'lib/language_operator/config.rb', line 241

def self.get_array(*keys, default: [], separator: ',')
  keys.each do |key|
    value = ENV.fetch(key.to_s, nil)
    next unless value
    next if value.empty?

    return value.split(separator).map(&:strip).reject(&:empty?)
  end

  default
end

.get_bool(*keys, default: false) ⇒ Boolean

Get environment variable as boolean

Treats 'true', '1', 'yes', 'on' as true (case insensitive).

Examples:

Config.get_bool('USE_TLS', 'ENABLE_TLS', default: true)

Parameters:

  • Environment variable names to try

  • (defaults to: false)

    Default value if none found

Returns:

  • The value as boolean



221
222
223
224
225
226
227
228
229
230
# File 'lib/language_operator/config.rb', line 221

def self.get_bool(*keys, default: false)
  keys.each do |key|
    value = ENV.fetch(key.to_s, nil)
    next unless value

    return %w[true 1 yes on].include?(value.to_s.downcase)
  end

  default
end

.get_int(*keys, default: nil) ⇒ Integer?

Get environment variable as integer

Examples:

Config.get_int('MAX_WORKERS', default: 4)

Parameters:

  • Environment variable names to try

  • (defaults to: nil)

    Default value if none found

Returns:

  • The value converted to integer, or default

Raises:



192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'lib/language_operator/config.rb', line 192

def self.get_int(*keys, default: nil)
  keys.each do |key|
    value = ENV.fetch(key.to_s, nil)
    next unless value

    begin
      return Integer(value)
    rescue ArgumentError, TypeError => e
      suggestion = "Please set #{key} to a valid integer (e.g., export #{key}=4)"
      raise ArgumentError, "Invalid integer value '#{value}' in environment variable '#{key}'. #{suggestion}. Error: #{e.message}"
    end
  end

  return default if default

  # No variables found
  raise ArgumentError, "Missing required integer configuration. Checked environment variables: #{keys.join(', ')}. Please set one of these variables."
end

.load(mappings, required: [], defaults: {}, types: {}, prefix: nil) ⇒ Hash

Load configuration with validation in one call

Combines from_env and validate_required! for convenience.

Examples:

Complete configuration loading

config = Config.load(
  { host: 'HOST', port: 'PORT', user: 'USER', password: 'PASSWORD' },
  prefix: 'SMTP',
  required: [:host, :user, :password],
  defaults: { port: '587' },
  types: { port: :integer }
)

Parameters:

  • Config key to env var mappings

  • (defaults to: [])

    Required config keys

  • (defaults to: {})

    Default values

  • (defaults to: {})

    Type conversions

  • (defaults to: nil)

    Env var prefix

Returns:

  • Validated configuration

Raises:

  • If required keys are missing



147
148
149
150
151
# File 'lib/language_operator/config.rb', line 147

def self.load(mappings, required: [], defaults: {}, types: {}, prefix: nil)
  config = from_env(mappings, prefix: prefix, defaults: defaults, types: types)
  validate_required!(config, required) unless required.empty?
  config
end

.require(*keys) ⇒ String

Get required environment variable with fallback keys

Examples:

Config.require('DATABASE_URL', 'DB_URL')

Parameters:

  • Environment variable names to try

Returns:

  • The first non-nil value

Raises:

  • If none of the keys are set



177
178
179
180
181
182
# File 'lib/language_operator/config.rb', line 177

def self.require(*keys)
  value = get(*keys)
  raise ArgumentError, "Missing required configuration: #{keys.join(' or ')}" unless value

  value
end

.set?(*keys) ⇒ Boolean

Check if environment variable is set (even if empty string)

Examples:

Config.set?('DEBUG', 'VERBOSE')

Parameters:

  • Environment variable names to check

Returns:

  • True if any key is set



260
261
262
# File 'lib/language_operator/config.rb', line 260

def self.set?(*keys)
  keys.any? { |key| ENV.key?(key.to_s) }
end

.validate_required!(config, required_keys) ⇒ Object

Validate that required configuration keys are present and non-empty

Examples:

Config.validate_required!(config, [:host, :user, :password])

Parameters:

  • Configuration hash

  • Keys that must be present

Raises:

  • If any required keys are missing or empty



69
70
71
72
73
74
# File 'lib/language_operator/config.rb', line 69

def self.validate_required!(config, required_keys)
  missing = required_keys.select { |key| config[key].nil? || config[key].to_s.strip.empty? }
  return if missing.empty?

  raise LanguageOperator::Errors.missing_config(missing.map(&:to_s).map(&:upcase))
end

.with_prefix(prefix) ⇒ Hash<String, String>

Get all environment variables matching a prefix

Examples:

Config.with_prefix('DATABASE_')
# Returns { 'URL' => '...', 'POOL_SIZE' => '5' } for DATABASE_URL and DATABASE_POOL_SIZE

Parameters:

  • Prefix to match

Returns:

  • Hash with prefix removed from keys



272
273
274
275
# File 'lib/language_operator/config.rb', line 272

def self.with_prefix(prefix)
  ENV.select { |key, _| key.start_with?(prefix) }
     .transform_keys { |key| key.sub(prefix, '') }
end