3

I'm using Apollo Federation for 2 months but I'm actually stuck. I've no idea how to pass a variable between my two graphql services.

I've got a website (website graphql service) which have orders (orders graphql service). I have a query to find websites and for these websites I want some stats of orders for a date range. Here the typedef (website) :

type Query {
  websites(orderFilter: OrderFilterInput): [Website!]
}

type Website @key(fields: "id") {
  id: ID!
  name: String!
  url: String!
  orderSummary(orderFilter: OrderSummaryFilterInput): OrderSummary
}

input OrderSummaryFilterInput {
  beginDate: Date
  endDate: Date
}

extend type OrderSummary @key(fields: "websiteId") {
  websiteId: String! @external
}

The resolver :

orderSummary: (website, { orderSummaryFilter }) => {                
  console.log("orderSummaryFilter", orderSummaryFilter); // filters are OK
  // HOW CAN I PASS orderFilterSummary to my order graphql service here ????
  return { __typename: "OrderSummary", websiteId: website.id }; 
}

And Order graphql service

Typedef part :

type OrderSummary @key(fields: "websiteId") {
    websiteId: String!
    count: Int
    amount: Int
}

Resolver part :

// order gql service

OrderSummary: {
  __resolveReference(website, args, info) {
    console.log("website id :", website.id); // I ve got my website ID
    // HOW TO GET OrderSummaryFilter here ????
  },
},

How can I access to order summary filter variable in order graphql resolver ? Thank you.

Denis Tsoi
  • 9,428
  • 8
  • 37
  • 56
Joe Allen
  • 1,267
  • 4
  • 24
  • 41

2 Answers2

1

From what I am aware of, it is not possible to send variables from one service to another other then the ID. But there is a solution to this.

If you want to pass in variables, extend your Website type in your order service instead of extending order type in website service.

Order typedef:

extend type Website @key(fields: "id") {
  id: ID! @external
  orderSummary(orderFilter: OrderSummaryFilterInput): OrderSummary @requires(fields:"id")
}

Order resolver:

Website: {
 orderSummary: async (website, { orderFilter }) => getOrderSummary(orderFilter) //get orderSummary with orderFilter
},
Sihoon Kim
  • 1,481
  • 2
  • 13
  • 32
0

So I want to expound on the previous (and I believe correct) answer:

In Federation, you almost never should have to expose a field called somethingId (userId, websiteId, etc). That is often either a left-over from Schema Stitching, or you simply got your type origins backward. Instead of using somethingId, you should be able to just use the object. Often, moving the @extend to the other service will get rid of the somethingId field, and get rid of the type of problem you're currently facing:

Website Service:

type Query {
  websites(orderFilter: OrderFilterInput): [Website!]
}

type Website @key(fields: "id") {
  id: ID!
  name: String!
  url: String!
}

Order Service:


extend type Website @key(fields: "id") {
  id: ID! @external
  orderSummary(orderFilter: OrderSummaryFilterInput): OrderSummary
}

input OrderSummaryFilterInput {
  beginDate: Date
  endDate: Date
}

type OrderSummary {
  website: Website!
  count: Int
  amount: Int
}

Resolvers:

const resolvers = {
  Website: {
    orderSummary(parent, args, context) {
      const websiteId = parent.id;
      // args is the data you wanted
    }
  },
};
Dan Crews
  • 3,067
  • 17
  • 20