0
votes

I am writing an Apollo GraphQL API that returns product information from various brands. A simplified version of the schema looks like this:

type Query {
  products: [Product]!
}

type Product {
  name: String!
  brand: String!
}

I want to be able to query products from a specific brand. Normally this would be simple to achieve by adding a brand argument to the Product object:

type Query {
    products(brand: String!): [Product]!
}

However, I have multiple GraphQL clients in different apps and each is associated with a specific brand so it seems redundant to always pass the same brand argument in every query. I also have many other objects in my schema (orders, transactions, etc.) that are specific to a brand and would require a brand argument.

Furthermore, my resolvers need to query a different API depending on the brand so even objects in my schema such as User, which are conceptually unrelated to a brand, would potentially need a brand argument so that the resolver knows which API to fetch from.

Is there a way to set the brand context for each client and have this context received by the server? Or maybe there is a better way to achieve this brand separation?

1

1 Answers

0
votes

I would probably make Brand be a first-class type in your GraphQL query. That doesn't save you from having to qualify many of the queries you describe by a specific brand, but it at least gives you a common place to start from. Then you'd wind up with an API somewhat like:

type Query {
  brand(name: String!): Brand
  allProducts: [Product!]!
}
type Brand {
  name: String!
  products: [Product!]!
  # users: [User!]!
}
type Product {
  name: String!
  brand: Brand! # typical, but not important to your question
}

If the differences between kinds of brands are visible at the API layer, you also could consider using a GraphQL interface to describe the set of fields that all brands have, but actually return a more specific type from the resolver.

The way you describe your application, it could also make sense to run one copy of the service for each brand, each with a different GraphQL endpoint. That would let you straightforwardly parameterize the per-brand internal object configuration and make the "current brand" be process-global context. The big constraints here are that, at a GraphQL level, one brand's objects can never refer to another, and if you have a lot of brands, you need some good way to run a lot of servers.