Class: Printavo::GraphqlClient

Inherits:
Object
  • Object
show all
Defined in:
lib/printavo/graphql_client.rb

Constant Summary collapse

SAFE_ERROR_EXTENSION_KEYS =
%w[classification code].freeze
SAFE_METADATA_HEADERS =
%w[
  retry-after
  x-request-id
  x-ratelimit-limit
  x-ratelimit-remaining
  x-ratelimit-reset
].freeze

Instance Method Summary collapse

Constructor Details

#initialize(connection, cache: nil, default_ttl: 300, sensitive_values: []) ⇒ GraphqlClient

Returns a new instance of GraphqlClient.

Parameters:

  • connection (Faraday::Connection)
  • cache (#fetch, #delete, nil) (defaults to: nil)

    any cache store implementing fetch(key, expires_in:) { } and delete(key), e.g. Rails.cache, Printavo::MemoryStore.new, or nil

  • default_ttl (Integer) (defaults to: 300)

    default TTL in seconds applied to cached queries (default: 300)

  • sensitive_values (Array<String>) (defaults to: [])

    credentials to redact from provider messages



24
25
26
27
28
29
30
31
32
# File 'lib/printavo/graphql_client.rb', line 24

def initialize(connection, cache: nil, default_ttl: 300, sensitive_values: [])
  @connection  = connection
  @cache       = cache
  @default_ttl = default_ttl
  @sensitive_values = sensitive_values.filter_map do |value|
    string = value.to_s
    string unless string.empty?
  end.freeze
end

Instance Method Details

#mutate(mutation_string, variables: {}) ⇒ Hash

Executes a GraphQL mutation and returns the parsed data hash. Semantically equivalent to query — both POST to the same endpoint — but distinguishes write intent at the call site.

Examples:

client.graphql.mutate(
  <<~GQL,
    mutation UpdateOrder($id: ID!, $input: OrderInput!) {
      updateOrder(id: $id, input: $input) {
        order { id nickname }
        errors
      }
    }
  GQL
  variables: { id: "99", input: { nickname: "Rush Job" } }
)

Parameters:

  • mutation_string (String)

    the GraphQL mutation document

  • variables (Hash) (defaults to: {})

    optional input variables

Returns:

  • (Hash)


74
75
76
# File 'lib/printavo/graphql_client.rb', line 74

def mutate(mutation_string, variables: {})
  execute(mutation_string, variables: variables)
end

#mutate_envelope(mutation_string, variables: {}) ⇒ Printavo::ResponseEnvelope

Mutation equivalent of #query_envelope. Callers must decide whether a partial mutation response represents an uncertain write.



91
92
93
# File 'lib/printavo/graphql_client.rb', line 91

def mutate_envelope(mutation_string, variables: {})
  execute_envelope(mutation_string, variables: variables)
end

#paginate(query_string, path:, variables: {}, first: 25) {|nodes| ... } ⇒ Object

Iterates all pages of a paginated GraphQL query, yielding each page's nodes array. The query must accept $first: Int and $after: String variables, and the target connection must expose nodes and pageInfo.

Examples:

client.graphql.paginate(ORDERS_QUERY, path: "orders") do |nodes|
  nodes.each { |n| puts n["nickname"] }
end

With extra variables

client.graphql.paginate(JOBS_QUERY, path: "order.lineItems",
                        variables: { orderId: "99" }, first: 50) do |nodes|
  nodes.each { |j| puts j["name"] }
end

Parameters:

  • query_string (String)

    the GraphQL query document

  • path (String)

    dot-separated key path to the connection in the response e.g. "orders" or "customer.orders"

  • variables (Hash) (defaults to: {})

    additional variables merged with first and after

  • first (Integer) (defaults to: 25)

    page size (default 25)

Yield Parameters:

  • nodes (Array<Hash>)

    one page of raw node hashes



116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/printavo/graphql_client.rb', line 116

def paginate(query_string, path:, variables: {}, first: 25)
  after = nil
  loop do
    data  = execute(query_string, variables: variables.merge(first: first, after: after))
    conn  = dig_path(data, path)
    nodes = conn&.fetch('nodes', []) || []
    yield nodes
    page_info = conn&.fetch('pageInfo', {}) || {}
    break unless page_info['hasNextPage']

    after = page_info['endCursor']
  end
end

#query(query_string, variables: {}) ⇒ Hash

Executes a GraphQL query and returns the parsed data hash.

Examples:

client.graphql.query("{ customers { nodes { id } } }")
client.graphql.query(
  "query Customer($id: ID!) { customer(id: $id) { id email } }",
  variables: { id: "42" }
)

Parameters:

  • query_string (String)

    the GraphQL query document

  • variables (Hash) (defaults to: {})

    optional input variables

Returns:

  • (Hash)


46
47
48
49
50
51
52
# File 'lib/printavo/graphql_client.rb', line 46

def query(query_string, variables: {})
  return execute(query_string, variables: variables) unless @cache

  @cache.fetch(cache_key(query_string, variables), expires_in: @default_ttl) do
    execute(query_string, variables: variables)
  end
end

#query_envelope(query_string, variables: {}) ⇒ Printavo::ResponseEnvelope

Executes a GraphQL query without discarding partial data when GraphQL errors are present. HTTP and transport failures still raise their identifier-only SDK exceptions.



83
84
85
# File 'lib/printavo/graphql_client.rb', line 83

def query_envelope(query_string, variables: {})
  execute_envelope(query_string, variables: variables)
end