From 56495fdf0e118563b292a26161f950b8b4755ffe Mon Sep 17 00:00:00 2001 From: kbaum Date: Sun, 8 Oct 2023 19:53:58 -0400 Subject: [PATCH] Pass in schema as an option --- README.md | 27 ++++++++++++++++++++++++++- lib/graphlient/client.rb | 11 ++++++++++- spec/graphlient/client_schema_spec.rb | 20 ++++++++++++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3985cfc..7f696b4 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,8 @@ A friendlier Ruby client for consuming GraphQL-based APIs. Built on top of your - [Installation](#installation) - [Usage](#usage) - - [Schema storing and loading on disk](#schema-storing-and-loading-on-disk) + - [Schema Storing and Loading on Disk](#schema-storing-and-loading-on-disk) + - [Preloading Schema Once](#preloading-schema-once) - [Error Handling](#error-handling) - [Executing Parameterized Queries and Mutations](#executing-parameterized-queries-and-mutations) - [Parse and Execute Queries Separately](#parse-and-execute-queries-separately) @@ -140,6 +141,30 @@ client = Client.new(url, schema_path: 'config/your_graphql_schema.json') client.schema.dump! # you only need to call this when graphql schema changes ``` +### Preloading schema once + +Even if caching the schema on disk, instantiating `Graphlient::Client` often can be both time and memory intensive due to reading in the schema for each instance. This is especially true if the schema is a large file. To get around these performance issues, instantiate your schema once and pass it in as a configuration option. + +One time in an initializer + +```ruby +$schema = Graphlient::Schema.new( + 'https://graphql.foo.com/graphql', 'lib/graphql_schema_foo.json' +) +``` + +Pass in each time you initialize a client + +``` +client = Graphlient::Client.new( + $schema.http, + $schema: schema, + headers: { + 'Authorization' => 'Bearer 123', + } +) +``` + ### Error Handling Unlike graphql-client, Graphlient will always raise an exception unless the query has succeeded. diff --git a/lib/graphlient/client.rb b/lib/graphlient/client.rb index a7e7bc4..a0b6e5e 100644 --- a/lib/graphlient/client.rb +++ b/lib/graphlient/client.rb @@ -2,9 +2,12 @@ module Graphlient class Client attr_accessor :uri, :options + class InvalidConfigurationError < StandardError; end + def initialize(url, options = {}, &_block) @url = url @options = options.dup + raise_error_if_invalid_configuration! yield self if block_given? end @@ -51,11 +54,17 @@ def http(&block) end def schema - @schema ||= Graphlient::Schema.new(http, schema_path) + @schema ||= options[:schema] || Graphlient::Schema.new(http, schema_path) end private + def raise_error_if_invalid_configuration! + if options.key?(:schema_path) && options.key?(:schema) + raise InvalidConfigurationError, 'schema_path and schema cannot both be provided' + end + end + def schema_path return options[:schema_path].to_s if options[:schema_path] end diff --git a/spec/graphlient/client_schema_spec.rb b/spec/graphlient/client_schema_spec.rb index e3b0247..8faeafe 100644 --- a/spec/graphlient/client_schema_spec.rb +++ b/spec/graphlient/client_schema_spec.rb @@ -51,5 +51,25 @@ expect(client.schema.path).to eq 'config/schema.json' end end + + context 'when preloaded schema is provided' do + let(:schema) { Graphlient::Schema.new(url, 'spec/support/fixtures/invoice_api.json') } + let(:client) { described_class.new(url, schema: schema) } + + it 'returns the passed in schema' do + expect(client.schema).not_to be_nil + expect(client.schema).to eq(schema) + end + end + + context 'when and a schema and a schema path are provided' do + let(:schema) { Graphlient::Schema.new(url, 'spec/support/fixtures/invoice_api.json') } + let(:client) { described_class.new(url, schema: schema, schema_path: 'spec/support/fixtures/invoice_api.json') } + + it 'raises an invalid configuration error' do + expect { client }.to raise_error(Graphlient::Client::InvalidConfigurationError, + /schema_path and schema cannot both be provided/) + end + end end end