Reason and GraphQL

Reason and GraphQL

Using Reason's type inference we can create GraphQL servers with 100% type coverage. Regardless if we compile to Node.js or native binaries using Reason we can do this with ease.

Besides that Reason shines even more so on the client. Send one quick introspection request and you get full auto completion on your schema right in the browser.

Afcee4ad6e383e26799ff05681d1a2a5?s=128

Nikolaus Graf

October 19, 2018
Tweet

Transcript

  1. None
  2. None
  3. let meaningOfLife = 41 + 1;

  4. let add = (x, y) => x + y; add(2,

    2); add(41, 1);
  5. let fruits = ["Apple", "Orange"];

  6. Goal: full stack GraphQL in Reason

  7. Reason Syntax OCaml Syntax OCaml AST JavaScript BuckleScript

  8. Reason Syntax OCaml Syntax OCaml AST Native Code JavaScript BuckleScript

  9. Let’s go native

  10. None
  11. Benefits • The type of a field agrees with the

    return type of the resolve function. • The arguments of a field agrees with the accepted arguments of the resolve function. • The source of a field agrees with the type of the object to which it belongs. • The context argument for all resolver functions in a schema agree.
  12. opam install graphql-lwt dune git clone git@github.com:andreas/ocaml-graphql-server.git cd ocaml-graphql-server/examples dune

    exec ./server.exe
  13. None
  14. None
  15. Client?

  16. None
  17. yarn add reason-apollo # Add graphql_ppx yarn add --dev graphql_ppx

    # Add JS dependencies yarn add react-apollo apollo-client graphql … "bs-dependencies": [ "reason-react", "reason-apollo" ], "ppx-flags": [ "graphql_ppx/ppx" ] yarn send-introspection-query http://localhost:8080/graphql
  18. { "data": { "__schema": { "queryType": { "name": "query" },

    "mutationType": null, "subscriptionType": { "name": "subscription" }, "types": [ { "kind": "OBJECT", "name": "subscription", "description": null, "fields": [ { graphql_schema.json
  19. let inMemoryCache = ApolloInMemoryCache.createInMemoryCache(); let httpLink = ApolloLinks.createHttpLink(~uri="/api/graphql", ()); let

    instance = ReasonApollo.createApolloClient( ~link=httpLink, ~cache=inMemoryCache, () ); Instantiate a Apollo Client
  20. ReactDOMRe.renderToElementWithId( <ReasonApollo.Provider client=Client.instance> <App /> </ReasonApollo.Provider>, "root", ); Add a

    Apollo Provider
  21. None
  22. None
  23. None
  24. None
  25. module GetUsers = [%graphql {| query users { users {

    id name } } |} ]; module GetUsersQuery = ReasonApollo.CreateQuery(GetUsers);
  26. None
  27. None
  28. None
  29. None
  30. None
  31. None
  32. Let’s do it in TypeScript 1. Unique names for all

    your queries and mutation … (per directory?) 2. Download the schema
 apollo schema:download —endpoint=http://example.com graphql-schema.json 3. Generate the types
 apollo codegen:generate genTypes --schema=graphql-schema.json — queries=‘packages/**/src/**/*.ts*’ --passthroughCustomScalars -- customScalarsPrefix=GraphQl --addTypename --globalTypesFile=./packages/ types/src/global-graphql.ts 4. Import the Type and extend the Component
  33. import { UsersQuery } from "./genTypes/UsersQuery"; const USERS_QUERY = gql`

    query UsersQuery { users { id name } } `; export default () => ( <Query<UsersQuery> query={USERS_QUERY}> {({ loading, error, data }) => { if (loading) return <div>Loading…</div>; if (error) return <div>Error</div>; if (!data) return null; // NOTE guarding that data is not null <ul> {data.users.map(user => ( <li key={user.id}>{user.name}</li> ))} </ul>; }} </Query> );
  34. import { UsersQuery } from "./genTypes/UsersQuery"; const USERS_QUERY = gql`

    query UsersQuery { users { id name } } `; export default () => ( <Query<UsersQuery> query={USERS_QUERY}> {({ loading, error, data }) => { if (loading) return <div>Loading…</div>; if (error) return <div>Error</div>; if (!data) return null; // NOTE guarding that data is not null <ul> {data.users.map(user => ( <li key={user.id}>{user.name}</li> ))} </ul>; }} </Query> );
  35. import { UsersQuery } from "./genTypes/UsersQuery"; const USERS_QUERY = gql`

    query UsersQuery { users { id name } } `; export default () => ( <Query<UsersQuery> query={USERS_QUERY}> {({ loading, error, data }) => { if (loading) return <div>Loading…</div>; if (error) return <div>Error</div>; if (!data) return null; // NOTE guarding that data is not null <ul> {data.users.map(user => ( <li key={user.id}>{user.name}</li> ))} </ul>; }} </Query> );
  36. Type generation safe yet another day!

  37. Why care about Reason then?

  38. Is it perfect?

  39. Things I like to see • Records instead of objects

    • Lists instead of Js.Array • Correct auto-completion inside the GraphQL PPX • Formatting of PPX
  40. So what now?

  41. Don’t be that person

  42. Time Innovation React Ecosystem

  43. Time Innovation Reason Ecosystem React Ecosystem

  44. https://egghead.io/courses/get-started-with-reason

  45. https://www.reason-conf.com

  46. The End