module Tina4::Env
def self.truthy?(val)
Accepts: "true", "True", "TRUE", "1", "yes", "Yes", "YES", "on", "On", "ON".
Check if a value is truthy for env boolean checks.
def self.truthy?(val) %w[true 1 yes on].include?(val.to_s.strip.downcase) end
def all_env
def all_env ENV.to_h end
def create_default_env(path)
def create_default_env(path) api_key = Digest::MD5.hexdigest(Time.now.to_s) content = DEFAULT_ENV.map { |k, v| "#{k}=\"#{v}\"" }.join("\n") content += "\nAPI_KEY=\"#{api_key}\"\n" File.write(path, content) end
def get_env(key, default = nil)
def get_env(key, default = nil) ENV[key.to_s] || default end
def has_env?(key)
def has_env?(key) ENV.key?(key.to_s) end
def load_env(root_dir = Dir.pwd)
def load_env(root_dir = Dir.pwd) env_file = resolve_env_file(root_dir) unless File.exist?(env_file) create_default_env(env_file) end parse_env_file(env_file) end
def parse_env_file(path)
def parse_env_file(path) return unless File.exist?(path) File.readlines(path).each do |line| line = line.strip next if line.empty? || line.start_with?("#") if (match = line.match(/\A([A-Za-z_][A-Za-z0-9_]*)=["']?(.*)["']?\z/)) key = match[1] value = match[2].gsub(/["']\z/, "") ENV[key] ||= value @loaded_keys ||= [] @loaded_keys << key end end end
def require_env!(*keys)
def require_env!(*keys) missing = keys.map(&:to_s).reject { |k| ENV.key?(k) } unless missing.empty? raise KeyError, "Missing required env vars: #{missing.join(', ')}" end end
def reset_env
def reset_env @loaded_keys&.each { |k| ENV.delete(k) } @loaded_keys = [] end
def resolve_env_file(root_dir)
def resolve_env_file(root_dir) environment = ENV["ENVIRONMENT"] if environment && !environment.empty? candidate = File.join(root_dir, ".env.#{environment}") return candidate if File.exist?(candidate) end File.join(root_dir, ".env") end