Module: GraphWeaver::Selection
- Includes:
- Kernel
- Included in:
- Codegen, Testing::Anonymizer, Testing::FakeClient
- Defined in:
- lib/graph_weaver/selection.rb
Overview
Shared query-selection walking — the rules Codegen, FakeClient, and the cassette Anonymizer all follow, in one place so they can't drift: how fragments flatten into selections, and when a type condition applies. Hosts set @schema and call load_operation before walking.
Instance Method Summary collapse
-
#applies?(condition, type) ⇒ Boolean
A fragment's type condition applies when it names this type exactly, or an interface/union this type belongs to (
... on Named { ... }). -
#each_field(type, selections, &block) ⇒ Object
Flatten a selection set as seen by
type, yielding (result_key, field_node) per field: plain fields yield directly; inline fragments and named spreads recurse when their type condition applies. -
#load_operation(query) ⇒ Object
Parse a query, stash its fragment definitions for the walk, and return the operation.
-
#operation_root_type(operation) ⇒ Object
The schema type an operation's selections start from.
Instance Method Details
#applies?(condition, type) ⇒ Boolean
A fragment's type condition applies when it names this type exactly,
or an interface/union this type belongs to (... on Named { ... }).
57 58 59 60 61 62 63 64 65 66 |
# File 'lib/graph_weaver/selection.rb', line 57 def applies?(condition, type) return true if condition.nil? || condition == type.graphql_name condition_type = @schema.get_type(condition) return false unless condition_type kind = condition_type.kind.name (kind == "INTERFACE" || kind == "UNION") && @schema.possible_types(condition_type).include?(type) end |
#each_field(type, selections, &block) ⇒ Object
Flatten a selection set as seen by type, yielding (result_key,
field_node) per field: plain fields yield directly; inline fragments
and named spreads recurse when their type condition applies.
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/graph_weaver/selection.rb', line 37 def each_field(type, selections, &block) selections.each do |selection| case selection when GraphQL::Language::Nodes::Field yield(selection.alias || selection.name, selection) when GraphQL::Language::Nodes::InlineFragment each_field(type, selection.selections, &block) if applies?(selection.type&.name, type) when GraphQL::Language::Nodes::FragmentSpread fragment = @fragments.fetch(selection.name) do raise ArgumentError, "unknown fragment: #{selection.name}" end each_field(type, fragment.selections, &block) if applies?(fragment.type.name, type) else raise GraphWeaver::Error, "unsupported selection: #{selection.class}" end end end |
#load_operation(query) ⇒ Object
Parse a query, stash its fragment definitions for the walk, and return the operation.
16 17 18 19 20 21 22 23 |
# File 'lib/graph_weaver/selection.rb', line 16 def load_operation(query) doc = GraphQL.parse(query) @fragments = doc.definitions .grep(GraphQL::Language::Nodes::FragmentDefinition) .to_h { |fragment| [fragment.name, fragment] } doc.definitions.grep(GraphQL::Language::Nodes::OperationDefinition).first end |
#operation_root_type(operation) ⇒ Object
The schema type an operation's selections start from.
26 27 28 29 30 31 32 |
# File 'lib/graph_weaver/selection.rb', line 26 def operation_root_type(operation) case operation&.operation_type when "query", nil then @schema.query when "mutation" then @schema.mutation else raise GraphWeaver::Error, "unsupported operation: #{operation.operation_type}" end end |