Giter Site home page Giter Site logo

Comments (9)

martijnwalraven avatar martijnwalraven commented on July 23, 2024

Thanks for the report! I don't think we have tests for nested input types, so I can definitely see how there could be going something wrong with the code generation there. Could you post the relevant part of the schema as well so I can look into this?

from apollo-ios.

beno avatar beno commented on July 23, 2024

You mean my schema.json? Not sure what the relevant bits are there, but I'll take a look. To give a bit of context, I am using Apollo to query a graph database (Arango), which results in having quite a few nested (input) objects. Each edge get its own object, since they can carry meaning and payloads. Hence the writtenBy and publishedBy input objects.

Here are some (edited and simplified) bits of my schema and types (in Absinthe/Elixir), hope you can get the gist of what I am trying to do:

  query do
    field :publishers, list_of(:publisher), do: resolve &Resolver.Publisher.all/3    
    field :books, list_of(:book), do: resolve &Resolver.Book.all/3
    field :authors, list_of(:author) do
      arg :published_by, :published_by_input
      resolve &Resolver.Author.all/3
    end
  end
  
  mutation do
    field :create_book, :book do
      arg :book, non_null(:book_input)
      resolve &Resolver.Book.create/2
    end
  end

And my types are defined here:

  object :book do
    field :id, :id
    field :name, :string
    field :written_by, :written_by_spec do
      resolve &Contracts.Resolver.Book.written_by/3
    end
  end
  
  object :written_by_spec do
    field :author, :author
  end
  
  object :author do
    field :id, :id
    field :name, :string
    field :published_by, list_of(:published_by_spec) do
      resolve &Contracts.Resolver.Author.published_by/3
    end
  end
  
  object :published_by_spec do
    field :publisher, :publisher
  end
  
  object :publisher do
    field :id, :id
    field :name, :string
  end

  input_object :book_input do
    field :name, non_null(:string)
    field :written_by, non_null(:written_by_input)
  end
  
  input_object :written_by_input do
    field :author, non_null(:id_input)
  end

  input_object :published_by_input do
    field :publisher, non_null(:id_input)
  end
  
  input_object :id_input do
    field :id, non_null(:string)
  end

from apollo-ios.

beno avatar beno commented on July 23, 2024

Is this enough info for you? I really need this fixed because it's a bit of a showstopper. Any workarounds perhaps? Is this a big issue or something I could try and fix myself?

from apollo-ios.

martijnwalraven avatar martijnwalraven commented on July 23, 2024

I won't be able to look into this until tomorrow, but I should be able to get it fixed then.

from apollo-ios.

beno avatar beno commented on July 23, 2024

OK, great. I have been plating with this for a bit, and have gotten as far as a failing test case for apollo-codegen. See attached for schema. But I didn't really see an easy fix, since it seems to me the inputFields info from the schema (which contains the required info afaik) gets discarded when the doc is parsed. Now I am new to this, so I hope and trust you will set me straight, but this is what I have.

describe('Compiling query documents', () => {
  it(`should parse nested input objects`, () => {
    const bookstore_schema = loadSchema(require.resolve('./bookstore/schema.json'));
    const document = parse(`
      query ListBooks {
          books {
              id name writtenBy { author { id name }}
          }
      }
      
      mutation CreateBook($book: BookInput!) {
          createBook(book: $book) {
              id, name, writtenBy {author { id name }}
          }
      }
      
      query ListPublishers {
          publishers {
              id name
          }
      }
      
      query ListAuthors($publishedBy: PublishedByInput!) {
          authors(publishedBy: $publishedBy) {
              id name publishedBy {publisher {id name}}
          }
      }
      
    `)
    
    const { typesUsed } = compileToIR(bookstore_schema, document);
    expect(filteredIR(typesUsed)).to.deep.include('IdInput');
    expect(filteredIR(typesUsed)).to.deep.include('WrittenByInput');
  }
}

schema.json.zip

from apollo-ios.

martijnwalraven avatar martijnwalraven commented on July 23, 2024

Thanks for the failing test case, that is very helpful. The fix turned out to be fairly simple. So upgrading apollo-codegen will hopefully solve your issue. Let me know how it goes!

There are definitely use cases for nested input types, but I have to say the schema you included looks unnecessarily complicated to me. I'm not sure if the schema is under your control, or what reasons you have for using this design, but it seems to me getting rid of most of the nesting would improve your API's usability a lot.

For instance, instead of:

input BookInput {
  name: String!
  writtenBy: WrittenByInput!
}

input WrittenByInput {
  author: IdInput!
}

input IdInput {
  id: String!
}

You could simply use:

input BookInput {
  name: String!
  writtenBy: String! (or ID)
}

Also, I'm curious what the function of the Spec wrappers is. Why do you use PublishedBySpec instead of just exposing Publisher directly for instance?

from apollo-ios.

beno avatar beno commented on July 23, 2024

Hi, thanks for the update, I will let you know how it goes.

As I tried to explain earlier, this is an API for a graph database and the reason for all the nesting is that the edges (like writtenBy) can have payloads (like maybe startDate and completionDate). So the only simplification could be getting rid of the idInput. But with it, it fits nicer onto my domain model and will allow me to specify the author by name/slug/other_id at some point.
The whole reason I came to Graphql is that REST was forcing me to come up with this whole mapping scheme, while this allows me to interact with the underlying data structures with a few layers of indirection as possible.

The _spec thing stems from some naming conflict Absinthe threw up, and mostly me not entirely sure what I'm doing :)

from apollo-ios.

martijnwalraven avatar martijnwalraven commented on July 23, 2024

Ah, sorry, I missed your earlier reply about the graph database. If that is your use case, and you prefer to expose the database structure directly, that might be a fine solution.

from apollo-ios.

beno avatar beno commented on July 23, 2024

Well, so far, so good, it all seems to be working. Yay!

from apollo-ios.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.