Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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.

Nikolaus Graf

October 19, 2018
Tweet

More Decks by Nikolaus Graf

Other Decks in Programming

Transcript

  1. View Slide

  2. View Slide

  3. let meaningOfLife = 41 + 1;

    View Slide

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

    View Slide

  5. let fruits = ["Apple", "Orange"];

    View Slide

  6. Goal:
    full stack GraphQL in Reason

    View Slide

  7. Reason Syntax OCaml Syntax
    OCaml AST
    JavaScript
    BuckleScript

    View Slide

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

    View Slide

  9. Let’s go native

    View Slide

  10. View Slide

  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.

    View Slide

  12. opam install graphql-lwt dune
    git clone [email protected]:andreas/ocaml-graphql-server.git
    cd ocaml-graphql-server/examples
    dune exec ./server.exe

    View Slide

  13. View Slide

  14. View Slide

  15. Client?

    View Slide

  16. View Slide

  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

    View Slide

  18. {
    "data": {
    "__schema": {
    "queryType": {
    "name": "query"
    },
    "mutationType": null,
    "subscriptionType": {
    "name": "subscription"
    },
    "types": [
    {
    "kind": "OBJECT",
    "name": "subscription",
    "description": null,
    "fields": [
    {
    graphql_schema.json

    View Slide

  19. let inMemoryCache = ApolloInMemoryCache.createInMemoryCache();
    let httpLink = ApolloLinks.createHttpLink(~uri="/api/graphql", ());
    let instance = ReasonApollo.createApolloClient(
    ~link=httpLink, ~cache=inMemoryCache, ()
    );
    Instantiate a Apollo Client

    View Slide

  20. ReactDOMRe.renderToElementWithId(


    ,
    "root",
    );
    Add a Apollo Provider

    View Slide

  21. View Slide

  22. View Slide

  23. View Slide

  24. View Slide

  25. module GetUsers = [%graphql
    {|
    query users {
    users {
    id
    name
    }
    }
    |}
    ];
    module GetUsersQuery = ReasonApollo.CreateQuery(GetUsers);

    View Slide

  26. View Slide

  27. View Slide

  28. View Slide

  29. View Slide

  30. View Slide

  31. View Slide

  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

    View Slide

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

    {data.users.map(user => (
    {user.name}
    ))}
    ;
    }}

    );

    View Slide

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

    {data.users.map(user => (
    {user.name}
    ))}
    ;
    }}

    );

    View Slide

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

    {data.users.map(user => (
    {user.name}
    ))}
    ;
    }}

    );

    View Slide

  36. Type generation safe yet another day!

    View Slide

  37. Why care about Reason then?

    View Slide

  38. Is it perfect?

    View Slide

  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

    View Slide

  40. So what now?

    View Slide

  41. Don’t be that person

    View Slide

  42. Time
    Innovation
    React Ecosystem

    View Slide

  43. Time
    Innovation
    Reason Ecosystem
    React Ecosystem

    View Slide

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

    View Slide

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

    View Slide

  46. The End

    View Slide