View Source Absinthe.Federation.Notation (absinthe_federation v0.7.1)
Module that includes macros for annotating a schema with federation directives.
example
Example
defmodule MyApp.MySchema.Types do
use Absinthe.Schema.Notation
+ use Absinthe.Federation.Notation
end
Link to this section Summary
Functions
The @authenticated
directive marks specific fields and types as requiring authentication.
The @context
directive defines a named context from which a field of the annotated type can be passed to a receiver of the context.
The receiver must be a field annotated with the @fromContext
directive.
The @cost
directive defines a custom weight for a schema location. For GraphOS Router, it customizes the operation cost calculation of the demand control feature.
Adds the @extends
directive to the type to indicate that the type as owned by another service.
Adds the @external
directive to the field which marks a field as owned by another service.
This allows service A to use fields from service B while also knowing at runtime the types of that field.
The @inaccessible
directive indicates that a field or type should be omitted from the gateway's API schema,
even if it's also defined in other subgraphs.
Adds the @interfaceObject
directive to the field which indicates that the
object definition serves as an abstraction of another subgraph's entity
interface. This abstraction enables a subgraph to automatically contribute
fields to all entities that implement a particular entity interface.
Adds a @key
directive to the type which indicates a combination of fields
that can be used to uniquely identify and fetch an object or interface.
This allows the type to be extended by other services.
A string rather than atom is used here to support composite keys e.g. id organization { id }
The @link
directive links definitions from an external specification to this schema.
Every Federation 2 subgraph uses the @link
directive to import the other federation-specific directives.
The @listSize
directive is used to customize the cost calculation of the demand control feature of GraphOS Router.
The @override
directive is used to indicate that the current subgraph is
taking responsibility for resolving the marked field away from the
subgraph specified in the from argument.
The @policy
directive marks fields and types as restricted based on authorization policies evaluated in a Rhai script or coprocessor.
This enables custom authorization validation beyond authentication and scopes.
Adds the @provides
directive which is used to annotate the expected returned fieldset
from a field on a base type that is guaranteed to be selectable by the gateway.
Adds the @requires
directive which is used to annotate the required input fieldset from a base type for a resolver.
It is used to develop a query plan where the required fields may not be needed by the client,
but the service may need additional information from other services.
The @requiresScopes
directive marks fields and types as restricted based on required scopes.
Adds the @shareable
directive to the type to indicate that a field can be resolved by multiple subgraphs.
The @tag
directive indicates whether to include or exclude the field/type from your contract schema.
Link to this section Functions
The @authenticated
directive marks specific fields and types as requiring authentication.
example
Example
object :secret do
field :text, :string do
authenticated()
end
end
sdl-output
SDL Output
type Secret {
text: String @authenticated
}
The @context
directive defines a named context from which a field of the annotated type can be passed to a receiver of the context.
The receiver must be a field annotated with the @fromContext
directive.
example
Example
object :user do
context("userContext")
field :id, non_null(:id)
field :name, :string
end
sdl-output
SDL Output
type User @context(name: "userContext") {
id: ID!
name: String
}
The @cost
directive defines a custom weight for a schema location. For GraphOS Router, it customizes the operation cost calculation of the demand control feature.
example
Example
object :user do
field :posts, list_of(:post) do
cost(5)
resolve &PostResolvers.list_for_user/3
end
end
sdl-output
SDL Output
type User {
posts: [Post] @cost(weight: 5)
}
Adds the @extends
directive to the type to indicate that the type as owned by another service.
example
Example
object :user do
extends()
key_fields("id")
field :id, non_null(:id)
end
sdl-output
SDL Output
type User @key(fields: "id") @extends {
id: ID!
}
Adds the @external
directive to the field which marks a field as owned by another service.
This allows service A to use fields from service B while also knowing at runtime the types of that field.
example
Example
object :user do
extends()
key_fields("email")
field :email, :string do
external()
end
field :reviews, list_of(:review)
end
sdl-output
SDL Output
# extended from the Users service
type User @key(fields: "email") @extends {
email: String @external
reviews: [Review]
}
This type extension in the Reviews service extends the User type from the Users service.
It extends it for the purpose of adding a new field called reviews, which returns a list of Review
s.
The @inaccessible
directive indicates that a field or type should be omitted from the gateway's API schema,
even if it's also defined in other subgraphs.
example
Example
object :user do
key_fields("id")
field :id, non_null(:id)
field :name, :string do
inaccessible()
end
end
sdl-output
SDL Output
type User @key(fields: "id") {
id: ID!
name: String @inaccessible
}
Adds the @interfaceObject
directive to the field which indicates that the
object definition serves as an abstraction of another subgraph's entity
interface. This abstraction enables a subgraph to automatically contribute
fields to all entities that implement a particular entity interface.
During composition, the fields of every @interfaceObject
are added both to
their corresponding interface definition and to all entity types that
implement that interface.
More information can be found on: https://www.apollographql.com/docs/federation/federated-types/interfaces
example
Example
object :media do
key_fields("id")
interface_object()
field :id, non_null(:id), do: external()
field :reviews, non_null(list_of(non_null(:review)))
end
object :review do
field :score, non_null(:integer)
end
sdl-output
SDL Output
type Media @interfaceObject @key(fields: "id") {
id: ID! @external
reviews: [Review!]!
}
type Review {
score: Int!
}
Adds a @key
directive to the type which indicates a combination of fields
that can be used to uniquely identify and fetch an object or interface.
This allows the type to be extended by other services.
A string rather than atom is used here to support composite keys e.g. id organization { id }
example
Example
object :user do
key_fields("id")
field :id, non_null(:id)
end
sdl-output
SDL Output
type User @key(fields: "id") {
id: ID!
}
The @link
directive links definitions from an external specification to this schema.
Every Federation 2 subgraph uses the @link
directive to import the other federation-specific directives.
NOTE: If you're using Absinthe v1.7.1 or later, instead of using this macro, it's preferred to use the
extend schema
method you can find in the README.
example
Example
link(url: "https://specs.apollo.dev/federation/v2.0", import: ["@key", "@tag", "@shareable"])
query do
field :me, :user
end
object :user do
key_fields("id")
shareable()
field :id, non_null(:id)
field :ssn, :string do
tag("internal")
end
end
sdl-output
SDL Output
schema @link(url: "url: https:\/\/specs.apollo.dev\/federation\/v2.0", import: ["@key", "@tag", "@shareable"])
type User @key(fields: "id") @shareable {
id: ID!
name: String @tag(name: "internal")
}
The @listSize
directive is used to customize the cost calculation of the demand control feature of GraphOS Router.
example
Example
object :post do
field :text, :string
end
object :user do
field :posts, non_null(list_of(:post)) do
list_size(
assumed_size: 10,
slicing_arguments: ["first", "last"],
sized_fields: ["postCount"],
required_one_slicing_argument: false
)
arg :first, :integer
arg :last, :integer
end
end
sdl-output
SDL Output
type User {
posts(first: Int, last: Int): [Post]! @listSize(assumedSize: 10, slicingArguments: ["first", "last"], sizedFields: ["postCount"], requiredOneSlicingArgument: false)
}
The @override
directive is used to indicate that the current subgraph is
taking responsibility for resolving the marked field away from the
subgraph specified in the from argument.
The progressive @override
feature enables the gradual, progressive deployment of a subgraph with an @override
field.
As a subgraph developer, you can customize the percentage of traffic that the overriding and overridden subgraphs each resolve for a field.
example
Example
# @override
object :user do
key_fields("id")
field :id, non_null(:id)
field :name, :string do
override_from("SubgraphA")
end
end
# progressive @override
object :user do
key_fields("id")
field :id, non_null(:id)
field :name, :string do
override_from("SubgraphA", label: "percent(10)")
end
end
sdl-output
SDL Output
# @override
type User @key(fields: "id") {
id: ID!
name: String @override(from: "SubgraphA")
}
# progressive @override
type User @key(fields: "id") {
id: ID!
name: String @override(from: "SubgraphA", label: "percent(10)")
}
The @policy
directive marks fields and types as restricted based on authorization policies evaluated in a Rhai script or coprocessor.
This enables custom authorization validation beyond authentication and scopes.
example
Example
object :user do
field :id, non_null(:id)
field :username, :string
field :email, :string
field :profile_image, :string
field :credit_card, :string do
policy([["read_credit_card"]])
end
end
sdl-output
SDL Output
type User {
id: ID!
username: String
email: String
profileImage: String
credit_card: String @policy(policies: [["read_credit_card"]])
}
Adds the @provides
directive which is used to annotate the expected returned fieldset
from a field on a base type that is guaranteed to be selectable by the gateway.
example
Example
object :review do
key_fields("id")
field :id, non_null(:id)
field :product, :product do
provides_fields("name")
end
end
object :product do
extends()
key_fields("upc")
field :upc, :string do
external()
end
field :name, :string do
external()
end
end
sdl-output
SDL Output
type Review @key(fields: "id") {
product: Product @provides(fields: "name")
}
type Product @key(fields: "upc") @extends {
upc: String @external
name: String @external
}
When fetching Review.product
from the Reviews service,
it is possible to request the name
with the expectation that the Reviews service
can provide it when going from review to product. Product.name
is an external field
on an external type which is why the local type extension of Product
and annotation of name
is required.
Adds the @requires
directive which is used to annotate the required input fieldset from a base type for a resolver.
It is used to develop a query plan where the required fields may not be needed by the client,
but the service may need additional information from other services.
example
Example
object :user do
extends()
key_fields("id")
field :id, non_null(:id) do
external()
end
field :email, :string do
external()
end
field :reviews, list_of(:review) do
requires_fields("email")
end
end
sdl-output
SDL Output
# extended from the Users service
type User @key(fields: "id") @extends {
id: ID! @external
email: String @external
reviews: [Review] @requires(fields: "email")
}
In this case, the Reviews service adds new capabilities to the User
type by providing
a list of reviews
related to a User
. In order to fetch these reviews
, the Reviews service needs
to know the email
of the User
from the Users service in order to look up the reviews
.
This means the reviews
field / resolver requires the email
field from the base User
type.
The @requiresScopes
directive marks fields and types as restricted based on required scopes.
example
Example
object :user do
field :id, non_null(:id)
field :username, :string
field :email, :string do
requires_scopes([["read:email"]])
end
field :profile_image, :string
end
sdl-output
SDL Output
type User {
id: ID!
username: String
email: String @requiresScopes(scopes: [["read:email"]])
profileImage: String
}
The @tag
directive indicates whether to include or exclude the field/type from your contract schema.
example
Example
object :user do
key_fields("id")
field :id, non_null(:id)
field :ssn, :string do
tag("internal")
end
end
sdl-output
SDL Output
type User @key(fields: "id") {
id: ID!
name: String @tag(name: "internal")
}