RFC: Handling lazy evaluation/passing in secrets, e.g. for hasura
A hasura-generated endpoint I work with is authenticated and requires a header "x-api-key" => api_key
I have a client class which takes in a client_name and looks up some configuration information, such as an api_key, which is not available globally.
the graphql-client gem would recommend I define
HTTP = ::GraphQL::Client::HTTP.new(uri) do
def headers(_context)
# Optionally set any HTTP headers
{
"Accept" => "application/json;charset=UTF-8",
"Content-Type" => "application/json",
"x-api-key" => api_key,
}
end
but I don't have access to that 'context' yet, so I have an instance method like
@http ||=
begin
instance = self
::GraphQL::Client::HTTP.new(uri) do
define_method :headers do |_context|
# Optionally set any HTTP headers
{
"Accept" => "application/json;charset=UTF-8",
"Content-Type" => "application/json",
"x-api-key" => instance.api_key,
}
end
end
I know that code pattern makes me feel like I'm fighting the library, but I persist because I can't @schema ||= GraphQL::Client.load_schema(http) and @client ||= ::GraphQL::Client.new(schema: schema, execute: http) without the authenticated 'http', which requires authentication.
Now, I know that when I query like client.query(definition, variables: variables, context: client_context) that the 'client_context' can include the auth keys, but I don't get access to that until after the 'schema' has been loaded by the 'http'. (Now, I can possibly get around that by loading the schema from a file, but that also feels like fighting the library).
But the problem really beings when I client.parse(definition) because there's a requirement that that the returned module have a 'name' (presumably duck-typing that it's been set to a constant). I can work around this by
@client ||= ::GraphQL::Client.new(schema: schema, execute: http).tap do |client|
client.allow_dynamic_queries = true
end
but since allow_dynamic_queries is deprecated, I know that this is both fighting the library and not a long-term solution.
I've searched around in this repository and a few others and haven't found anything which addresses these issues.
Hopefully this makes sense.
The alternative would a factory pattern which builds the Http, Client, Schema, and all the Definitions.. but that seems like more meta-programming than I'm up for right now.
@josh this a you thing?