teamwalnut / graphql-ppx

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

Type errors when defining fragments using @ppxCustom #207

Open mbirkegaard opened 3 years ago

mbirkegaard commented 3 years ago

I've been trying to use @ppxCustom on this fragment

    fragment UserFragment on User {
      id
      firstName
    }

where User has the following definition

type User {
  id: ID!
  firstName: string
}

The recursive version

module rec UserFragment = [%graphql
  {|
    fragment UserFragment on User @ppxCustom(module: "UserFragmentDecoder") {
      id
      firstName
    }
  |}
]
and UserFragmentDecoder: {
  type t = {
    id: string,
    name: string,
  };
  let parse: UserFragment.t => t;
  let serialize: t => UserFragment.t;
} = {
  type t = {
    id: string,
    name: string,
  };
  let parse: UserFragment.t => t =
    v =>
      switch (v) {
      | {id, firstName: Some(name)} => {id, name}
      | {id, firstName: None} => {id, name: "Default Name"}
      };
  let serialize: t => UserFragment.t =
    ({id, name}) => {id, firstName: Some(name)};
};

fails with

  We've found a bug for you!
  (No file name)

  This has type:
    UserFragmentDecoder.t
  But somewhere wanted:
    t (defined as UserFragment.t)

I also tried the less compact non-recursive version which fails with the same error (naming is slightly different but that is immaterial).

A very similar approach works with a query currentUser: User

module rec UserQuery = [%graphql
  {|
  query {
    currentUser @ppxCustom(module: "UserQueryDecoder") {
      id
      firstName
    }
  } |}
]
and UserQueryDecoder: {
  type t = {
    id: string,
    name: string,
  };
  let parse: UserQuery.t_currentUser => t;
  let serialize: t => UserQuery.t_currentUser;
} = {
  type t = {
    id: string,
    name: string,
  };
  let parse: UserQuery.t_currentUser => t =
    v =>
      switch (v) {
      | {id, firstName: Some(name)} => {id, name}
      | {id, firstName: None} => {id, name: "Default Name"}
      };
  let serialize: t => UserQuery.t_currentUser =
    ({id, name}) => {id, firstName: Some(name)};
};
jfrolich commented 3 years ago

Possibly this is a bug indeed (perhaps particularly with a top level ppxCustom on fragments). It would be great if you can contribute the failing query to the tests, then I'll look into fixing it.

The recursive modules where one of the last features that were added to the 1.0 release. Thanks for stress testing them!

mbirkegaard commented 3 years ago

I'd be happy to add the failing query and seeing about fixing it also. Let me get get the build and tests working first (as per my questions in #205)

Emilios1995 commented 2 years ago

@jfrolich Just following up on this since it's blocking our migration from the old ppx. I have a branch with a non-compiling test. (I didn't write a proper test since that's hard to do with a query that doesn't compile, the branch is mainly for illustrative purposes.) Could you please look into fixing it?

jfrolich commented 2 years ago

Yes will look at this ASAP!