Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deriving schema from types #185

Open
bram209 opened this issue Jan 5, 2020 · 7 comments
Open

Deriving schema from types #185

bram209 opened this issue Jan 5, 2020 · 7 comments

Comments

@bram209
Copy link

bram209 commented Jan 5, 2020

It would be nice if we could derive a schema directly from a type, for example:

type user = {
  id   : int [@description "Unique user identifier"];
  name : string [@name "firstName"];
  role : role;
}
[@@deriving graphql_object]

would generate the following code:

Schema.(obj "user"
  ~fields:(fun _ -> [
    field "id"
      ~doc:"Unique user identifier"
      ~typ:(non_null int)
      ~args:Arg.[]
      ~resolve:(fun info p -> p.id)
    ;
    field "firstName"
      ~typ:(non_null string)
      ~args:Arg.[]
      ~resolve:(fun info p -> p.name)
    ;
    field "role"
      ~typ:(non_null role)
      ~args:Arg.[]
      ~resolve:(fun info p -> p.role)
  ])
)

thoughts?

@sgrove
Copy link

sgrove commented Jan 5, 2020

What about using SDL to generate the types and resolvers (and use a few custom directives to control the generation)?

So the above could be written as:

"""
User role
"""
# Specify that a GraphQL type should specify an existing OCaml type:
enum Role @useExistingType(name: "Roles.t") {
  admin
  user
}

# Otherwise generate a new type definition (and resolvers) for our GraphQL type
type User {
  id: int!
  """
  Unique user identifier
  """
  firstName: String! @rename(lookupKey: "name") # Specify that the record field name should actually be `name` while the GraphQL field name is `firstName`
  role: role
}

@andreas
Copy link
Owner

andreas commented Jan 5, 2020

Hey @bram209 😄 I've been toying in my mind with such an idea myself, and I think it could be great for simple GraphQL objects. It's not obvious to me how it can be adapted for more complex use cases though (e.g. fields with arguments).

@sgrove: I really like the idea of a PPX based on the SDL. I've been wondering whether it could generate a functor, where the user supplies the types and resolvers. As an example, the following SDL:

type User {
  id: int!
  friends(first: int): [User!]
}

type Query {
  me: User!
}

schema {
  query: Query
}

... would generate a functor with the following type:

functor (S : sig
  type ctx

  module User : sig
    type t
    val id : t -> int
    val friends : ctx Schema.resolve_info -> t -> first:int option -> t list option
  end

  module Query : sig
    type t
    val me : ctx Schema.resolve_info -> t -> User.t
  end
end) -> sig
  val schema : S.ctx Schema.schema
end

@cem2ran
Copy link

cem2ran commented Feb 9, 2020

Been thinking about this for a while too. (Pardon the Reason syntax), but do you think something like this is viable w.r.t defining resolvers?

let name_resolver = (info, p) => p.name;

type role = 
| [@desc "A regular user"] User 
| [@desc "An admin user"] Admin
| Test;

[@deriving graphql_object]
type user = {
  id: [@desc "Unique user identifier"] int,
  name: [@name "firstName"][@resolver name_resolver] string,
  role,
  age: option(int),
  friends: list(user)
};

https://astexplorer.net/#/gist/842c826d3dbd3ce841f33ff1d7e8ba26/d8ce85315ec79cf0b3906121deb1a7178ea52a83

@sgrove I believe you have done some work on codegen from record type declarations? I'd be happy to go down this rabbit hole with some guidance!

@cem2ran
Copy link

cem2ran commented Feb 18, 2020

W.r.t. the SDL approach, it looks like the sister project (targeting node.js) has a PR open for SDL parsing & printing! sikanhe/reason-graphql#31

@andreas
Copy link
Owner

andreas commented Feb 18, 2020

W.r.t. the SDL approach, it looks like the sister project (targeting node.js) has a PR open for SDL parsing & printing! sikanhe/reason-graphql#31

Yeah, unfortunately it's with a handrolled parser rather than using Menhir or similar 😕

@cem2ran
Copy link

cem2ran commented Feb 18, 2020

Right :/

Good news though. The following seems to be:
https://github.com/tahnik/graphqlx/blob/master/src/language/src/parser.mly

Might be missing things such as description. Maybe now is the time I'll finally get to try out Menhir 😄

@sgrove
Copy link

sgrove commented May 10, 2020

W.r.t. the SDL approach, it looks like the sister project (targeting node.js) has a PR open for SDL parsing & printing! sikanhe/reason-graphql#31

Yeah, unfortunately it's with a handrolled parser rather than using Menhir or similar 😕

I don't know if that's the worst thing for a production project, given the error messages Menhir or similar tend to produce (not that a handrolled parser will give good error messages by default)...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants