Declaratively Build a Graph of Graphs Using @materializer

Declaratively build a graph of graphs using the @materializer directive

In StepZen, your GraphQL API against multiple backends is built by:

  1. First building subgraphs against each backend. You can do that in one of two ways:

    • Let us introspect the backend using stepzen import, or

    • Build your own subgraph using @rest, @dbquery and @graphql directives.

  2. Combining these subgraphs using @materializer directive.

In this section, we will focus on step 2 - combining the subgraphs.

Combine subgraphs using the @materializer directive

Let us say that you have built up two subgraphs--one for Customer (against a REST backend), and another for Order against a MySQL database. At the simplest, your schema might look like:

  1. customer.graphql:
type Customer {
  name: String
  id: ID
  email: String
type Query {
  customer(id: ID): Customer @rest(endpoint: "api.acme/com/customers/$id")

  customerByEmail(email: String): Customer
    @rest(endpoint: "$email")
  1. order.graphql:
type Order {
  createOn: Date
  amount: Float
type Query {
  orders(customerId: ID): [Order] @dbquery(type: "mysql", table: "orders")

For building the supergraph, it does not matter how each subgraph is built. They are stitched together at the schema level, not at the implementation level. The stitching syntax is simple: data from one subgraph is used to call a query/mutation in the same subgraph, or a different subgraph, through a series of transformations.

At its simplest, this might look like: a new file customer-orders.graphql:

extend type Customer {
  orders: [Order]
  @materializer (query: "orders", arguments: [{name: "customerId", field: "id"}]

Let us examine what the above is:

  • The extend clause is just a neat way of extending a subgraph with new fields. In this case, we are adding a new field called orders to type Customer. We can achieve the same purpose by editing the customer.graphql file. but in general, using extend keeps the concerns of the supergraph separate from those of the subgraphs.

  • The field orders must be of the type returned by the query (or mutation) references in the @materializer clause. This enables compile time checking.

  • The @materializer clause calls a query or a mutation. It has two arguments.

    • the name of the query or mutation.
    • list of argument mappings.

      Basically, you are telling StepZen how to take the fields in the calling subgraph, and convert them into the arguments of the query or mutation. So here, the query: "orders" gets the customerId argument from the field id of Customer. If the field to argument mapping is an equality, then you can skip that argument mapping.

As you can see in the above, how orders is implemented is irrelevant for the stitching. That is the beauty of the StepZen graph of subgraphs concepts. You can stitch a layer above.

Sometimes, you have to do a series of transformations to massage the data from the first subgraph into the right arguments for the second subgraph. For example, to connect customers to weather, you might have to take the field address and convert it to lat,lon before calling weather. You can do that easily in StepZen using the @sequence construct:

extend type Customer {
  weather: Weather @materializer(query: "customerWeather")
type Coord {
  lat: Float
  lon: Float
type Query {
  customerWeather(address: String): Weather
    @sequence(steps: [{ query: "geocode" }, { query: "weather" }])

  geocode(address: String): Coord
  # any implementation, using @rest, @graphql, @dbquery

Even though all the above examples are for query, they work equally well for mutation. Just make the argument of @materializer to be mutation: "name-of-the-mutation".

The StepZen Federation model

As you can see, the above stitching (using materializer and when needed @sequence) is independent of how that subgraph is formed.

A special case is when all subgraphs are formed using @graphql. In that case, we are federating across a set of subgraphs. even though federation means something particular in Apollo context, in general, if you have a set of teams that have each built a subgraph, you can bring them all together in StepZen. Whether each subgraph is built in StepZen or not, it does not matter, it can all be made into a federated supergraph in StepZen.

This site uses cookies: By using this website, you consent to our use of cookies in accordance with our Website Terms of Use and Cookie Policy.