module Ecoportal module API class GraphQL module Logic class Mutation class GenericPayload def initialize(*args, **kargs) raise "Missuse error. You should define a payload_class for a class that inherits from Mutation class." end end class GenericInput def initialize(*args, **kargs) raise "Missuse error. You should define a input_class for a class that inherits from Mutation class." end end include Ecoportal::API::Common::GraphQL::ClassHelpers class << self # Used to obtain the full `path` in the GraphQL query by using `base_path` # @note it is meant for reusability of queries from different end-points def field_name(str = nil) return @field_name unless str @field_name = nil @field_name = str.to_s if str end end class_resolver :payload_class, GenericPayload class_resolver :input_class, GenericInput attr_reader :client attr_reader :base_path def initialize(client, path: nil, base_path: []) @path = path @base_path = base_path @client = client end # Resolves the `path` by using `path` or `base_path` + `class.field_name`. def path(field_name = self.class.field_name) result = @path result ||= default_path if self.respond_to?(:default_path, true) result ||= (base_path + [field_name]) if base_path && field_name result end # Query rely that manages the different blocks. # @return [Class] an object of `response_class` with the results hanving from `path`. def query(input:, path: self.path, &block) request(*path) do client.query(input: as_input(input), &basic_block(&block)) end rescue Faraday::ParsingError => e puts "Internal Error with these input ('#{input.class}'):" pp input raise end def response_class payload_class end def access_point(path = []) path.last end private def basic_block(&block) raise "This method should be implemented in the child class #{self.class}" end def as_input(value) case value when input_class value.as_input when Hash value when Ecoportal::API::GraphQL::Base::Model value.as_input when Hash value = Helpers::Model::HashKeys.keys_to_sym_deep(value) Ecoportal::API::Base::Model.as_input(value) when Enumerable value.map {|v| as_input(v)} else raise ArgumentError.new("Expecting Hash, GraphQL::Base::Model or Enumerable. Unsupported type '#{value.class}'.") end end def request(*path) response = yield wrap_response(response, path) end def wrap_response(response, path = []) raise "Complete failure on request. Path: #{path}" unless res = response.to_h.dig(*path.dup.unshift("data")) data = Ecoportal::API::Common::GraphQL::HashHelpers.deep_dup(res) response_class.new(data) end end end end end end