[6.x] Improve type handling in GraphQL schemas#14677
Open
lostgeek wants to merge 6 commits into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Improved GraphQL Types for Entries, Terms, and Assets
This PR tries to tackle the same issue that #14618 tried. So similarly, if you want to approach this topic in a different way, feel free to close this until v7. In any case, we will likely be patching these changes into our Statamic projects, so feel free to approach me for more feedback in the future, if you close this.
Closes #12974.
Summary
This PR introduces concrete type resolution and dynamic union types for the Entries, Terms, and Assets GraphQL fieldtypes. Instead of always returning the generic interface type (e.g.
EntryInterface,TermInterface,AssetInterface), fieldtypes now resolve to the most specific type possible based on their blueprint configuration, and dynamic union types are generated if multiple blueprints are possible (e.g.DynamicEntryUnionType).It also adds per-collection and per-taxonomy top-level queries that return typed results, so consumers can query e.g.
blogPosts { ... }of type[Entry_BlogPosts_Article]instead ofentries(collection: ["blog_posts"]) { ... }of type[EntryInterface].Both features are controlled through a new
improved_typesconfig section inconfig/graphql.php.What changed
Config —
statamic.graphql.improved_typesis now a structured array:enabled(defaulttrue, envSTATAMIC_GRAPHQL_IMPROVED_TYPES) — controls fieldtype improved type resolution.collections— list of collection handles (or'*'for all) that get dedicated typed queries.terms— list of taxonomy handles (or'*'for all) that get dedicated typed queries.Entries fieldtype — When
improved_types.enabledistrue:EntryInterface(unchanged).EntryType(e.g.Entry_BlogPosts_Article).DynamicEntryUnionTypescoped to exactly those blueprint types.[Type!](non-null items) instead of[Type].Terms fieldtype — Same logic as Entries, using
TermType/DynamicTermUnionType.Assets fieldtype — When
improved_types.enabledistrue, resolves to the concreteAssetTypefor the configured container instead ofAssetInterface. Lists use non-null items.Per-collection queries — For each collection listed in
improved_types.collections, a dedicated query is registered (e.g.blogPostsforblog_posts). The query:EntryType(single blueprint) or aDynamicEntryUnionType(multiple blueprints).entriesminuscollection.collectionsresource is also enabled.Per-taxonomy queries — Same pattern for taxonomies listed in
improved_types.terms, usingSpecificTermsQuery.New classes:
DynamicEntryUnionType— A union type composed of the concreteEntryTypes matching the fieldtype's configured collections/blueprints.DynamicTermUnionType— Same concept for taxonomy terms.SpecificEntriesQuery— Per-collection paginated query with typed results.SpecificTermsQuery— Per-taxonomy paginated query with typed results.Why
The generic interface types make it difficult for GraphQL consumers to use the returned data types without a further cleanup step, rendering the advantage of GraphQL somewhat limited. One of the most common pain points is with an Entries fieldtype that only allows a single blueprint still delivering an
EntryInterfacetype, making it difficult to use the data easily in a client application.The per-collection/taxonomy queries go further by giving each collection or taxonomy its own top-level query with properly typed results, eliminating the need to filter by
__typenameafterwards.Possible improvements
DynamicEntryUnionType_and then concatenates the blueprint handles with underscores, which can lead to very long type names such asDynamicEntryUnionType_Entry_BlogPosts_Article_Entry_BlogPosts_News.