AbsintheProjector.Engine (AbsintheProjector v0.1.1)

Copy Markdown View Source

Turns a projected GraphQL selection set into an exact Repo.preload/2 tree.

Given a recursively normalized list of Absinthe.Blueprint.Document.Field nodes and the root Ecto schema of the field, the engine keeps only the fields that name a real association of the current schema — asking AbsintheProjector.Introspection, never a whitelist — recurses into each match using the association's related schema, and merges duplicate or aliased requests of the same association by unioning their child selections.

Association matching keys on schema_node.identifier (the schema field atom), so GraphQL aliases and repeated fields collapse to a single entry. Scalar fields, __typename, introspection nodes (schema_node == nil) and any identifier that is not an association are skipped silently. An association whose sub-selection contains no further associations is emitted as a bare atom (a leaf); otherwise it becomes a {association, children} keyword entry.

The function is pure — no process state, no database access — and looks up a schema's associations once per recursion level.

Examples

Flat selection (scalars dropped, association-less children collapse to a leaf):

# order { number status customer { name } }
project(fields, Order) #=> [:customer]

Nested selection:

# order { customer { name } items { product { supplier { name } } } }
project(fields, Order) #=> [:customer, items: [product: [:supplier]]]

Aliased duplicates merge into one entry with the union of their children:

# a: items { product }  b: items { }
project(fields, Order) #=> [items: [:product]]

A selection with no associations yields an empty, no-op tree:

# order { number status }
project(fields, Order) #=> []

Summary

Functions

Projects fields against schema, returning the nested Repo.preload/2 tree.

Functions

project(fields, schema)

@spec project([struct()], module()) :: AbsintheProjector.preload_tree()

Projects fields against schema, returning the nested Repo.preload/2 tree.

fields is a list of Absinthe.Blueprint.Document.Field nodes; schema is the root Ecto schema module. Returns [] when the selection contains no associations. Raises ArgumentError (via Introspection) when schema is not an Ecto schema module.