FSharp.Data.GraphQL icon indicating copy to clipboard operation
FSharp.Data.GraphQL copied to clipboard

Q: Print AST to string?

Open haf opened this issue 6 years ago • 6 comments

Description

Question: is it possible to print the AST to a string (latest master)? The ToString() impl primarily prints x.name + "!". I'm trying to build a F# to GraphQL generating using your Shared lib.

OT: can you split the Shared lib to a separate nuget please? That way I don't have to reference either the client or server to work with the object model.

Similarly, why are the Ast constructors internal? I would prefer to be able to do a 1-1 mapping from F#'s AST to the GQL AST without going through the builders (I think).

haf avatar Sep 04 '19 14:09 haf

Hi @haf

Can you clarify as to which constructors are internal?

Thanks, John

johnberzy-bazinga avatar Sep 04 '19 23:09 johnberzy-bazinga

@johnberzy-bazinga It was FieldDefinition, ScalarDefinition, etc, but I moved the TypeDefinitions to the Ast module (see #249) and then I can use them.

haf avatar Sep 05 '19 06:09 haf

@haf Is your plan to generate code based on GraphQL SDL documents? if that's the case, would you consider modifying our existing parser to do that? We have a use case for that in our client provider so we're planning to eventually support SDL documents.

johnberzy-bazinga avatar Sep 05 '19 20:09 johnberzy-bazinga

@johnberzy-bazinga Actually I'm going the other way, from F# to SDL right now.

I've written a basic transpiler from F# to GraphQL SDL based on the F# compiler services and I'm using the AST in both languages, and I've written an GQL AST -> text printer. This is a currently passing test:


let interfaces = [
  let humanBoyA = parseFSharp """
/// All humans are of type Human
type Human =
  /// They have names...
  abstract name: string

/// A boy is a human with a name and a birthdate
type Boy =
    /// A boy has no name?
  { name: string
    /// When?
    born: Instant }
  interface Human with
    member x.name = x.name
"""

  yield testCaseAsync "transpile interface" <|
    async {
      let! xs = humanBoyA
      xs
        |> GraphQL.encodeTypeDefinitions
        |> Expect.sequenceEqual "Should create one interface and one object" [
          let ifFields = [ FD.create ("name", NN (N "String"), "They have names...") ]
          yield InterfaceTypeDefinition (ITD.create ("Human", ifFields, "All humans are of type Human"))

          let objFields = [
            FD.create ("name", NN (N "String"), "A boy has no name?")
            FD.create ("born", NN (N "DateTime"), "When?")
          ]
          let objIfs = [ "Human" ]
          yield OTD.create ("Boy", objFields, "A boy is a human with a name and a birthdate", objIfs)
            |> ObjectTypeDefinition
        ]
    }

  yield testCaseAsync "print interface and type" <|
    async {
      let! xs = humanBoyA
      let str =
        xs
          |> GraphQL.encodeTypeDefinitions
          |> Seq.map GraphQL.mapToString |> String.concat "\n"
      let expected = """
"All humans are of type Human"
type Human {
  "They have names..."
  name: String!
}

"A boy is a human with a name and a birthdate"
type Boy implements Human {
  "A boy has no name?"
  name: String!
  "When?"
  born: DateTime!
}
"""
      str
        |> Expect.stringContains "Should have the expected contents" (expected.Trim([| '\n' |]))
    }
]

I'll consider sending it back, if you reciprocate by cleaning up the pull requests that have been lingering; that way I can rebase my changes on top of the latest features and bugfixes.

haf avatar Sep 06 '19 08:09 haf

@haf That's pretty cool. We have had similar ideas to introduce a reflection-based schema with the use of attributes for metadata such as descriptions. Your approach is nice since you can just extract the comments from source. Do you have a bit of time to join our gitter for a chat? We're working on some changes for 2.0 release that will have some breaking changes. Would be good to coordinate with you.

johnberzy-bazinga avatar Sep 10 '19 16:09 johnberzy-bazinga

@johnberzy-bazinga I've joined now

haf avatar Sep 10 '19 16:09 haf