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

Link to this macro

authenticated()

View Source (macro)

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 Reviews.

Link to this macro

inaccessible()

View Source (macro)

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
}
Link to this macro

interface_object()

View Source (macro)

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!
}
Link to this macro

key_fields(fields)

View Source (macro)

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")
}
Link to this macro

list_size(opts)

View Source (macro)

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)
}
Link to this macro

override_from(subgraph, opts \\ [])

View Source (macro)

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)")
}
Link to this macro

policy(policies)

View Source (macro)

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"]])
}
Link to this macro

provides_fields(fields)

View Source (macro)

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.

Link to this macro

requires_fields(fields)

View Source (macro)

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.

Link to this macro

requires_scopes(scopes)

View Source (macro)

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

}

Adds the @shareable directive to the type to indicate that a field can be resolved by multiple subgraphs.

example

Example

object :user do
  key_fields("id")
  shareable()
  field :id, non_null(:id)
end

sdl-output

SDL Output

type User @key(fields: "id") @shareable {
  id: ID!
}

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")
}