Recipes
1. Application Configuration Manager
Centralized configuration with defaults and validation.
class APP_CONFIG
create
make
feature {NONE} -- Initialization
make
do
create env
load_config
end
feature -- Configuration
database_host: STRING_32
database_port: INTEGER
log_level: STRING_32
debug_mode: BOOLEAN
max_connections: INTEGER
feature -- Queries
is_valid: BOOLEAN
do
Result := not database_host.is_empty and
database_port > 0 and
max_connections > 0
end
feature {NONE} -- Implementation
env: SIMPLE_ENV
load_config
do
-- Required with defaults
database_host := get_or_default ("DB_HOST", "localhost")
database_port := get_integer_or_default ("DB_PORT", 5432)
log_level := get_or_default ("LOG_LEVEL", "INFO")
max_connections := get_integer_or_default ("MAX_CONNECTIONS", 10)
-- Boolean flag
debug_mode := get_boolean ("DEBUG")
end
get_or_default (a_name, a_default: STRING_32): STRING_32
do
if attached env.get (a_name) as v then
Result := v
else
Result := a_default
end
end
get_integer_or_default (a_name: STRING_32; a_default: INTEGER): INTEGER
do
if attached env.get (a_name) as v and then v.is_integer then
Result := v.to_integer
else
Result := a_default
end
end
get_boolean (a_name: STRING_32): BOOLEAN
do
if attached env.get (a_name) as v then
Result := v.same_string ("true") or
v.same_string ("1") or
v.same_string ("yes")
end
end
end
Usage
local
config: APP_CONFIG
do
create config.make
if config.is_valid then
print ("Database: " + config.database_host + ":" +
config.database_port.out)
if config.debug_mode then
print ("Debug mode enabled%N")
end
else
print ("Invalid configuration%N")
end
end
2. Dynamic Path Resolver
Resolve application paths with environment variable expansion.
class PATH_RESOLVER
create
make
feature {NONE} -- Initialization
make
do
create env
end
feature -- Path Resolution
config_dir: STRING_32
do
Result := env.expand ("%APPDATA%\MyApp")
end
data_dir: STRING_32
do
Result := env.expand ("%LOCALAPPDATA%\MyApp\Data")
end
log_dir: STRING_32
do
if attached env.get ("MYAPP_LOG_DIR") as custom then
Result := custom
else
Result := env.expand ("%TEMP%\MyApp\Logs")
end
end
temp_file (a_name: STRING_32): STRING_32
do
Result := env.expand ("%TEMP%\") + a_name
end
user_document (a_name: STRING_32): STRING_32
do
Result := env.expand ("%USERPROFILE%\Documents\") + a_name
end
resolve (a_template: STRING_32): STRING_32
-- Resolve any path with %VAR% references
do
Result := env.expand (a_template)
end
feature {NONE} -- Implementation
env: SIMPLE_ENV
end
Usage
local
paths: PATH_RESOLVER
do
create paths.make
-- Standard locations
print ("Config: " + paths.config_dir + "%N")
print ("Logs: " + paths.log_dir + "%N")
-- Dynamic paths
print ("Temp: " + paths.temp_file ("cache.tmp") + "%N")
-- Custom templates
print (paths.resolve ("%PROGRAMFILES%\MyApp\bin"))
end
3. Feature Flags from Environment
Control application features via environment variables.
class FEATURE_FLAGS
create
make
feature {NONE} -- Initialization
make
do
create env
end
feature -- Feature Queries
is_enabled (a_feature: STRING_32): BOOLEAN
-- Is feature enabled via FEATURE_{name}=true/1/yes?
do
if attached env.get ("FEATURE_" + a_feature.as_upper) as v then
Result := v.same_string_general ("true") or
v.same_string_general ("1") or
v.same_string_general ("yes")
end
end
is_disabled (a_feature: STRING_32): BOOLEAN
-- Is feature explicitly disabled?
do
if attached env.get ("FEATURE_" + a_feature.as_upper) as v then
Result := v.same_string_general ("false") or
v.same_string_general ("0") or
v.same_string_general ("no")
end
end
enabled_features: ARRAYED_LIST [STRING_32]
-- All currently enabled features
local
feature_vars: ARRAYED_LIST [STRING_32]
name: STRING_32
do
create Result.make (10)
feature_vars := env.names_with_prefix ("FEATURE_")
across feature_vars as var loop
name := var.substring (9, var.count) -- Remove "FEATURE_"
if is_enabled (name) then
Result.extend (name)
end
end
end
feature -- Common Features
new_ui_enabled: BOOLEAN
do
Result := is_enabled ("NEW_UI")
end
beta_features_enabled: BOOLEAN
do
Result := is_enabled ("BETA")
end
debug_logging_enabled: BOOLEAN
do
Result := is_enabled ("DEBUG_LOGGING")
end
feature {NONE} -- Implementation
env: SIMPLE_ENV
end
Usage
-- Set in environment:
-- FEATURE_NEW_UI=true
-- FEATURE_BETA=yes
-- FEATURE_DEBUG_LOGGING=1
local
flags: FEATURE_FLAGS
do
create flags.make
if flags.new_ui_enabled then
show_new_ui
else
show_classic_ui
end
if flags.is_enabled ("EXPERIMENTAL_CACHE") then
enable_experimental_cache
end
-- List all enabled features
across flags.enabled_features as f loop
print ("Enabled: " + f + "%N")
end
end
4. Library Path Manager
Manage simple_* library paths for build systems.
class LIBRARY_PATHS
create
make
feature {NONE} -- Initialization
make
do
create env
end
feature -- Library Access
simple_libraries: ARRAYED_LIST [TUPLE [name, path: STRING_32]]
-- All configured SIMPLE_* libraries
do
create Result.make (20)
across env.names_with_prefix ("SIMPLE_") as name loop
if attached env.get (name) as path then
Result.extend ([name.twin, path.twin])
end
end
end
library_path (a_name: STRING_32): detachable STRING_32
-- Get path for specific library (e.g., "json" -> SIMPLE_JSON path)
do
Result := env.get ("SIMPLE_" + a_name.as_upper)
end
is_configured (a_name: STRING_32): BOOLEAN
-- Is library path configured?
do
Result := env.has ("SIMPLE_" + a_name.as_upper)
end
feature -- Validation
missing_libraries (a_required: ARRAY [STRING_32]): ARRAYED_LIST [STRING_32]
-- Which required libraries are not configured?
do
create Result.make (a_required.count)
across a_required as lib loop
if not is_configured (lib) then
Result.extend (lib)
end
end
end
validate_required (a_required: ARRAY [STRING_32]): BOOLEAN
-- Are all required libraries configured?
do
Result := missing_libraries (a_required).is_empty
end
feature -- Output
generate_env_script: STRING_32
-- Generate shell script to set all library paths
do
create Result.make (1024)
Result.append ("#!/bin/bash%N")
across simple_libraries as lib loop
Result.append ("export " + lib.name + "=" + lib.path + "%N")
end
end
feature {NONE} -- Implementation
env: SIMPLE_ENV
end
Usage
local
libs: LIBRARY_PATHS
required: ARRAY [STRING_32]
do
create libs.make
-- Check required libraries
required := <<"JSON", "FILE", "ENV">>
if not libs.validate_required (required) then
print ("Missing libraries:%N")
across libs.missing_libraries (required) as lib loop
print (" SIMPLE_" + lib + "%N")
end
end
-- List all configured
across libs.simple_libraries as lib loop
print (lib.name + " = " + lib.path + "%N")
end
end
5. Environment Dump Utility
Dump environment variables for debugging.
class ENV_DUMP
create
make
feature {NONE} -- Initialization
make
do
create env
end
feature -- Output
dump_all: STRING_32
-- All environment variables as NAME=VALUE
do
create Result.make (4096)
across env.all_names as name loop
if attached env.get (name) as value then
Result.append (name + "=" + value + "%N")
end
end
end
dump_filtered (a_prefix: STRING_32): STRING_32
-- Variables matching prefix
do
create Result.make (1024)
across env.names_with_prefix (a_prefix) as name loop
if attached env.get (name) as value then
Result.append (name + "=" + value + "%N")
end
end
end
dump_sensitive_masked: STRING_32
-- All variables with sensitive values masked
local
value: STRING_32
do
create Result.make (4096)
across env.all_names as name loop
if attached env.get (name) as v then
if is_sensitive (name) then
value := "********"
else
value := v
end
Result.append (name + "=" + value + "%N")
end
end
end
feature {NONE} -- Implementation
env: SIMPLE_ENV
sensitive_patterns: ARRAY [STRING_32]
once
Result := <<"PASSWORD", "SECRET", "KEY", "TOKEN", "CREDENTIAL">>
end
is_sensitive (a_name: STRING_32): BOOLEAN
do
across sensitive_patterns as pattern loop
if a_name.as_upper.has_substring (pattern) then
Result := True
end
end
end
end
6. Simple .env File Loader
Load environment variables from .env files.
class DOTENV_LOADER
create
make
feature {NONE} -- Initialization
make
do
create env
end
feature -- Loading
load (a_path: STRING_32): BOOLEAN
-- Load .env file. Returns True if successful.
local
file: SIMPLE_FILE
lines: ARRAYED_LIST [STRING_32]
do
create file.make (a_path)
if file.exists then
lines := file.read_lines
across lines as line loop
process_line (line)
end
Result := True
end
end
load_if_exists (a_path: STRING_32)
-- Load .env file if it exists (silent if not)
do
load (a_path).do_nothing
end
feature {NONE} -- Implementation
env: SIMPLE_ENV
process_line (a_line: STRING_32)
local
line: STRING_32
eq_pos: INTEGER
name, value: STRING_32
do
line := a_line.twin
line.left_adjust
line.right_adjust
-- Skip empty lines and comments
if not line.is_empty and not line.starts_with ("#") then
eq_pos := line.index_of ('=', 1)
if eq_pos > 1 then
name := line.substring (1, eq_pos - 1)
value := line.substring (eq_pos + 1, line.count)
-- Remove surrounding quotes if present
value := unquote (value)
-- Only set if not already defined (don't override)
if not env.has (name) then
env.set (name, value)
end
end
end
end
unquote (a_value: STRING_32): STRING_32
do
Result := a_value.twin
if Result.count >= 2 then
if (Result.starts_with ("%"") and Result.ends_with ("%"")) or
(Result.starts_with ("'") and Result.ends_with ("'")) then
Result := Result.substring (2, Result.count - 1)
end
end
end
end
Usage
-- .env file:
-- DATABASE_URL=postgres://localhost/mydb
-- API_KEY="secret-key-12345"
-- DEBUG=true
local
dotenv: DOTENV_LOADER
do
create dotenv.make
dotenv.load_if_exists (".env")
-- Variables are now available via SIMPLE_ENV
end
7. Multi-Environment Configuration
Support development, staging, and production environments.
class MULTI_ENV_CONFIG
create
make
feature {NONE} -- Initialization
make
do
create env
detect_environment
end
feature -- Environment
environment: STRING_32
-- Current environment: development, staging, production
is_development: BOOLEAN
do
Result := environment.same_string ("development")
end
is_staging: BOOLEAN
do
Result := environment.same_string ("staging")
end
is_production: BOOLEAN
do
Result := environment.same_string ("production")
end
feature -- Environment-Specific Values
get (a_key: STRING_32): detachable STRING_32
-- Get value, checking environment-specific first
local
env_key: STRING_32
do
-- Try environment-specific first: PROD_DATABASE_URL
env_key := environment.as_upper.substring (1, 4) + "_" + a_key
Result := env.get (env_key)
-- Fall back to generic: DATABASE_URL
if Result = Void then
Result := env.get (a_key)
end
end
feature {NONE} -- Implementation
env: SIMPLE_ENV
detect_environment
do
if attached env.get ("APP_ENV") as e then
environment := e.as_lower
elseif attached env.get ("ENVIRONMENT") as e then
environment := e.as_lower
else
environment := "development"
end
end
end
8. Database Connection String Builder
Build connection strings from environment variables.
class DB_CONNECTION_BUILDER
create
make
feature {NONE} -- Initialization
make
do
create env
end
feature -- Connection Strings
postgres_url: detachable STRING_32
-- Build PostgreSQL connection URL from env vars
local
host, port, user, pass, db: detachable STRING_32
do
host := env.get ("DB_HOST")
port := env.get ("DB_PORT")
user := env.get ("DB_USER")
pass := env.get ("DB_PASSWORD")
db := env.get ("DB_NAME")
if host /= Void and db /= Void then
create Result.make (100)
Result.append ("postgresql://")
if user /= Void then
Result.append (user)
if pass /= Void then
Result.append (":" + pass)
end
Result.append ("@")
end
Result.append (host)
if port /= Void then
Result.append (":" + port)
end
Result.append ("/" + db)
end
end
sqlite_path: STRING_32
-- Get SQLite database path
do
if attached env.get ("SQLITE_PATH") as p then
Result := env.expand (p) -- Expand %APPDATA% etc.
else
Result := env.expand ("%LOCALAPPDATA%\MyApp\data.db")
end
end
feature {NONE} -- Implementation
env: SIMPLE_ENV
end
Usage
-- Environment:
-- DB_HOST=localhost
-- DB_PORT=5432
-- DB_USER=myapp
-- DB_PASSWORD=secret
-- DB_NAME=myapp_dev
local
builder: DB_CONNECTION_BUILDER
do
create builder.make
if attached builder.postgres_url as url then
print ("Connecting to: " + url)
-- postgresql://myapp:secret@localhost:5432/myapp_dev
end
end