Class: ForestAdminDatasourceGraphqlHasura::Client
- Inherits:
-
Object
- Object
- ForestAdminDatasourceGraphqlHasura::Client
- Defined in:
- lib/forest_admin_datasource_graphql_hasura/client.rb
Overview
GraphQL-over-HTTP client for Hasura (queries, mutations and the metadata API), on Net::HTTP so the gem needs no HTTP dependency.
Constant Summary collapse
- TRANSPORT_ERRORS =
Wrapped in TransportError (503) so they reach the user as an actionable message without masquerading as a client mistake: errors Hasura itself returns are the only ones raised as GraphqlError (400).
[ Net::OpenTimeout, Net::ReadTimeout, Net::WriteTimeout, Net::HTTPBadResponse, IOError, SocketError, SystemCallError, OpenSSL::SSL::SSLError, JSON::ParserError ].freeze
Instance Method Summary collapse
- #execute(query, variables = {}) ⇒ Object
-
#fetch_metadata ⇒ Object
Returns nil when the endpoint is unreachable or forbidden, which is common in production: introspection then falls back to the configuration and to naming conventions.
-
#initialize(configuration) ⇒ Client
constructor
A new instance of Client.
Constructor Details
#initialize(configuration) ⇒ Client
Returns a new instance of Client.
10 11 12 |
# File 'lib/forest_admin_datasource_graphql_hasura/client.rb', line 10 def initialize(configuration) @configuration = configuration end |
Instance Method Details
#execute(query, variables = {}) ⇒ Object
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/forest_admin_datasource_graphql_hasura/client.rb', line 22 def execute(query, variables = {}) body = JSON.generate({ query: query, variables: variables }) response = post(@configuration.uri, body) raise TransportError, "GraphQL endpoint returned HTTP #{response.code}" unless response.is_a?(Net::HTTPSuccess) # A 204 is a success with a nil body, which JSON.parse would turn into an # unwrapped TypeError. raise TransportError, 'GraphQL endpoint returned an empty body' if response.body.nil? || response.body.empty? payload = JSON.parse(response.body) raise TransportError, 'GraphQL endpoint returned an unexpected body' unless payload.is_a?(Hash) if payload['errors']&.any? = payload['errors'].map { |e| e['message'] }.join('; ') raise GraphqlError, end # A 200 with neither data nor errors is malformed, and letting a nil out # would crash the caller with an opaque NoMethodError. data = payload['data'] raise TransportError, 'GraphQL endpoint returned no data' if data.nil? data rescue *TRANSPORT_ERRORS => e raise TransportError, "Could not reach the GraphQL endpoint (#{e.class}): #{e.}" end |
#fetch_metadata ⇒ Object
Returns nil when the endpoint is unreachable or forbidden, which is common in production: introspection then falls back to the configuration and to naming conventions. Every fallback branch warns — losing the metadata silently disables polymorphism detection and custom root field resolution, and each cause deserves something to grep for.
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/forest_admin_datasource_graphql_hasura/client.rb', line 54 def if @configuration..nil? return ("no metadata endpoint could be derived from uri (no '/v1/graphql' " \ "segment); set the 'metadata_uri' option") end body = JSON.generate({ type: 'export_metadata', version: 2, args: {} }) response = post(@configuration., body) return ("the metadata endpoint answered HTTP #{response.code}") unless response.is_a?(Net::HTTPSuccess) (response.body) rescue *TRANSPORT_ERRORS => e ("the metadata endpoint is not reachable (#{e.class})") end |