module Eco module Common class MethaThor class MultiInput MODES = [:both, :json, :value] attr_reader :mode def initialize(doc = {}, mode = :both) @mode = doc_mode(doc) || mode @mode = :both unless MODES.include?(@mode) @doc = {} @doc['value'] = {} if self.value? @doc['json'] = {} if self.json? self.merge(doc) unless doc.empty? end def to_h @doc end def json? @mode == :json || @mode = :both end def value? @mode == :value || @mode = :both end def json(key) @doc.dig('json', key) end def [](key) return @doc.dig('value', key) if self.value? JSON.parse(@doc.dig('json', key)) end def []=(key, value) @doc['value'][key] = value if self.value? @doc['json'][key] = to_json(value) if self.json? end def delete(key) if self.key?(key) value = @doc['value'].delete(key) if self.value? value2 = JSON.parse(@doc['json'].delete(key)) if self.json? return value if self.value? value2 end end def key?(key) return @doc['value'].key?(key) if self.value? @doc['json'].key?(key) end def present?(key) self[key]&.present? end def empty? return @doc['value'].keys.length == 0 if self.value? @doc['json'].keys.length == 0 end # merging implies that @mode is equalized to the lesser # => :both.merge(:json) == :json ; :value.merge(:both) == :value mode # => :json.merge(:value) will raise an exception def merge(value) merge_hash(hash(value)) self end private def to_json(value) if value.respond_to?(:as_json) input.as_json elsif value.respond_to?(:to_json) value.to_json end end def doc_mode(doc) case doc when String doc = JSON.parse(doc) return nil unless doc.is_a?(Hash) doc_mode(doc) when CliInput doc.mode when Hash mod_json = doc.key?('json') mod_value = doc.key?('value') mod_json ? (mod_value ? :both : :json) : (mod_value ? :value : nil) end end def hash(value) case value when String JSON.parse(value) when CliInput value.to_h when Hash value end end def merge_hash(value) err_input = "Error: merge requires a correct Hashable value or a #{self.class.name} instance." err_incompatible = "Error: can't merge value mode with json mode." raise err_input unless value.is_a?(Hash) return unless !value.empty? raise err_input if ! (mode = doc_mode(value)) raise err_incompatible if ! (new_mode = resolve_mode(mode)) @mode = new_mode @doc.delete('json') unless self.json? @doc.delete('value') unless self.value? @doc['json'].merge(value['json']) if self.json? @doc['value'].merge(value['value']) if self.value? end def resolve_mode(mode) return mode if @mode == :both return @mode if mode == :both return mode if @mode == mode end end end end end