The macros a client module gets from use TypedGql.
defgql/2 and defgqlp/2 define a query function from a GraphQL document,
and deffragment/1 registers a fragment those documents can spread. All
three run at compile time: the document is parsed, validated against the
loaded schema, and lowered into embedded schemas for its result and its
variables, so a query the schema rejects fails the build rather than a call.
~GQL does none of that. It marks a string as GraphQL so mix format can
format it and returns that string unchanged; the macro it is passed to is
what compiles it.
Summary
Functions
Defines a reusable named GraphQL fragment.
Defines a public GraphQL query function.
Defines a private GraphQL query function.
A sigil for writing GraphQL query strings that can be formatted by mix format.
Functions
Defines a reusable named GraphQL fragment.
At compile time, parses and validates the fragment against the schema,
then registers it in the module for use by defgql/defgqlp. When a
query uses ...FragmentName, the fragment definition is automatically
appended to the query string sent to the server.
The fragment name is inferred from the GraphQL definition itself
(fragment UserFields on User { ... }), so no separate Elixir name is
required.
Fragments are resolved lexically: a defgql sees only the fragments
defined before it in the module body. If the same fragment name is
defined multiple times before a defgql, the latest definition wins.
The same rule applies inside a fragment body: it may only spread
fragments defined above it, and spreading one defined later is a
compile error.
The ordering restriction comes from the macro model, not from GraphQL —
the spec allows a spread to reference a fragment defined later in the
same document. Each deffragment compiles as it is expanded, when later
definitions do not exist yet, and lexical order is also what gives the
redefinition rule above its meaning: with forward references, a spread
written before a redefinition would have no defined answer for which
version it names. Within a single query string the restriction does not
apply — a fragment defined next to the operation may be spread before or
after its definition.
The generated module is an embedded schema for an object type condition,
and for an interface whose selections are shared by every member. A
condition that resolves to per-member selections instead yields the
TypedGql.Types.Union parameterized type at Fragments.Name.Union —
not a struct — with the per-member embedded schemas at
Fragments.Name.MemberType.
Examples
deffragment ~GQL"""
fragment UserFields on User {
name
email
}
"""
defgql :get_user, ~GQL"""
query GetUser($id: ID!) {
user(id: $id) {
...UserFields
}
}
"""
Defines a public GraphQL query function.
At compile time, parses and validates the query, generates typed
response schemas, and defines a function that calls TypedGql.execute/3.
The query string may define its own fragments next to the operation. Such
a definition shadows a deffragment of the same name: it is the one the
server sees, and the registered source is not appended. Every fragment the
string defines must also be spread by the operation — an unused definition
is transmitted as written and the server rejects the document.
Examples
defgql :get_user, "query($id: ID!) { user(id: $id) { name } }"
# Generates: def get_user(variables, opts \\ [])
defgql :current_user, "query { currentUser { name email } }"
# Generates: def current_user(opts \\ [])
Defines a private GraphQL query function.
Same as defgql/2 but generates a defp instead of def.
A sigil for writing GraphQL query strings that can be formatted by mix format.
Returns the query as a plain string — use it with defgql/defgqlp.
Does not support interpolation (uppercase sigil convention).
To enable formatting, add TypedGql.Formatter to your .formatter.exs plugins.
Examples
defgql :get_user, ~GQL"""
query GetUser($id: ID!) {
user(id: $id) {
name
email
}
}
"""