Calculated fields in federation: How to calculate total on a cart with federated product-service?

Hello Community!

I am rather new to Apollo-GraphlQL but I start to like it and it looks really promising. Unfortunately I am still unable to solve some seemingly simple problems. Here is one it:

I want to define a schema and resolvers for a cart type, which holds information about products as well as their respective quantities (product + quantity = lineItem). On that cart type I would also like to return the total value of the lineItems (=sum over all products*quantity). The product information comes from a federated subgraph. So the (subgraph-)schemas look like this:

cart-service:

type Cart {
  id: String!
  lineItems: [LineItem!]
  total: Float
}

type LineItem {
  product: Product!
  quantity: Int!
}

extend type Product @key(fields: "id") {
  id: String! @external
}

product-service:

type Product @key(fields: "id") {
  id: String!
  name: String
  price: Float!
}

I have successfully implemented the resolvers the get information from my federated product-subgraph. Yet, I don’t know how resolve the “total” field on cart. “Total” needs “lineItems” clearly to be resolved first, but this is something GraphQL does not like. In GraphQL logic “total” and “lineItems” are independent branches on the graph which are supposed to be resolved independently. This logic seems to fail me in this case.

I have also tried to bombard the cart-service with interceptors and field middleware but the price-information never seems to be available (probably because it goes from the product-service directly to the gateway, instead of the cart-service?). What I am basically looking for is a way to do some extra operation after ALL fields from all federated services have been resolved.

Another potential solution came to my mind where I insert and extra service above the cart-service (call it “super-cart”), since then I can use the @requires-directive. I haven’t tried this, but I could imagine something like this:

super-cart-service:

extend type Cart @key(fields: "id") {
  id: String! @external
  lineItems: [LineItem!] @external
  total: Float @requires(fields: "lineItems{product{price} quantity}")
}

cart-service:

type Cart @key(fields:"id") {
  id: String!
  lineItems: [LineItem!]
}

To be honest, this looks overly complicated. Introducing another service just to calculate one additional field? This problem does not seem to be so hard at first glance, but I did not manage to come up with a practical solution. Do you have any good ideas? Btw: I working with Nest.js, but a plain Apollo solution is also welcome.

Thank you very much for your effort.