lib/superconfig.rb in superconfig-1.0.0 vs lib/superconfig.rb in superconfig-2.0.1

- old
+ new

@@ -1,9 +1,9 @@ # frozen_string_literal: true module SuperConfig - VERSION = "1.0.0" + VERSION = "2.0.1" MissingEnvironmentVariable = Class.new(StandardError) MissingCallable = Class.new(StandardError) def self.new(**kwargs, &block) @@ -16,10 +16,11 @@ def initialize(env: ENV, raise_exception: true, stderr: $stderr, &block) @env = env @raise_exception = raise_exception @stderr = stderr + @attributes = {} @__cache__ = {} instance_eval(&block) end def to_s @@ -35,18 +36,21 @@ aliases: [], description: nil ) name = name.to_s env_var = name.upcase + + @attributes[env_var] = {required: required, default: default} + name = "#{name}?" if type == bool validate!(env_var, required, description) define_singleton_method(name) do return default unless @env.key?(env_var) - coerce(type, @env[env_var]) + coerce(env_var, type, @env[env_var]) end aliases.each do |alias_name| define_singleton_method(alias_name, method(name)) end @@ -137,44 +141,72 @@ def json :json end - private def coerce_to_string(value) + def report + attrs = @attributes.sort + + report = attrs.each_with_object([]) do |(env_var, info), buffer| + icon, message = if @env.key?(env_var) + ["✅", "is set"] + elsif info[:required] + ["❌", "is not set"] + elsif !info[:required] && !info[:default].nil? + ["✅", "is not set, but has default value"] + else + ["⚠️", "is not set"] + end + + label = if info[:required] + "mandatory" + else + "optional" + end + + buffer << [icon, env_var, message, "(#{label})"].join(" ") + end + + "#{report.join("\n")}\n" + end + + private def coerce_to_string(_name, value) value end - private def coerce_to_bool(value) + private def coerce_to_bool(_name, value) BOOL_TRUE.include?(value) end - private def coerce_to_int(value) + private def coerce_to_int(_name, value) Integer(value) if !BOOL_FALSE.include?(value) && value end - private def coerce_to_float(value) + private def coerce_to_float(_name, value) Float(value) if value end - private def coerce_to_bigdecimal(value) + private def coerce_to_bigdecimal(_name, value) BigDecimal(value) if value end - private def coerce_to_symbol(value) + private def coerce_to_symbol(_name, value) value&.to_sym end - private def coerce_to_array(value, type) - value&.split(/, */)&.map {|v| coerce(type, v) } + private def coerce_to_array(name, value, type) + value&.split(/, */)&.map {|v| coerce(name, type, v) } end - private def coerce_to_json(value) + private def coerce_to_json(name, value) value && JSON.parse(value) + rescue JSON::ParserError + raise ArgumentError, "#{name} is not a valid JSON string" end - private def coerce(type, value) + private def coerce(name, type, value) main_type, sub_type = type - args = [value] + args = [name, value] args << sub_type if sub_type send("coerce_to_#{main_type}", *args) end end