class ApolloUploadServer::GraphQLDataBuilder

Constants

OutOfBounds

Public Class Methods

new(strict_mode: false) click to toggle source
# File lib/apollo_upload_server/graphql_data_builder.rb, line 10
def initialize(strict_mode: false)
  @strict_mode = strict_mode
end

Public Instance Methods

call(params) click to toggle source
# File lib/apollo_upload_server/graphql_data_builder.rb, line 14
def call(params)
  operations = safe_json_parse(params['operations'])
  file_mapper = safe_json_parse(params['map'])

  return nil if operations.nil? || file_mapper.nil?
  if operations.is_a?(Hash)
    single_transformation(file_mapper, operations, params)
  else
    { '_json' => multiple_transformation(file_mapper, operations, params) }
  end
end

Private Instance Methods

assign_file(field, splited_path, file) click to toggle source
# File lib/apollo_upload_server/graphql_data_builder.rb, line 85
def assign_file(field, splited_path, file)
  wrapped_file = Wrappers::UploadedFile.new(file)

  if field.is_a? Hash
    field.merge!(splited_path.last => wrapped_file)
  elsif field.is_a? Array
    index = parse_array_index(splited_path)
    verify_array_index!(splited_path, index, field.size)
    field[index] = wrapped_file
  end
end
get_parent_field(operations, splited_path) click to toggle source
# File lib/apollo_upload_server/graphql_data_builder.rb, line 71
def get_parent_field(operations, splited_path)
  # returns parent element of file field

  splited_path[0..-2].inject(operations) do |element, key|
    case element
    when Array
      element[Integer(key)]
    else
      element[key]
    end
  end
end
multiple_transformation(file_mapper, operations, params) click to toggle source
# File lib/apollo_upload_server/graphql_data_builder.rb, line 43
def multiple_transformation(file_mapper, operations, params)
  operations = operations.dup

  file_mapper.each do |file_index, paths|
    paths.each do |path|
      splited_path = path.split('.')
      # dig from second to penultimate key, and merge last key with value as file to operation with first key index
      field = operations[splited_path.first.to_i].dig(*splited_path[1..-2])

      assign_file(field, splited_path, params[file_index])
    end
  end
  operations
end
parse_array_index(path) click to toggle source
# File lib/apollo_upload_server/graphql_data_builder.rb, line 97
def parse_array_index(path)
  return path.last.to_i unless @strict_mode

  Integer(path.last)
rescue ArgumentError
  raise OutOfBounds, "Not a valid path to an array value: #{path.join('.')}"
end
safe_json_parse(data) click to toggle source
# File lib/apollo_upload_server/graphql_data_builder.rb, line 65
def safe_json_parse(data)
  JSON.parse(data)
rescue JSON::ParserError
  nil
end
single_transformation(file_mapper, operations, params) click to toggle source
# File lib/apollo_upload_server/graphql_data_builder.rb, line 28
def single_transformation(file_mapper, operations, params)
  operations = operations.dup
  file_mapper.each do |file_index, paths|
    paths.each do |path|
      splited_path = path.split('.')
      # splited_path => 'variables.input.profile_photo'; splited_path[0..-2] => ['variables', 'input']
      # dig from first to penultimate key, and merge last key with value as file

      field = get_parent_field(operations, splited_path)
      assign_file(field, splited_path, params[file_index])
    end
  end
  operations
end
verify_array_index!(path, index, size) click to toggle source
# File lib/apollo_upload_server/graphql_data_builder.rb, line 58
def verify_array_index!(path, index, size)
  return unless @strict_mode
  return if 0 <= index && index < size

  raise OutOfBounds, "Path #{path.join('.')} maps to out-of-bounds index: #{index}"
end