diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..36a0a059 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,36 @@ +# Changelog + +All notable changes to this project are documented in this file. + +This file was introduced after the 0.26.0 release; entries for earlier versions are +reconstructed from the merged pull requests and release tags and may be incomplete. + +## Unreleased + +* [#60](https://github.com/github-community-projects/graphql-client/pull/60): Allow loading the schema from an SDL definition file (`.graphql` / `.graphqls`) in addition to JSON - [@Tabby](https://github.com/Tabby). +* [#76](https://github.com/github-community-projects/graphql-client/issues/76): Document support for inline (colocated) named fragments — fragments defined in the same `parse` string as the operation, whose fields are directly accessible on the result without enforced component isolation - [@rellampec](https://github.com/rellampec). +* Your contribution here. + +## 0.26.0 (2025-05-29) + +* Maintenance release: CI workflow permissions, test fixes, and dependency updates ([#69](https://github.com/github-community-projects/graphql-client/pull/69), [#70](https://github.com/github-community-projects/graphql-client/pull/70), [#71](https://github.com/github-community-projects/graphql-client/pull/71)). +* [#66](https://github.com/github-community-projects/graphql-client/pull/66): Tidy Dependabot configuration - [@issyl0](https://github.com/issyl0). +* Dependency and GitHub Actions bumps ([#47](https://github.com/github-community-projects/graphql-client/pull/47), [#58](https://github.com/github-community-projects/graphql-client/pull/58), [#64](https://github.com/github-community-projects/graphql-client/pull/64)). + +## 0.25.0 (2024-12-12) + +* [#44](https://github.com/github-community-projects/graphql-client/pull/44): Contribution from [@ajsharma](https://github.com/ajsharma). +* Dependency and CI maintenance ([#30](https://github.com/github-community-projects/graphql-client/pull/30), [#41](https://github.com/github-community-projects/graphql-client/pull/41), [#42](https://github.com/github-community-projects/graphql-client/pull/42)). + +## 0.24.0 (2024-11-13) + +* [#43](https://github.com/github-community-projects/graphql-client/pull/43): Allow accessing the full GraphQL response - [@billybonks](https://github.com/billybonks). + +## 0.23.0 (2024-06-17) + +* [#28](https://github.com/github-community-projects/graphql-client/pull/28): Fix possible-types resolution - [@rmosolgo](https://github.com/rmosolgo). +* Dependency and CI maintenance ([#24](https://github.com/github-community-projects/graphql-client/pull/24), [#25](https://github.com/github-community-projects/graphql-client/pull/25), [#26](https://github.com/github-community-projects/graphql-client/pull/26)). + +## Earlier releases + +See the [release tags](https://github.com/github-community-projects/graphql-client/tags) for versions 0.22.0 and earlier. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..ddb058ce --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,79 @@ +# Contributing to graphql-client + +This project is the work of [many contributors](https://github.com/github-community-projects/graphql-client/graphs/contributors). +You're encouraged to submit [pull requests](https://github.com/github-community-projects/graphql-client/pulls) +and to [propose features and discuss issues](https://github.com/github-community-projects/graphql-client/issues). + +In the examples below, substitute your GitHub username for `contributor` in URLs. + +## Fork the Project + +Fork the [project on GitHub](https://github.com/github-community-projects/graphql-client) and check out your copy. + +``` +git clone https://github.com/contributor/graphql-client.git +cd graphql-client +git remote add upstream https://github.com/github-community-projects/graphql-client.git +``` + +## Bundle Install and Test + +Ensure that you can build the project and run the tests. + +``` +bundle install +bundle exec rake +``` + +The default Rake task runs the test suite **and** RuboCop. The project uses +**Minitest** (not RSpec) — keep new tests in that framework and style, alongside the +existing `test/test_*.rb` files. + +## Create a Topic Branch + +Keep your fork up to date and create a topic branch off `master` for your change. + +``` +git checkout master +git pull upstream master +git checkout -b my-feature-branch +``` + +## Write Tests + +Add Minitest coverage for any behavior you change or add. Characterization tests that +pin existing behavior are especially welcome around the parser and fragment handling. +Run the full suite and RuboCop before pushing: + +``` +bundle exec rake +``` + +## Update the CHANGELOG + +Add a line describing your change to the **Unreleased** section of `CHANGELOG.md`, +crediting yourself: + +``` +* [#123](https://github.com/github-community-projects/graphql-client/pull/123): Short description - [@contributor](https://github.com/contributor). +``` + +## Commit and Push Your Changes + +Use clear commit messages. Keep the history focused — one logical change per branch. + +``` +git commit -am "Add my feature" +git push origin my-feature-branch +``` + +## Open a Pull Request + +[Open a pull request](https://github.com/github-community-projects/graphql-client/compare) +from your topic branch against `master`. Describe the motivation and the change, and link +any related issues. + +## Be Patient + +Maintainers review on a best-effort basis. It's likely a reviewer will ask for changes — +that's a normal part of getting a contribution merged. Thanks for contributing! diff --git a/README.md b/README.md index 690e5b05..1c796c4f 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,38 @@ end `::` is invalid in regular GraphQL syntax, but `#parse` makes an initial pass on the query string and resolves all the fragment spreads with [`constantize`](http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-constantize). +#### Named fragments defined inline + +Standard GraphQL named fragment definitions can also be included directly in the same `parse` string alongside the operation that uses them. This is the simplest approach when you don't need component-isolation across Ruby modules. + +This follows the same convention as Apollo Client's [colocating fragments](https://www.apollographql.com/docs/react/data/fragments#colocating-fragments) (see Apollo's [fragments guide](https://www.apollographql.com/docs/react/data/fragments)): a fragment is defined next to the operation that consumes it, and its fields are directly accessible on the result — fragments used purely for reuse, without forcing a parent–child component hierarchy. This addresses the use case raised in [#76](https://github.com/github-community-projects/graphql-client/issues/76). + +```ruby +Queries = SWAPI::Client.parse <<-'GRAPHQL' + fragment HumanFields on Human { + name + homePlanet + } + + query HeroQuery { + luke: human(id: "1000") { + ...HumanFields + } + leia: human(id: "1003") { + ...HumanFields + } + } +GRAPHQL + +result = SWAPI::Client.query(Queries::HeroQuery) +result.data.luke.name # directly accessible — no re-wrapping needed +result.data.luke.home_planet # directly accessible +``` + +The fragment and its sub-constant (`Queries::HumanFields`) are available for re-wrapping if needed, but all fields from the inline fragment spread are directly accessible on the operation result. + +The difference from the constant style: inline named fragments are scoped to the same `parse` call and do not enforce cross-component data isolation. Use the constant style (`fragment on Type { ... }`) when you want `ImplicitlyFetchedFieldError` to guard against accidental field access across module boundaries. + ### Executing queries Pass the reference of a parsed query definition to `GraphQL::Client#query`. Data is returned back in a wrapped `GraphQL::Client::Schema::ObjectType` struct that provides Ruby-ish accessors. diff --git a/guides/implicitly-fetched-field-error.md b/guides/implicitly-fetched-field-error.md index dd99e21a..90403d70 100644 --- a/guides/implicitly-fetched-field-error.md +++ b/guides/implicitly-fetched-field-error.md @@ -85,6 +85,31 @@ user.full_name The raw flattened data will include `fullName` just like the previous example. But again, we should depend on our `UserQuery` always having `fullName` available show the subview be modified. +## When isolation does not apply + +If a fragment is defined **inline in the same `parse` string** as the operation that uses it (a standard named GraphQL fragment, not a separate Ruby constant), the fragment fields are directly accessible on the operation result — no `ImplicitlyFetchedFieldError`, no re-wrapping needed. + +```ruby +Queries = Client.parse <<-'GRAPHQL' + fragment UserDetails on User { + fullName + location + } + + query UserQuery { + user(name: "Josh") { + ...UserDetails + } + } +GRAPHQL + +result = Client.query(Queries::UserQuery) +result.data.user.full_name # works — inline fragment, no isolation enforced +result.data.user.location # works +``` + +Use this style when fragments serve code reuse within a single query document and component isolation is not a requirement. + ## See Also * [Over-fetching and under-fetching](over-under-fetching.md)