graphql icon indicating copy to clipboard operation
graphql copied to clipboard

Expected Iterable, but did not find one for field

Open BarryThePenguin opened this issue 2 years ago • 5 comments

When a schema defines a list using an interface, it looks like @miragejs/graphql fails to build the field for the list

interface ItemRead {
  authors: [String!]!
  id: ID!
  title: String!
}

type BookChapterRead implements ItemRead {
  authors: [String!]!
  chapter: Int
  id: ID!
  title: String!
}

type BookRead implements ItemRead {
  authors: [String!]!
  id: ID!
  rating: Int
  title: String!
}

type Query {
  booksRead: [BookRead]
  bookChapterRead: [BookChapterRead]
  itemsRead: [ItemRead]
}

Querying for..

{
  itemsRead {
    id
    title
    authors
  }
}

..fails with..

Expected Iterable, but did not find one for field "Query.itemsRead".

..while querying other fields works fine.

I put together a reproduction in the REPL https://miragejs.com/repl/v2/042996bcd5

BarryThePenguin avatar May 27 '22 03:05 BarryThePenguin

Looking at the mirageGraphQLFieldResolver, it may need additional checks for lists that are a GraphQLInterfaceType or GraphQLUnionType?

https://github.com/miragejs/graphql/blob/8364bb66dae872ba7c208fe199acebf8855adb71/lib/resolvers/mirage.js#L29-L41

BarryThePenguin avatar May 27 '22 03:05 BarryThePenguin

I can't remember the auto-resolution logic at play here but it might be the case that the library will only try to auto-resolve types that implement an interface. I'll have to check as soon as I get a chance. In the meantime, you should be able to add your own resolver for the field, if you haven't done so already.

jneurock avatar May 29 '22 15:05 jneurock

Ok, thanks! I hadn't considered adding a field resolver

BarryThePenguin avatar May 29 '22 20:05 BarryThePenguin

I didn't have much luck making a field resolver.. But I was able to reproduce the issue in #56

BarryThePenguin avatar May 30 '22 06:05 BarryThePenguin

I think this will work for you https://miragejs.com/repl/v2/571a844c0b:

this.post("/graphql", createGraphQLHandler(graphQLSchema, this.schema, {
  resolvers: {
    Query: {
      itemsRead(_obj, _args, context) {
        const booksRead = context.mirageSchema.db.bookReads.map((book) => ({
          ...book,
          __typename: 'BookRead'
        }));
        const bookChaptersRead = context.mirageSchema.db.bookChapterReads.map((chapter) => ({
          ...chapter,
          __typename: 'BookChapterRead'
        }));
        
        return [...booksRead, ...bookChaptersRead];
      }
    }
  }
}))

Mirage's inflector doesn't seem to be able to handle the pluralization well in this case so the table names are a bit weird.

jneurock avatar May 30 '22 08:05 jneurock