lib/graphql/remote_loader/loader.rb in graphql-remote_loader-0.0.5 vs lib/graphql/remote_loader/loader.rb in graphql-remote_loader-1.0.0
- old
+ new
@@ -1,6 +1,7 @@
require "prime"
+require "json"
require_relative "query_merger"
module GraphQL
module RemoteLoader
class Loader < GraphQL::Batch::Loader
@@ -31,21 +32,36 @@
private
def perform(queries_and_primes)
query_string = QueryMerger.merge(queries_and_primes)
- response = query(query_string)
+ response = query(query_string).to_h
+ data, errors = response["data"], response["errors"]
+
queries_and_primes.each do |query, prime|
- fulfill([query, prime], filter_keys_on_response(response.to_h, prime))
+ response = {}
+
+ response["data"] = filter_keys_on_data(data, prime)
+
+ errors_key = filter_errors(errors, prime)
+ response["errors"] = dup(errors_key) unless errors_key.empty?
+
+ scrub_primes_from_error_paths!(response["errors"])
+
+ fulfill([query, prime], response)
end
end
- def filter_keys_on_response(obj, prime)
+ def dup(hash)
+ JSON.parse(hash.to_json)
+ end
+
+ def filter_keys_on_data(obj, prime)
case obj
when Array
- obj.map { |element| filter_keys_on_response(element, prime) }
+ obj.map { |element| filter_keys_on_data(element, prime) }
when Hash
filtered_results = {}
# Select field keys on the results hash
fields = obj.keys.select { |k| k.match /\Ap[0-9]+.*[^?]\z/ }
@@ -59,17 +75,45 @@
# redefine methods on new obj, recursively filter sub-selections
fields.each do |method|
method_name = method.match(/\Ap[0-9]+(.*)/)[1]
method_value = obj[method]
- filtered_value = filter_keys_on_response(method_value, prime)
+ filtered_value = filter_keys_on_data(method_value, prime)
filtered_results[underscore(method_name)] = filtered_value
end
filtered_results
else
return obj
+ end
+ end
+
+ def filter_errors(errors, prime)
+ return [] unless errors
+
+ errors.select do |error|
+ # For now, do not support global errors with no path key
+ next unless error["path"]
+
+ # We fulfill a promise with an error object if field in the path
+ # key was requested by the promise.
+ error["path"].all? do |path_key|
+ next true if path_key.is_a? Integer
+
+ path_key_prime = path_key.match(/\Ap([0-9]+)/)[1].to_i
+ path_key_prime % prime == 0
+ end
+ end
+ end
+
+ def scrub_primes_from_error_paths!(error_array)
+ return unless error_array
+
+ error_array.map do |error|
+ error["path"].map! do |path_key|
+ path_key.match(/\Ap[0-9]+(.*)/)[1]
+ end
end
end
def underscore(str)
str.gsub(/::/, '/').