teamwalnut / graphql-ppx

GraphQL language primitives for ReScript/ReasonML written in ReasonML
https://graphql-ppx.com
MIT License
259 stars 54 forks source link

Option for opaque query types #201

Closed johnridesabike closed 3 years ago

johnridesabike commented 4 years ago

It would be useful if queries could be given an opaque type instead of string

The motivation is that this would make adding type-safe extensions easier. For example:

module ExtendQuery: (M: GraphQLQuery) => {
  @bs.module("gatsby")
-  external useStaticQuery: string => M.Raw.t = "useStaticQuery"
+  external useStaticQuery: M.queryType => M.Raw.t = "useStaticQuery"
}

You can’t implement an opaque query type in the functor and redefine the query because Gatsby requires query values to be static--they can’t get passed through different functions before use.

johnridesabike commented 4 years ago

I just learned about the templateTagReturnType config option, which seems to mostly satisfy what I’m trying to do. I still think it would be useful to be able to have a unique type per module, if that’s feasible.

jfrolich commented 4 years ago

Actually can you not pass the whole query to useStaticQuery? Like:

useStaticQuery((module MyQuery))

or as a extension:

MyQuery.useStatic()

Actually, for your specific example, you can use the query inside of the passed module in the functor right?

module ExtendQuery: (M: GraphQLQuery) => {
  // you can hide this in the interface
  @bs.module("gatsby")
  external useStaticQueryJs: string => M.Raw.t = "useStaticQuery"
  let useStatic = () => {
    useStaticQueryJs(GraphQLQuery.query)
  }
}
johnridesabike commented 4 years ago

That was one of my first thoughts too, but sadly it is not possible in Gatsby. The input to useStaticQuery can’t be a variable (like a function argument). See https://www.gatsbyjs.com/docs/use-static-query/#known-limitations

Anyway, this suggestion is probably low-priority since templateTagReturnType almost completely solves my use case.

jfrolich commented 3 years ago

Ok, I'll close it then. It shouldn't be too hard to implement, perhaps even an "opaque" value to templateTagReturnType?