# frozen_string_literal: true require 'eac_ruby_utils/configs' require 'eac_ruby_utils/core_ext' module EacRubyUtils module Console class Configs require_sub __FILE__ enable_console_speaker class << self def entry_key_to_envvar_name(entry_key) path = if entry_key.is_a?(::Array) entry_key else ::EacRubyUtils::PathsHash.parse_entry_key(entry_key) end path.join('_').gsub(/[^a-z0-9_]/i, '').gsub(/\A_+/, '').gsub(/_+\z/, '') .gsub(/_{2,}/, '_').upcase end end STORE_PASSWORDS_KEY = 'core.store_passwords' attr_reader :configs def initialize(configs_key, options = {}) options.assert_argument(::Hash, 'options') @configs = ::EacRubyUtils::Configs.new(configs_key, options.merge(autosave: true)) end def read_password(entry_key, options = {}) options = ReadEntryOptions.new(options.merge(noecho: true)) if store_passwords? read_entry(entry_key, options) else looped_entry_value_from_input(entry_key, options) end end def read_entry(entry_key, options = {}) options = ReadEntryOptions.new(options) unless options[:noenv] envvar_value = envvar_read_entry(entry_key) return envvar_value if envvar_value.present? end stored_value = configs.read_entry(entry_key) return stored_value if stored_value return read_entry_from_console(entry_key, options) unless options[:noinput] raise "No value found for entry \"#{entry_key}\"" if options[:required] end def store_passwords? read_entry( STORE_PASSWORDS_KEY, before_input: -> { store_password_banner }, validator: ->(entry_value) { %w[yes no].include?(entry_value) } ) == 'yes' end protected def envvar_read_entry(entry_key) env_entry_key = self.class.entry_key_to_envvar_name(entry_key) return nil unless ENV.key?(env_entry_key) ENV.fetch(env_entry_key).if_present(::EacRubyUtils::BlankNotBlank.instance) end def read_entry_from_console(entry_key, options) options[:before_input].call if options[:before_input].present? entry_value = looped_entry_value_from_input(entry_key, options) configs.write_entry(entry_key, entry_value) entry_value end def store_password_banner infom 'Do you wanna to store passwords?' infom "Warning: the passwords will be store in clear text in \"#{configs.storage_path}\"" infom 'Enter "yes" or "no"' end def looped_entry_value_from_input(entry_key, options) loop do entry_value = entry_value_from_input(entry_key, options) next if entry_value.blank? next if options[:validator] && !options[:validator].call(entry_value) return entry_value end end def entry_value_from_input(entry_key, options) entry_value = request_input("Value for entry \"#{entry_key}\"", options.request_input_options) warn('Entered value is blank') if entry_value.blank? entry_value end end end end