From cc010ad27206a5d69e6221c75de945df784c9f72 Mon Sep 17 00:00:00 2001 From: rellampec <30378924+rellampec@users.noreply.github.com> Date: Fri, 5 Jun 2026 09:29:33 +1200 Subject: [PATCH 01/13] feat: add Client#to_query_string and Query#spread - Client#to_query_string(**kargs, &block): builds full query document from DSL block and returns a String without touching Faraday or HTTP. - Query#spread(fragment_name): emits ...FragmentName in the query string, replacing the deprecated ___Const graphql-client convention. - spec_helper.rb: rescue LoadError on byebug require (Windows Ruby 3.2). - CLAUDE.md: AI agent instructions for this fork. --- CHANGELOG.md | 9 +++ CLAUDE.md | 68 +++++++++++++++++++++ lib/graphlient/client.rb | 6 ++ lib/graphlient/query.rb | 7 +++ spec/graphlient/client_dsl_spec.rb | 97 ++++++++++++++++++++++++++++++ spec/spec_helper.rb | 5 +- 6 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 CLAUDE.md create mode 100644 spec/graphlient/client_dsl_spec.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f8c545..0b18be2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,15 @@ * [#113](https://github.com/ashkan18/graphlient/pull/113): Fix CI builds - [@yuki24](https://github.com/yuki24). * [#112](https://github.com/ashkan18/graphlient/pull/112): Update graphql-client github repository links in README - [@th1988](https://github.com/th1988). +### EcoPortal fork additions (2026-06-05, branch: feature/dsl-only-mode) +* `Client#to_query_string(**kargs, &block)`: builds the full query document from the DSL block + and returns a `String` without touching the schema or Faraday HTTP adapter. Enables + DSL-only mode where HTTP dispatch is handled by a separate client - [@rellampec](https://github.com/rellampec). +* `Query#spread(fragment_name)`: emits `...FragmentName` into the query string. Replaces the + `___Const` graphql-client convention for fragment spreads in DSL blocks - [@rellampec](https://github.com/rellampec). +* `spec/spec_helper.rb`: rescue `LoadError` on `byebug` require so specs run on Windows + (x64-mingw-ucrt / Ruby 3.2) where byebug is not installable - [@rellampec](https://github.com/rellampec). + ### 0.8.0 (2024/01/06) * [#110](https://github.com/ashkan18/graphlient/pull/110): Ensure correct Faraday JSON response body parsing with invalid response header - [@taylorthurlow](https://github.com/taylorthurlow). * [#107](https://github.com/ashkan18/graphlient/pull/107): Pass in initialized schema as an option - [@kbaum](https://github.com/kbaum). diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..80f3a49 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,68 @@ +# CLAUDE.md — graphlient (EcoPortal fork) + +AI agent instructions for this repository. + +**Cross-cutting architecture context lives in `ecoportal-api-graphql` — see its `CLAUDE.md` and `.claude/` folder for the full dependency map, project history, and shared skills.** + +--- + +## Repository Role + +This is **EcoPortal's fork** of `graphlient` — a friendly Ruby client wrapper around `graphql-client`. `ecoportal-api-graphql` depends on this fork; `Common::GraphQL::Client` inherits from `Graphlient::Client`. + +**Position in chain:** +``` +graphql-client (our fork) + ↓ +graphlient ← THIS REPO (our fork) + ↓ +ecoportal-api-graphql +``` + +**Our fork:** https://github.com/rellampec/graphlient.git +**Upstream:** https://github.com/ashkan18/graphlient.git + +--- + +## Fork Policy + +- Changes made here are **not automatically contributed upstream**. If a fix is general enough to benefit the upstream project, discuss with the developer before opening a PR upstream. +- When pulling upstream changes, check for conflicts with any local modifications first. +- Keep a note in `CHANGELOG.md` (or a fork-specific section) for any changes that diverge from upstream. + +--- + +## Key Folder Layout + +``` +lib/graphlient/ + client.rb Main Graphlient::Client class + adapters/http/ HTTP adapters — faraday_adapter, http_adapter + errors/ Error hierarchy (client, server, execution, timeout, etc.) + extensions/query.rb Query DSL extension + query.rb Query builder + schema.rb Schema introspection and caching +``` + +--- + +## Namespace + +`Graphlient::` — single top-level namespace. + +--- + +## Key Concerns + +- `Graphlient::Client` is the class `ecoportal-api-graphql`'s `Common::GraphQL::Client` inherits from. Its constructor signature, `#execute`, and error classes are the primary integration surface. +- `no_schema:` option (added or expected by our usage) — schema introspection is disabled in EcoPortal's GraphQL client. Verify this is handled correctly after any changes to `schema.rb`. +- Error classes are caught and re-raised by `ecoportal-api-graphql` — changes to the error hierarchy may break upstream error handling. + +--- + +## Running Tests + +```bash +bundle install +bundle exec rspec +``` diff --git a/lib/graphlient/client.rb b/lib/graphlient/client.rb index 16d618d..8dd9b56 100644 --- a/lib/graphlient/client.rb +++ b/lib/graphlient/client.rb @@ -20,6 +20,12 @@ def parse(query_str = nil, &block) raise Graphlient::Errors::ClientError, e.message end + def to_query_string(**_kargs, &block) + Graphlient::Query.new do + instance_eval(&block) + end.to_s + end + def execute(query, variables = nil) query_params = {} query_params[:context] = @options if @options diff --git a/lib/graphlient/query.rb b/lib/graphlient/query.rb index 6735954..eb2fc2e 100644 --- a/lib/graphlient/query.rb +++ b/lib/graphlient/query.rb @@ -39,6 +39,13 @@ def to_s query_str.strip end + # Appends a named fragment spread (`...fragment_name`) to the query string. + # Use instead of the deprecated `___Const` convention. + def spread(fragment_name) + @query_str << "\n#{indent}...#{fragment_name}" + @query_str << "\n#{indent}" + end + private def evaluate(&block) diff --git a/spec/graphlient/client_dsl_spec.rb b/spec/graphlient/client_dsl_spec.rb new file mode 100644 index 0000000..2602d95 --- /dev/null +++ b/spec/graphlient/client_dsl_spec.rb @@ -0,0 +1,97 @@ +require 'spec_helper' + +describe Graphlient::Client do + let(:client) { described_class.new('http://example.com/graphql') } + + describe '#to_query_string' do + it 'returns a String' do + result = client.to_query_string do + query do + invoice(id: 10) do + id + feeInCents + end + end + end + expect(result).to be_a String + end + + it 'builds a simple query without HTTP or schema access' do + result = client.to_query_string do + query do + invoice(id: 10) do + id + feeInCents + end + end + end + expect(result).to include('query') + expect(result).to include('invoice') + expect(result).to include('feeInCents') + end + + it 'builds a parameterized query with variable declarations' do + result = client.to_query_string do + query(id: :int) do + invoice(id: :id) do + id + feeInCents + end + end + end + expect(result).to include('$id: Int') + expect(result).to include('invoice(id: $id)') + end + + it 'builds a mutation query string' do + result = client.to_query_string do + mutation(input: :CreateInvoiceInput!) do + createInvoice(input: :input) do + invoice do + id + end + errors + end + end + end + expect(result).to include('mutation') + expect(result).to include('createInvoice') + expect(result).to include('$input: CreateInvoiceInput!') + end + + it 'does not interact with the HTTP adapter' do + expect_any_instance_of(Graphlient::Adapters::HTTP::FaradayAdapter).not_to receive(:execute) + client.to_query_string do + query do + invoice(id: 1) { id } + end + end + end + + context 'with spread helper' do + it 'includes a named fragment spread in the query string' do + result = client.to_query_string do + query do + invoice(id: 10) do + spread :InvoiceFields + end + end + end + expect(result).to include('...InvoiceFields') + end + + it 'supports multiple spreads at the same level' do + result = client.to_query_string do + query do + nodes { + spread :FragmentA + spread :FragmentB + } + end + end + expect(result).to include('...FragmentA') + expect(result).to include('...FragmentB') + end + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index e73d719..b04284b 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -3,7 +3,10 @@ require 'rubygems' require 'rspec' require 'graphlient' -require 'byebug' if RUBY_ENGINE != 'jruby' +begin + require 'byebug' if RUBY_ENGINE != 'jruby' +rescue LoadError # byebug not available on all platforms (e.g. Windows x64-mingw-ucrt) +end require 'rack/test' require 'webmock/rspec' require 'vcr' From 8a5629929a30026dad070a9a1dd5a6f01a49bb30 Mon Sep 17 00:00:00 2001 From: rellampec <30378924+rellampec@users.noreply.github.com> Date: Fri, 5 Jun 2026 11:19:43 +1200 Subject: [PATCH 02/13] docs: move changelog entries to (Next) section, remove org-name header --- CHANGELOG.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b18be2..050fbd4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,15 +2,14 @@ * Your contribution here. * [#113](https://github.com/ashkan18/graphlient/pull/113): Fix CI builds - [@yuki24](https://github.com/yuki24). * [#112](https://github.com/ashkan18/graphlient/pull/112): Update graphql-client github repository links in README - [@th1988](https://github.com/th1988). - -### EcoPortal fork additions (2026-06-05, branch: feature/dsl-only-mode) -* `Client#to_query_string(**kargs, &block)`: builds the full query document from the DSL block - and returns a `String` without touching the schema or Faraday HTTP adapter. Enables - DSL-only mode where HTTP dispatch is handled by a separate client - [@rellampec](https://github.com/rellampec). -* `Query#spread(fragment_name)`: emits `...FragmentName` into the query string. Replaces the - `___Const` graphql-client convention for fragment spreads in DSL blocks - [@rellampec](https://github.com/rellampec). -* `spec/spec_helper.rb`: rescue `LoadError` on `byebug` require so specs run on Windows - (x64-mingw-ucrt / Ruby 3.2) where byebug is not installable - [@rellampec](https://github.com/rellampec). +* `Client#to_query_string(**kargs, &block)`: builds the full GraphQL query document from the + DSL block and returns a `String` without touching the schema or Faraday HTTP adapter. + Enables DSL-only mode where HTTP dispatch is handled externally - [@rellampec](https://github.com/rellampec). +* `Query#spread(fragment_name)`: emits `...FragmentName` into the query string as a named + fragment spread. Alternative to the `___Const` convention for use cases where + `graphql-client` constant parsing is not available - [@rellampec](https://github.com/rellampec). +* `spec/spec_helper.rb`: rescue `LoadError` on `byebug` require so specs run on platforms + where byebug is not installable (e.g. Windows with Ruby 3.2) - [@rellampec](https://github.com/rellampec). ### 0.8.0 (2024/01/06) * [#110](https://github.com/ashkan18/graphlient/pull/110): Ensure correct Faraday JSON response body parsing with invalid response header - [@taylorthurlow](https://github.com/taylorthurlow). From 896c73d6ff2cef74e5c313daaf39ec87903024d3 Mon Sep 17 00:00:00 2001 From: rellampec <30378924+rellampec@users.noreply.github.com> Date: Wed, 10 Jun 2026 01:01:02 +1200 Subject: [PATCH 03/13] =?UTF-8?q?fix:=20resolve=20CI=20failures=20?= =?UTF-8?q?=E2=80=94=20schema=5Fpath=20+=20rubocop=20offenses?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit static_client_query_spec: add schema_path: 'spec/support/fixtures/invoice_api.json' The client was fetching the schema from the live URL at module load time (before WebMock is active), causing 403 in CI. Using a local schema file avoids the network call and matches the pattern in webmock_client_query_spec. client_dsl_spec: nodes { } → nodes do end (Style/BlockDelimiters) query.rb: add rubocop:disable Metrics/ClassLength Class grew past 100 lines after DSL additions (spread, fragment resolution). spec_helper.rb: add rubocop:disable Lint/HandleExceptions on rescue LoadError The empty rescue is intentional — byebug unavailable on some platforms. Note: faraday_adapter_spec.rb:147 fails locally on Windows (TCP error message format differs from Linux) but passes in CI on ubuntu-latest. Pre-existing. --- lib/graphlient/query.rb | 2 +- spec/graphlient/client_dsl_spec.rb | 4 ++-- spec/graphlient/static_client_query_spec.rb | 1 + spec/spec_helper.rb | 3 ++- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/graphlient/query.rb b/lib/graphlient/query.rb index eb2fc2e..f63967c 100644 --- a/lib/graphlient/query.rb +++ b/lib/graphlient/query.rb @@ -1,5 +1,5 @@ module Graphlient - class Query + class Query # rubocop:disable Metrics/ClassLength SCALAR_TYPES = { int: 'Int', float: 'Float', diff --git a/spec/graphlient/client_dsl_spec.rb b/spec/graphlient/client_dsl_spec.rb index 2602d95..00cfbf5 100644 --- a/spec/graphlient/client_dsl_spec.rb +++ b/spec/graphlient/client_dsl_spec.rb @@ -83,10 +83,10 @@ it 'supports multiple spreads at the same level' do result = client.to_query_string do query do - nodes { + nodes do spread :FragmentA spread :FragmentB - } + end end end expect(result).to include('...FragmentA') diff --git a/spec/graphlient/static_client_query_spec.rb b/spec/graphlient/static_client_query_spec.rb index 5a47e46..84b5a43 100644 --- a/spec/graphlient/static_client_query_spec.rb +++ b/spec/graphlient/static_client_query_spec.rb @@ -5,6 +5,7 @@ module Graphlient::Client::Spec Client = Graphlient::Client.new( 'http://graph.biz/graphql', + schema_path: 'spec/support/fixtures/invoice_api.json', headers: { 'Authorization' => 'Bearer 1231' }, allow_dynamic_queries: false ) do |client| diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b04284b..4d09733 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -5,7 +5,8 @@ require 'graphlient' begin require 'byebug' if RUBY_ENGINE != 'jruby' -rescue LoadError # byebug not available on all platforms (e.g. Windows x64-mingw-ucrt) +rescue LoadError # rubocop:disable Lint/HandleExceptions + # byebug not available on all platforms (e.g. Windows x64-mingw-ucrt) end require 'rack/test' require 'webmock/rspec' From d81578e2c096ed45ea156b79474ca56ef6659ea6 Mon Sep 17 00:00:00 2001 From: rellampec <30378924+rellampec@users.noreply.github.com> Date: Wed, 10 Jun 2026 07:17:47 +1200 Subject: [PATCH 04/13] fix: make TCP error spec cross-platform (Windows/Linux) On Linux, Errno::ECONNREFUSED.new(msg).message prepends 'Connection refused - '. On Windows, the OS prepends a different string. Use a regex that matches the core error_message content rather than the exact platform-specific prefix. --- spec/graphlient/adapters/http/faraday_adapter_spec.rb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/spec/graphlient/adapters/http/faraday_adapter_spec.rb b/spec/graphlient/adapters/http/faraday_adapter_spec.rb index 05ecb19..8902129 100644 --- a/spec/graphlient/adapters/http/faraday_adapter_spec.rb +++ b/spec/graphlient/adapters/http/faraday_adapter_spec.rb @@ -145,8 +145,13 @@ end specify do - expected_error_message = "Connection refused - #{error_message}" - expect { client.schema }.to raise_error(Graphlient::Errors::ConnectionFailedError, expected_error_message) + # Use a regex so the test passes on both Linux ("Connection refused - ...") + # and Windows (where Errno::ECONNREFUSED prepends a different OS message). + # Both platforms include the core error_message string in the result. + expect { client.schema }.to raise_error( + Graphlient::Errors::ConnectionFailedError, + /#{Regexp.escape(error_message)}/ + ) end end From c0225fc1b240f1e934bfc5970b05636213354962 Mon Sep 17 00:00:00 2001 From: rellampec <30378924+rellampec@users.noreply.github.com> Date: Wed, 10 Jun 2026 09:09:25 +1200 Subject: [PATCH 05/13] chore: gitignore .vscode/ and .idea/ editor directories --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 3c4cfd5..45a54b0 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,10 @@ .byebug_history .history/ .DS_Store +.solargraph.yml +.vscode/ +.idea/ + # Used by dotenv library to load environment variables. # .env From d1ad529746dd80475b3454e7a508c20f4f8c7ee7 Mon Sep 17 00:00:00 2001 From: rellampec <30378924+rellampec@users.noreply.github.com> Date: Wed, 10 Jun 2026 10:55:59 +1200 Subject: [PATCH 06/13] chore: untrack CLAUDE.md + add to .gitignore AI agent instructions are local-only and not relevant to the upstream repo. CLAUDE.md is removed from git tracking but kept in the working directory. Added to .gitignore so future sessions don't accidentally commit it. --- .gitignore | 3 +++ CLAUDE.md | 68 ------------------------------------------------------ 2 files changed, 3 insertions(+), 68 deletions(-) delete mode 100644 CLAUDE.md diff --git a/.gitignore b/.gitignore index 45a54b0..49b7df3 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,6 @@ Gemfile.lock # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: .rvmrc + +# AI agent instructions — local only, not for the upstream repo +CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 80f3a49..0000000 --- a/CLAUDE.md +++ /dev/null @@ -1,68 +0,0 @@ -# CLAUDE.md — graphlient (EcoPortal fork) - -AI agent instructions for this repository. - -**Cross-cutting architecture context lives in `ecoportal-api-graphql` — see its `CLAUDE.md` and `.claude/` folder for the full dependency map, project history, and shared skills.** - ---- - -## Repository Role - -This is **EcoPortal's fork** of `graphlient` — a friendly Ruby client wrapper around `graphql-client`. `ecoportal-api-graphql` depends on this fork; `Common::GraphQL::Client` inherits from `Graphlient::Client`. - -**Position in chain:** -``` -graphql-client (our fork) - ↓ -graphlient ← THIS REPO (our fork) - ↓ -ecoportal-api-graphql -``` - -**Our fork:** https://github.com/rellampec/graphlient.git -**Upstream:** https://github.com/ashkan18/graphlient.git - ---- - -## Fork Policy - -- Changes made here are **not automatically contributed upstream**. If a fix is general enough to benefit the upstream project, discuss with the developer before opening a PR upstream. -- When pulling upstream changes, check for conflicts with any local modifications first. -- Keep a note in `CHANGELOG.md` (or a fork-specific section) for any changes that diverge from upstream. - ---- - -## Key Folder Layout - -``` -lib/graphlient/ - client.rb Main Graphlient::Client class - adapters/http/ HTTP adapters — faraday_adapter, http_adapter - errors/ Error hierarchy (client, server, execution, timeout, etc.) - extensions/query.rb Query DSL extension - query.rb Query builder - schema.rb Schema introspection and caching -``` - ---- - -## Namespace - -`Graphlient::` — single top-level namespace. - ---- - -## Key Concerns - -- `Graphlient::Client` is the class `ecoportal-api-graphql`'s `Common::GraphQL::Client` inherits from. Its constructor signature, `#execute`, and error classes are the primary integration surface. -- `no_schema:` option (added or expected by our usage) — schema introspection is disabled in EcoPortal's GraphQL client. Verify this is handled correctly after any changes to `schema.rb`. -- Error classes are caught and re-raised by `ecoportal-api-graphql` — changes to the error hierarchy may break upstream error handling. - ---- - -## Running Tests - -```bash -bundle install -bundle exec rspec -``` From 1b6b0000ed31a764b7497da9f01187241b18d629 Mon Sep 17 00:00:00 2001 From: rellampec <30378924+rellampec@users.noreply.github.com> Date: Wed, 10 Jun 2026 11:06:04 +1200 Subject: [PATCH 07/13] fix: use WebMock to_rack for Ruby 3.1 CI compatibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause: on Ruby 3.1, WebMock's Faraday middleware intercepts requests before they reach Faraday::Adapter::Rack, returning 403 for any URL without a stub. This caused 25 CI failures on that Ruby version. spec/support/context/dummy_client.rb: Replace Faraday::Adapter::Rack with stub_request.to_rack(app). WebMock routes both schema introspection and query execution through the Sinatra dummy app at the WebMock level (before Faraday dispatch). Removed schema_path: so graphql-client gets the full live schema (including test fields: executionErrorInvoice, partialSuccess etc.). spec/graphlient/static_client_query_spec.rb: Same to_rack approach for execution tests (schema_path kept here since the module constants are created at file-load time, before any before block). Removed Faraday::Adapter::Rack from the static client constructor. spec/graphlient/client_schema_spec.rb: Use include instead of eq for error message — Faraday 2.x appends the URL to the message; include matches on both old and new formats. 73 examples, 0 failures --- spec/graphlient/client_schema_spec.rb | 2 +- spec/graphlient/static_client_query_spec.rb | 24 +++++++++++++-------- spec/support/context/dummy_client.rb | 21 ++++++++++++------ 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/spec/graphlient/client_schema_spec.rb b/spec/graphlient/client_schema_spec.rb index 342b9c2..cc84734 100644 --- a/spec/graphlient/client_schema_spec.rb +++ b/spec/graphlient/client_schema_spec.rb @@ -30,7 +30,7 @@ expect do client.schema end.to raise_error Graphlient::Errors::FaradayServerError do |e| - expect(e.to_s).to eq 'the server responded with status 500' + expect(e.to_s).to include('the server responded with status 500') expect(e.status_code).to eq 500 expect(e.response['errors'].size).to eq 1 expect(e.response['errors'].first['message']).to eq 'test message' diff --git a/spec/graphlient/static_client_query_spec.rb b/spec/graphlient/static_client_query_spec.rb index 84b5a43..c49eaa3 100644 --- a/spec/graphlient/static_client_query_spec.rb +++ b/spec/graphlient/static_client_query_spec.rb @@ -3,18 +3,15 @@ describe Graphlient::Client do describe 'parse and execute' do module Graphlient::Client::Spec + # schema_path avoids an HTTP schema fetch at file-load time. + # No Rack adapter needed here — parsing is local; execution is handled + # by the stub_request below. Client = Graphlient::Client.new( 'http://graph.biz/graphql', schema_path: 'spec/support/fixtures/invoice_api.json', headers: { 'Authorization' => 'Bearer 1231' }, allow_dynamic_queries: false - ) do |client| - client.http do |h| - h.connection do |c| - c.adapter Faraday::Adapter::Rack, Sinatra::Application - end - end - end + ) StringQuery = Client.parse <<~GRAPHQL query($some_id: Int) { @@ -35,6 +32,15 @@ module Graphlient::Client::Spec end end + # Route execution requests through the Sinatra dummy app via WebMock. + # to_rack works reliably across Ruby/gem versions; Faraday::Adapter::Rack + # can be intercepted before dispatch on some Ruby 3.x + WebMock combinations. + before do + stub_request(:post, 'http://graph.biz/graphql') + .with(headers: { 'Authorization' => 'Bearer 1231' }) + .to_rack(Sinatra::Application) + end + it 'defaults allow_dynamic_queries to false' do expect(Graphlient::Client::Spec::Client.send(:client).allow_dynamic_queries).to be false end @@ -51,7 +57,7 @@ module Graphlient::Client::Spec context 'with both string- and block-based queries' do it 'gets identical results parsing equivalent string- and block-based queries' do - block_response = Graphlient::Client::Spec::Client.execute(Graphlient::Client::Spec::BlockQuery, some_id: 42) + block_response = Graphlient::Client::Spec::Client.execute(Graphlient::Client::Spec::BlockQuery, some_id: 42) string_response = Graphlient::Client::Spec::Client.execute(Graphlient::Client::Spec::StringQuery, some_id: 42) expect(string_response.to_h).to eq block_response.to_h end @@ -60,7 +66,7 @@ module Graphlient::Client::Spec context 'executing a query' do it 'succeeds with expected feeInCents' do response = Graphlient::Client::Spec::Client.execute(Graphlient::Client::Spec::BlockQuery, some_id: 42) - invoice = response.data.invoice + invoice = response.data.invoice expect(invoice.id).to eq '42' expect(invoice.fee_in_cents).to eq 20_000 end diff --git a/spec/support/context/dummy_client.rb b/spec/support/context/dummy_client.rb index 4101bff..1298e10 100644 --- a/spec/support/context/dummy_client.rb +++ b/spec/support/context/dummy_client.rb @@ -14,13 +14,20 @@ def app } end + # Route all requests through the Sinatra dummy app via WebMock's to_rack adapter. + # This is more reliable than configuring Faraday::Adapter::Rack directly because + # WebMock intercepts Faraday requests before they reach the adapter layer on some + # Ruby/gem version combinations — to_rack routes at the WebMock level instead. + before do + stub_request(:post, endpoint) + .with(headers: { 'Authorization' => 'Bearer 1231' }) + .to_rack(app) + end + + # No schema_path — the to_rack stub above routes schema introspection to the + # Sinatra app as well, so graphql-client gets the full live schema including + # test-only fields (executionErrorInvoice, partialSuccess etc.). let(:client) do - Graphlient::Client.new(endpoint, headers: headers) do |client| - client.http do |h| - h.connection do |c| - c.adapter Faraday::Adapter::Rack, app - end - end - end + Graphlient::Client.new(endpoint, headers: headers) end end From ad0f14c4485914be683d7ee9b29485af790b5200 Mon Sep 17 00:00:00 2001 From: rellampec <30378924+rellampec@users.noreply.github.com> Date: Wed, 10 Jun 2026 20:50:37 +1200 Subject: [PATCH 08/13] fix: rubocop AsciiComments + Ruby 3.4 mutex_m + add 3.4 to CI matrix spec/support/context/dummy_client.rb: spec/graphlient/static_client_query_spec.rb: Replace em-dashes (--) with ASCII semicolons/colons in comments. Style/AsciiComments cop requires pure ASCII. Gemfile: Add mutex_m gem -- activesupport 5.x requires mutex_m which was removed from Ruby's standard library in Ruby 3.4. Adding it explicitly silences the warning and fixes the LoadError on Ruby 3.4. .github/workflows/ci.yml: Add Ruby 3.4 to the required CI matrix (was previously only in ruby-head which is allowed to fail). Ruby 3.4 is now released and should be tested. --- .github/workflows/ci.yml | 1 + Gemfile | 1 + spec/graphlient/static_client_query_spec.rb | 2 +- spec/support/context/dummy_client.rb | 4 ++-- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9d89ab2..f690114 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,6 +16,7 @@ jobs: - { ruby: 3.1 } - { ruby: 3.2 } - { ruby: 3.3 } + - { ruby: 3.4 } - { ruby: "ruby-head", ignore: true } - { ruby: "jruby-9.4.8.0", ignore: true } - { ruby: "jruby-head", ignore: true } diff --git a/Gemfile b/Gemfile index adf946b..fde89be 100644 --- a/Gemfile +++ b/Gemfile @@ -6,6 +6,7 @@ gem 'rake' group :development, :test do gem 'activesupport', '< 6' + gem 'mutex_m' # activesupport 5.x depends on mutex_m, removed from stdlib in Ruby 3.4 end group :development do diff --git a/spec/graphlient/static_client_query_spec.rb b/spec/graphlient/static_client_query_spec.rb index c49eaa3..b3b560f 100644 --- a/spec/graphlient/static_client_query_spec.rb +++ b/spec/graphlient/static_client_query_spec.rb @@ -4,7 +4,7 @@ describe 'parse and execute' do module Graphlient::Client::Spec # schema_path avoids an HTTP schema fetch at file-load time. - # No Rack adapter needed here — parsing is local; execution is handled + # No Rack adapter needed here; parsing is local and execution is handled # by the stub_request below. Client = Graphlient::Client.new( 'http://graph.biz/graphql', diff --git a/spec/support/context/dummy_client.rb b/spec/support/context/dummy_client.rb index 1298e10..7433dbf 100644 --- a/spec/support/context/dummy_client.rb +++ b/spec/support/context/dummy_client.rb @@ -17,14 +17,14 @@ def app # Route all requests through the Sinatra dummy app via WebMock's to_rack adapter. # This is more reliable than configuring Faraday::Adapter::Rack directly because # WebMock intercepts Faraday requests before they reach the adapter layer on some - # Ruby/gem version combinations — to_rack routes at the WebMock level instead. + # Ruby/gem version combinations; to_rack routes at the WebMock level instead. before do stub_request(:post, endpoint) .with(headers: { 'Authorization' => 'Bearer 1231' }) .to_rack(app) end - # No schema_path — the to_rack stub above routes schema introspection to the + # No schema_path: the to_rack stub above routes schema introspection to the # Sinatra app as well, so graphql-client gets the full live schema including # test-only fields (executionErrorInvoice, partialSuccess etc.). let(:client) do From 5712a3ff76b44a087a4e3854cb4868b7101e9e7b Mon Sep 17 00:00:00 2001 From: rellampec <30378924+rellampec@users.noreply.github.com> Date: Wed, 10 Jun 2026 21:59:53 +1200 Subject: [PATCH 09/13] docs: document to_query_string and spread in README New sections: 'Build Query Strings without Validation' -- explains the serialization-only path (no schema load, no graphql-client validation, no HTTP), shows the basic usage, clarifies when the string can be fed back to client.execute (fragment-free queries only), explains why fragment spreads cannot go back through the gem (graphql-client's constant-based fragment model), and shows how to_query_string is the escape hatch for replacing graphql-client with your own HTTP transport entirely. 'Fragment Spreads' -- documents Query#spread as the modern alternative to the triple-underscore convention; covers basic usage and multiple spreads. --- README.md | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/README.md b/README.md index 9789209..143ac8d 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,10 @@ A friendlier Ruby client for consuming GraphQL-based APIs. Built on top of your - [Error Handling](#error-handling) - [Executing Parameterized Queries and Mutations](#executing-parameterized-queries-and-mutations) - [Parse and Execute Queries Separately](#parse-and-execute-queries-separately) + - [Build Query Strings without Validation](#build-query-strings-without-validation) - [Dynamic vs. Static Queries](#dynamic-vs-static-queries) - [Generate Queries with Graphlient::Query](#generate-queries-with-graphlientquery) + - [Fragment Spreads](#fragment-spreads) - [Create API Client Classes with Graphlient::Extension::Query](#create-api-client-classes-with-graphlientextensionquery) - [Swapping the HTTP Stack](#swapping-the-http-stack) - [Testing with Graphlient and RSpec](#testing-with-graphlient-and-rspec) @@ -278,6 +280,53 @@ GRAPHQL client.execute query, ids: [42] ``` +### Build Query Strings without Validation + +`Client#to_query_string` serializes a DSL block into a GraphQL query string and +returns it as a plain `String`. It uses the same DSL serializer (`Graphlient::Query`) +that powers `client.query` and `client.parse`, but it stops there — no schema is +loaded, no graphql-client validation runs, no HTTP call is made. + +```ruby +client = Graphlient::Client.new('https://example.com/graphql', + headers: { 'Authorization' => 'Bearer 123' } +) + +query_str = client.to_query_string do + query(id: :int) do + invoice(id: :id) do + id + feeInCents + end + end +end + +# => "query($id: Int){\n invoice(id: $id){\n id\n feeInCents\n }\n }" +``` + +For fragment-free queries the string can be fed back to `client.execute`: + +```ruby +client.execute(query_str, id: 42) +``` + +Queries containing fragment spreads (`spread :Name` → `...Name`) cannot go back +through the gem — graphql-client requires fragments to be pre-registered module +constants, not named strings. Pass those directly to your own HTTP client instead. + +This is also the escape hatch if you want to replace the graphql-client dependency +entirely. `to_query_string` gives you a standard GraphQL document — from there you +own the transport: Faraday, Net::HTTP, anything else. You get full control over +headers, retries, connection pooling, and middleware without any graphql-client +overhead. + +```ruby +conn = Faraday.new('https://example.com/graphql', + headers: { 'Authorization' => 'Bearer 123', 'Content-Type' => 'application/json' } +) +response = conn.post('/', { query: query_str, variables: { id: 42 } }.to_json) +``` + ### Dynamic vs. Static Queries Graphlient uses [graphql-client](https://github.com/github-community-projects/graphql-client), which [recommends](https://github.com/github-community-projects/graphql-client/blob/master/guides/dynamic-query-error.md) building queries as static module members along with dynamic variables during execution. This can be accomplished with graphlient the same way. @@ -397,6 +446,40 @@ invoice.fee_in_cents # 20000 ``` +### Fragment Spreads + +Use `spread` to emit a named fragment spread (`...FragmentName`) inside a DSL block. +This is a cleaner alternative to the `___Const__Name` triple-underscore convention. + +```ruby +query_str = client.to_query_string do + query do + invoice(id: 10) do + id + spread :InvoiceFields # → ...InvoiceFields + end + end +end +``` + +Multiple spreads at the same level are supported: + +```ruby +client.to_query_string do + query do + invoice(id: 10) do + spread :CoreFields + spread :AuditFields + end + end +end +``` + +`spread` works in both `to_query_string` and the standard `parse`/`query` execution +paths. The caller is responsible for appending the fragment definition to the query +string before sending it to the server, or for using a framework layer that handles +fragment assembly automatically. + ### Create API Client Classes with Graphlient::Extension::Query You can include `Graphlient::Extensions::Query` in your class. This will add a new `method_missing` method to your context which will be used to generate GraphQL queries. From 7e938a2697d572e2ed70fc896b5fe4917d73a890 Mon Sep 17 00:00:00 2001 From: rellampec <30378924+rellampec@users.noreply.github.com> Date: Wed, 10 Jun 2026 22:14:10 +1200 Subject: [PATCH 10/13] docs: fix CHANGELOG continuation line indentation (4 spaces) --- CHANGELOG.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 050fbd4..d619fc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,13 +3,13 @@ * [#113](https://github.com/ashkan18/graphlient/pull/113): Fix CI builds - [@yuki24](https://github.com/yuki24). * [#112](https://github.com/ashkan18/graphlient/pull/112): Update graphql-client github repository links in README - [@th1988](https://github.com/th1988). * `Client#to_query_string(**kargs, &block)`: builds the full GraphQL query document from the - DSL block and returns a `String` without touching the schema or Faraday HTTP adapter. - Enables DSL-only mode where HTTP dispatch is handled externally - [@rellampec](https://github.com/rellampec). + DSL block and returns a `String` without touching the schema or Faraday HTTP adapter. + Enables DSL-only mode where HTTP dispatch is handled externally - [@rellampec](https://github.com/rellampec). * `Query#spread(fragment_name)`: emits `...FragmentName` into the query string as a named - fragment spread. Alternative to the `___Const` convention for use cases where - `graphql-client` constant parsing is not available - [@rellampec](https://github.com/rellampec). + fragment spread. Alternative to the `___Const` convention for use cases where + `graphql-client` constant parsing is not available - [@rellampec](https://github.com/rellampec). * `spec/spec_helper.rb`: rescue `LoadError` on `byebug` require so specs run on platforms - where byebug is not installable (e.g. Windows with Ruby 3.2) - [@rellampec](https://github.com/rellampec). + where byebug is not installable (e.g. Windows with Ruby 3.2) - [@rellampec](https://github.com/rellampec). ### 0.8.0 (2024/01/06) * [#110](https://github.com/ashkan18/graphlient/pull/110): Ensure correct Faraday JSON response body parsing with invalid response header - [@taylorthurlow](https://github.com/taylorthurlow). From 112a99d5688441000e4ab750befc726229e1a14a Mon Sep 17 00:00:00 2001 From: rellampec <30378924+rellampec@users.noreply.github.com> Date: Wed, 10 Jun 2026 22:18:23 +1200 Subject: [PATCH 11/13] docs: add PR #115 reference to CHANGELOG entries --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d619fc0..6377bfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,13 +2,13 @@ * Your contribution here. * [#113](https://github.com/ashkan18/graphlient/pull/113): Fix CI builds - [@yuki24](https://github.com/yuki24). * [#112](https://github.com/ashkan18/graphlient/pull/112): Update graphql-client github repository links in README - [@th1988](https://github.com/th1988). -* `Client#to_query_string(**kargs, &block)`: builds the full GraphQL query document from the +* [#115](https://github.com/ashkan18/graphlient/pull/115): `Client#to_query_string(**kargs, &block)`: builds the full GraphQL query document from the DSL block and returns a `String` without touching the schema or Faraday HTTP adapter. Enables DSL-only mode where HTTP dispatch is handled externally - [@rellampec](https://github.com/rellampec). -* `Query#spread(fragment_name)`: emits `...FragmentName` into the query string as a named +* [#115](https://github.com/ashkan18/graphlient/pull/115): `Query#spread(fragment_name)`: emits `...FragmentName` into the query string as a named fragment spread. Alternative to the `___Const` convention for use cases where `graphql-client` constant parsing is not available - [@rellampec](https://github.com/rellampec). -* `spec/spec_helper.rb`: rescue `LoadError` on `byebug` require so specs run on platforms +* [#115](https://github.com/ashkan18/graphlient/pull/115): `spec/spec_helper.rb`: rescue `LoadError` on `byebug` require so specs run on platforms where byebug is not installable (e.g. Windows with Ruby 3.2) - [@rellampec](https://github.com/rellampec). ### 0.8.0 (2024/01/06) From 1bb7e2634e27636f98313a3134e1c9335262cf5b Mon Sep 17 00:00:00 2001 From: rellampec <30378924+rellampec@users.noreply.github.com> Date: Thu, 11 Jun 2026 22:56:00 +1200 Subject: [PATCH 12/13] chore: replace inline rubocop:disable with auto-gen-config, bump rubocop to ~> 1.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removed two inline disable comments (Metrics/ClassLength on Query, Lint/HandleExceptions in spec_helper) in favour of the rubocop_todo.yml approach suggested by upstream maintainer. Bumped rubocop dev dependency from pinned 0.56.0 to ~> 1.0 (required for Ruby 3.2 compatibility — Psych.safe_load signature changed). TargetRubyVersion kept at 2.3 to reflect the gem's minimum supported Ruby. Ran rubocop -a (11 auto-corrections) then --auto-gen-config to regenerate .rubocop_todo.yml with current cop names (Metrics/LineLength renamed to Layout/LineLength, Style/MethodMissingSuper removed, etc.). --- .rubocop.yml | 10 ++- .rubocop_todo.yml | 68 +++++++++++++------- Dangerfile | 4 +- Gemfile | 2 +- lib/graphlient/adapters/http/http_adapter.rb | 1 + lib/graphlient/client.rb | 3 +- lib/graphlient/errors/error.rb | 1 + lib/graphlient/errors/graphql_error.rb | 1 + lib/graphlient/query.rb | 3 +- lib/graphlient/schema.rb | 1 + spec/spec_helper.rb | 2 +- spec/support/dummy_schema.rb | 2 +- spec/support/queries/query.rb | 3 +- 13 files changed, 64 insertions(+), 37 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 81a370a..6116fdc 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,8 +1,8 @@ +inherit_from: .rubocop_todo.yml + AllCops: TargetRubyVersion: 2.3 - -Lint/SplatKeywordArguments: - Enabled: false + NewCops: disable Style/FrozenStringLiteralComment: Enabled: false @@ -13,7 +13,7 @@ Style/Documentation: Style/SafeNavigation: Enabled: false -Metrics/LineLength: +Layout/LineLength: Enabled: false Metrics/MethodLength: @@ -24,5 +24,3 @@ Metrics/BlockLength: Metrics/AbcSize: Enabled: false - -inherit_from: .rubocop_todo.yml diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 530f19b..e75f044 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,48 +1,72 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2018-08-14 17:57:21 -0400 using RuboCop version 0.56.0. +# on 2026-06-11 10:55:02 UTC using RuboCop version 1.87.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new # versions of RuboCop, may require this file to be generated again. # Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods. +Gemspec/RequiredRubyVersion: + Exclude: + - 'graphlient.gemspec' + +# Offense count: 1 +# Configuration parameters: AllowedMethods. +# AllowedMethods: enums +Lint/ConstantDefinitionInBlock: + Exclude: + - 'spec/graphlient/static_client_query_spec.rb' + +# Offense count: 1 +Lint/MixedRegexpCaptureTypes: + Exclude: + - 'lib/graphlient/query.rb' + +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +Lint/NonDeterministicRequireOrder: + Exclude: + - 'spec/spec_helper.rb' + +# Offense count: 1 +# This cop supports safe autocorrection (--autocorrect). +# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods, NotImplementedExceptions. +# NotImplementedExceptions: NotImplementedError Lint/UnusedMethodArgument: Exclude: - 'lib/graphlient/adapters/http/http_adapter.rb' -# Offense count: 2 -Metrics/CyclomaticComplexity: - Max: 8 +# Offense count: 1 +# Configuration parameters: CountComments, CountAsOne. +Metrics/ClassLength: + Max: 104 # Offense count: 1 -Metrics/PerceivedComplexity: - Max: 8 +# Configuration parameters: AllowedMethods, AllowedPatterns. +Metrics/CyclomaticComplexity: + Max: 9 # Offense count: 1 -# Cop supports --auto-correct. -# Configuration parameters: AutoCorrect, EnforcedStyle. +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle, EnforcedStyleForClasses, EnforcedStyleForModules. # SupportedStyles: nested, compact +# SupportedStylesForClasses: ~, nested, compact +# SupportedStylesForModules: ~, nested, compact Style/ClassAndModuleChildren: Exclude: - 'spec/graphlient/static_client_query_spec.rb' -# Offense count: 2 -Style/MethodMissingSuper: - Exclude: - - 'lib/graphlient/extensions/query.rb' - - 'lib/graphlient/query.rb' - -# Offense count: 5 +# Offense count: 8 Style/MultilineBlockChain: Exclude: - 'spec/graphlient/client_query_spec.rb' - 'spec/graphlient/client_schema_spec.rb' -# Offense count: 39 -# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. -# URISchemes: http, https -Metrics/LineLength: - Max: 181 +# Offense count: 1 +# This cop supports unsafe autocorrection (--autocorrect-all). +# Configuration parameters: EnforcedStyle. +# SupportedStyles: literals, strict +Style/MutableConstant: + Exclude: + - 'lib/graphlient/query.rb' diff --git a/Dangerfile b/Dangerfile index f8850d4..baaa7fa 100644 --- a/Dangerfile +++ b/Dangerfile @@ -14,9 +14,7 @@ warn("There're library changes, but not tests. That's OK as long as you're refac # -------------------------------------------------------------------------------------------------------------------- # You've made changes to specs, but no library code has changed? # -------------------------------------------------------------------------------------------------------------------- -if !has_app_changes && has_spec_changes - message('We really appreciate pull requests that demonstrate issues, even without a fix. That said, the next step is to try and fix the failing tests!', sticky: false) -end +message('We really appreciate pull requests that demonstrate issues, even without a fix. That said, the next step is to try and fix the failing tests!', sticky: false) if !has_app_changes && has_spec_changes # -------------------------------------------------------------------------------------------------------------------- # Have you updated CHANGELOG.md? diff --git a/Gemfile b/Gemfile index fde89be..748a272 100644 --- a/Gemfile +++ b/Gemfile @@ -11,7 +11,7 @@ end group :development do gem 'byebug', platform: :ruby - gem 'rubocop', '0.56.0' + gem 'rubocop', '~> 1.0' end group :test do diff --git a/lib/graphlient/adapters/http/http_adapter.rb b/lib/graphlient/adapters/http/http_adapter.rb index 15a351a..ab2b186 100644 --- a/lib/graphlient/adapters/http/http_adapter.rb +++ b/lib/graphlient/adapters/http/http_adapter.rb @@ -19,6 +19,7 @@ def execute(document:, operation_name: nil, variables: {}, context: {}) response = connection.request(request) raise Graphlient::Errors::HttpServerError, response unless response.is_a?(Net::HTTPOK) + JSON.parse(response.body) end diff --git a/lib/graphlient/client.rb b/lib/graphlient/client.rb index 8dd9b56..46da074 100644 --- a/lib/graphlient/client.rb +++ b/lib/graphlient/client.rb @@ -36,6 +36,7 @@ def execute(query, variables = nil) # see https://github.com/github-community-projects/graphql-client/pull/132 # see https://github.com/exAspArk/graphql-errors/issues/2 raise Graphlient::Errors::ExecutionError, rc if errors_in_result?(rc) + rc rescue GraphQL::Client::Error => e raise Graphlient::Errors::ClientError, e.message @@ -70,7 +71,7 @@ def raise_error_if_invalid_configuration! end def schema_path - return options[:schema_path].to_s if options[:schema_path] + options[:schema_path].to_s if options[:schema_path] end def client diff --git a/lib/graphlient/errors/error.rb b/lib/graphlient/errors/error.rb index fc93ceb..36419f9 100644 --- a/lib/graphlient/errors/error.rb +++ b/lib/graphlient/errors/error.rb @@ -2,6 +2,7 @@ module Graphlient module Errors class Error < StandardError attr_reader :inner_exception + def initialize(message, inner_exception = nil) super(message) diff --git a/lib/graphlient/errors/graphql_error.rb b/lib/graphlient/errors/graphql_error.rb index 72e7e35..7f90735 100644 --- a/lib/graphlient/errors/graphql_error.rb +++ b/lib/graphlient/errors/graphql_error.rb @@ -2,6 +2,7 @@ module Graphlient module Errors class GraphQLError < Error attr_reader :response + def initialize(response) super('the server responded with a GraphQL error') @response = response diff --git a/lib/graphlient/query.rb b/lib/graphlient/query.rb index f63967c..9c4b7bc 100644 --- a/lib/graphlient/query.rb +++ b/lib/graphlient/query.rb @@ -1,5 +1,5 @@ module Graphlient - class Query # rubocop:disable Metrics/ClassLength + class Query SCALAR_TYPES = { int: 'Int', float: 'Float', @@ -56,6 +56,7 @@ def evaluate(&block) def resolve_fragment_constant(value) return nil unless (match = value.to_s.match(FRAGMENT_DEFITION)) + raw_const = match[:const].gsub('__', '::') @context[@last_block].eval(raw_const).tap do |const| msg = "Expected constant #{raw_const} to be GraphQL::Client::FragmentDefinition. Given #{const.class}" diff --git a/lib/graphlient/schema.rb b/lib/graphlient/schema.rb index f155d93..776878e 100644 --- a/lib/graphlient/schema.rb +++ b/lib/graphlient/schema.rb @@ -20,6 +20,7 @@ def initialize(http, path) def dump! raise MissingConfigurationError, PATH_ERROR_MESSAGE unless path + GraphQL::Client.dump_schema(http, path) end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 4d09733..16d88b2 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -5,7 +5,7 @@ require 'graphlient' begin require 'byebug' if RUBY_ENGINE != 'jruby' -rescue LoadError # rubocop:disable Lint/HandleExceptions +rescue LoadError # byebug not available on all platforms (e.g. Windows x64-mingw-ucrt) end require 'rack/test' diff --git a/spec/support/dummy_schema.rb b/spec/support/dummy_schema.rb index f99b596..90c4243 100644 --- a/spec/support/dummy_schema.rb +++ b/spec/support/dummy_schema.rb @@ -1,7 +1,7 @@ require_relative 'types/invoice_type' require_relative 'queries/query' -require_relative 'types/mutation_type.rb' +require_relative 'types/mutation_type' require 'graphql/errors' diff --git a/spec/support/queries/query.rb b/spec/support/queries/query.rb index a714c8e..0f0141b 100644 --- a/spec/support/queries/query.rb +++ b/spec/support/queries/query.rb @@ -21,6 +21,7 @@ class Query < GraphQL::Schema::Object def invoice(id: nil) return nil if id.nil? + OpenStruct.new( id: id, fee_in_cents: 20_000 @@ -31,7 +32,7 @@ def not_null_invoice(*) nil end - def execution_error_invoice(id: nil, execution_errors:) + def execution_error_invoice(execution_errors:, id: nil) execution_errors.add(GraphQL::ExecutionError.new('Execution Error')) invoice(id: id) From 1e9d77b9ab7e6c7a758797adf0a265ecbcaefe38 Mon Sep 17 00:00:00 2001 From: rellampec <30378924+rellampec@users.noreply.github.com> Date: Fri, 12 Jun 2026 03:38:11 +1200 Subject: [PATCH 13/13] Update CHANGELOG.md --- CHANGELOG.md | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d210d0d..e0aef2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,14 +3,9 @@ * [#117](https://github.com/ashkan18/graphlient/pull/117): Migrate Danger to use `danger-pr-comment` reusable workflow, add Ruby 4.0 to CI, fix tests on Ruby 3.4+ and 4.0 - [@dblock](https://github.com/dblock). * [#113](https://github.com/ashkan18/graphlient/pull/113): Fix CI builds - [@yuki24](https://github.com/yuki24). * [#112](https://github.com/ashkan18/graphlient/pull/112): Update graphql-client github repository links in README - [@th1988](https://github.com/th1988). -* [#115](https://github.com/ashkan18/graphlient/pull/115): `Client#to_query_string(**kargs, &block)`: builds the full GraphQL query document from the - DSL block and returns a `String` without touching the schema or Faraday HTTP adapter. - Enables DSL-only mode where HTTP dispatch is handled externally - [@rellampec](https://github.com/rellampec). -* [#115](https://github.com/ashkan18/graphlient/pull/115): `Query#spread(fragment_name)`: emits `...FragmentName` into the query string as a named - fragment spread. Alternative to the `___Const` convention for use cases where - `graphql-client` constant parsing is not available - [@rellampec](https://github.com/rellampec). -* [#115](https://github.com/ashkan18/graphlient/pull/115): `spec/spec_helper.rb`: rescue `LoadError` on `byebug` require so specs run on platforms - where byebug is not installable (e.g. Windows with Ruby 3.2) - [@rellampec](https://github.com/rellampec). +* [#115](https://github.com/ashkan18/graphlient/pull/115): `Client#to_query_string(**kargs, &block)`: builds the full GraphQL query document from the DSL block and returns a `String` without touching the schema or Faraday HTTP adapter. Enables DSL-only mode where HTTP dispatch is handled externally - [@rellampec](https://github.com/rellampec). +* [#115](https://github.com/ashkan18/graphlient/pull/115): `Query#spread(fragment_name)`: emits `...FragmentName` into the query string as a named fragment spread. Alternative to the `___Const` convention for use cases where `graphql-client` constant parsing is not available - [@rellampec](https://github.com/rellampec). +* [#115](https://github.com/ashkan18/graphlient/pull/115): `spec/spec_helper.rb`: rescue `LoadError` on `byebug` require so specs run on platforms where byebug is not installable (e.g. Windows with Ruby 3.2) - [@rellampec](https://github.com/rellampec). ### 0.8.0 (2024/01/06) * [#110](https://github.com/ashkan18/graphlient/pull/110): Ensure correct Faraday JSON response body parsing with invalid response header - [@taylorthurlow](https://github.com/taylorthurlow).