1

I'm currently working on an Activity Feed built using GraphQL Nexus and Apollo Server (3.9.0). It will receive a flurry of information that will have shared fields that are handled by a shared IActivity interface.

In addition, there will be types that will also share similar fields through other interfaces that are not included in IActivity, say for example IMedia and INews.

We are looking for a way to bring all the fields from IActivity and be able to query IMedia and INews within IActivity. We know that there is a possibility to query the concrete types, but we'd like to avoid it, as we want to extend the backend by adding new types of feeds (That share the same fields of those interfaces) without updating the client (it's a react-native application). We would use concrete types only when rendering custom UI components.

Here's an example:

interface IActivity {
    id: ID!
    name: String!
    description: String
}

interface IMedia implements IActivity {
    id: ID!
    name: String!
    description: String
    url: String
    type: String
}
interface INews implements IActivity {
    id: ID!
    name: String!
    description: String
    date: DateTime
    author: String
    content: String
}

type Video implements IActivity & IMedia {
    id: ID!
    name: String!
    description: String
    url: String
    type: String
    format: String
    codec: String
}
type Image implements IActivity & IMedia {
    id: ID!
    name: String!
    description: String
    url: String
    type: String
    compressed: Boolean
    codec: String
    extension: String
}

type Audio implements IActivity & IMedia {
    id: ID!
    name: String!
    description: String
    url: String
    type: String
    bitrate: Boolean
}

type Post implements INews & IActivity {
    id: ID!
    name: String!
    description: String
    date: DateTime
    author: String
    content: String
    comments: [Comment]
}

type Comment {
    author: String
    message: String
}

type FlashNews implements INews & IActivity {
    id: ID!
    name: String!
    description: String
    date: DateTime
    author: String
    content: String
    rating: Int
}


type Query {
    activityFeed(): [IActivity]
}

This is the query

query getFeed() {
    activityFeed {
        id
        name
        description
        ... on IMedia {
            url
            type
        }
        ... on INews {
            date
            author
            content
        }
    }
}

This queries all the fields from IActivity but none of IMedia nor INews. There are no GraphQL errors (and we lint them through graphql-codegen and the Nexus builder.)

Our belief was that having IActivity also share the same as other interfaces, we could query IActivity and then specify the other interface (e.g: IMedia) as we do with concrete types.

In hindsight, what we're trying to do is somehow a union type of interfaces (which I know it's not possible)...

Is there a workaround or a solution for what we're trying to accomplish?

Edit

We found out that this exact example IS valid, and the problem is within how GraphQL Nexus is configured.

Here's a code sandbox and its Git Repo using plain Apollo Server.

Edit 2:

Try the following query:

query getFeed {
    activityFeed {
        id
        name
        description
        ... on IMedia {
            type
            format
        }
        ... on INews {
            date
            author
            content
        }
        ... on Video {
            length
        }
    }
}
Jose A
  • 10,053
  • 11
  • 75
  • 108
  • Well, we've made a discovery, and that is possible with GraphQL. It's actually pretty dope. – Jose A Jul 26 '22 at 17:59

1 Answers1

0

We have found the problem. It's been Apollo Client (front-end) which was not properly parsing the heuristic fragment matcher.

More information on how we solved the issue can be found here: https://stackoverflow.com/a/64886593/1057052

We generated something like this:

schema: "./appsync/appSync.gql"
# documents: "./appsync/**/*.gql"
generates:
      src/generated/graphql.schema.json:
        plugins:
            - 'fragment-matcher'
        apolloClientVersion: 3

Then the interfaces were working properly!

Jose A
  • 10,053
  • 11
  • 75
  • 108