gabotechs / graphqxl

GraphQXL is a new language built on top of the GraphQL syntax that extends the original language with some additional features useful for creating scalable and big server side schemas. This repository contains the source code for the GraphQXL compiler.
https://gabotechs.github.io/graphqxl
MIT License
272 stars 8 forks source link

Spread syntax for query/mutation args #56

Open RobertVillalba opened 6 months ago

RobertVillalba commented 6 months ago

First of all I want to say that this is some awesome work! I've been hunting for something like it and none of the other solutions I've seen feel anywhere near as clean as this project. I feel like the repetition of GQL is one of the things that have hit me the hardest when defining schemas. So all in all thank you for this awesome project!

With regards to the project, I was wondering if there are any plans to support the use of the spread syntax inside of queries/mutation args. Currently I have a query and I would like to be able to pass in some pagination args that I have defined in an input, but I believe this is not supported.

  getThings(
    q: String!
    ..._PaginationInput
  ): [Thing!]!
gabotechs commented 6 months ago

Hi @RobertVillalba! glad you find this library useful!

It's an interesting suggestion, but I'm not sure about the cost/benefit of adding the spread operator in input arguments. It would lead to some clunky edge cases, like what if you have directives in the input that are just meant to be used in input types? or what if the type you are spreading implements an interface? or what if there is a top level directive in the input, should it be lost?

The truth is that structural entities (inputs, types...) and arguments are of significantly different nature, I also don't think that other languages with spread operators support this, I'm not sure about their specific reasons though.

I think it's worth deferring this as much as possible until enough use-cases are gathered in order to know what is the best way of implementing this.

RobertVillalba commented 6 months ago

Hmm ok those are all fair points, perhaps what I want is something more simple. So let me preface this all with the fact that I'm fairly new to GQL and there is a great deal of things I'm not going to be familiar with or aware of. My background is more closely aligned with TS so I'm probably just wanting to bring some of those features to GQL. Not that TS has this exact same thing but, here is what I think would make GQL easier and would be great to see graphqxl allow.

(a bit of a detour follows, but promise it will get back to this subject)

I'm not a big fan of the separation between inputs and types. I sort of get why inputs have to be separated, but a lot of times I find that I'm just using simple inputs and types that could have been used interchangeably if it was not for GQL limitations. This lib greatly helps with this issue, but I find that it doesn't cover the case where I have inputs inside of inputs. I can't spread those so I need some repetition

input Thing1Input {
  "some nice docs"
  hello: String!
}

input Thing2Input {
  "some more nice docs"
  world: String!
  "some even nicer docs"
  thing1: Thing1Input!
}

type Thing2 {
  ...Thing2Input
}

To make the above example work, we'd have to make a type Thing1 and then duplicate the doc string for thing1 inside of Thing2 and pretty much also copy the thing1 line. It would be great to add some sort of type like a template that could just be used for both. The obvious restriction is that template would only be allowed to contain simple data (w.e. that might be) and that it would generate a type and an input. Allowing us to write something like

template Thing1 {
  "some nice docs"
  hello: String!
}

template Thing2 {
  "some more nice docs"
  world: String!
  "some even nicer docs"
  thing1: Thing1!
}

that would generate

input Thing1Input {
  "some nice docs"
  hello: String!
}

input Thing2Input {
  "some more nice docs"
  world: String!
  "some even nicer docs"
  thing1: Thing1Input!
}

type Thing1 {
  "some nice docs"
  hello: String!
}

type Thing2 {
  "some more nice docs"
  world: String!
  "some even nicer docs"
  thing1: Thing1!
}

If we place a restriction that templates must be simple then we can perhaps also allow spreading them inside of functions as well since it might eliminate some of the mentioned concerns?

Sorry I know that was fairly drawn out and perhaps a separate ticket, but they seemed somewhat related.