⚠️ NOTICE: This package recently changed and is now published asrescript-apollo-client
!
ReScript bindings for the Apollo Client ecosystem
Documentation • Installation • Quick Start • Examples • Contributing
Go to the official documentation site (work in progress)
We rely on Graphql-ppx for typesafe GraphQL operations and fragments in ReScript. Go to the official documentation for installation instructions.
You should now have a graphql_schema.json
in your project somewhere. Make sure it's always up-to-date!
npm install rescript-apollo-client @apollo/client
Add the following under bs-dependencies
and graphql
, in your bsconfig.json
{
"graphql": {
+ "apolloMode": true,
+ "extendMutation": "ApolloClient.GraphQL_PPX.ExtendMutation",
+ "extendQuery": "ApolloClient.GraphQL_PPX.ExtendQuery",
+ "extendSubscription": "ApolloClient.GraphQL_PPX.ExtendSubscription",
+ "templateTagReturnType": "ApolloClient.GraphQL_PPX.templateTagReturnType",
+ "templateTagImport": "gql",
+ "templateTagLocation": "@apollo/client"
},
"ppx-flags": ["@reasonml-community/graphql-ppx/ppx"],
"bs-dependencies: [
"@reasonml-community/graphql-ppx"
+ "rescript-apollo-client"
]
}
"apolloMode"
automaticaly sprinkles__typename
throughout our operation and fragment definitions"templateTag*"
is how we tellgraphql-ppx
to wrap every operation withgql
"extend*"
allowsrescript-apollo-client
to automatically decorate the generated modules with Apollo-specific things like the correct hook for that operation!
Other than some slightly different ergonomics, the underlying functionality is almost identical to the official Apollo Client 3 docs, so that is still a good resource for working with this library.
The EXAMPLES/ directory is the best documentation at the moment (real docs are literally in progress), but in short, the appropriate hook is exposed as a use
function on the module generated by graphql-ppx
. Variables are always the last argument:
module TodosQuery = %graphql(`
query Example ($userId: String!) {
user(id: $userId) {
id
name
}
}
`)
@react.component
let make = () =>
// The useQuery hook is automatically exposed on the module generated by graphql-ppx
switch ExampleQuery.use({userId: "1"}) {
| {data: Some({users})} =>
...
}
}
It's probably worth noting this library leverages records heavily which allows for very similar syntax to working with javascript objects and other benefits, but comes with a downside. You may need to annotate the types if you're using a record in a context where the compiler cannot infer what it is. The most common case is when using a non-T-first api like Js.Promise
. For this reason we expose every type from the ApolloClient.Types
module for convenience. Example:
let queryResult = SomeQuery.use()
// I can destructure or access properties just like javascript, and also pattern match!
switch queryResult {
| {loading: true} =>
// Show loading
| {data: Some(data), fetchMore} =>
let onClick = _ => fetchMore()
// Show data
}
// Annotation is necessary in some cases
apolloClient.query(~query=(module SomeQuery), ())
|> Js.Promise.then(result => // Hover over the type and you can see it is an ApolloQueryResult.t__ok
// Let's open the module so the record fields are accessible
open ApolloClient.Types.ApolloQueryResult
// ☝️ You don't have to go searching for a type, everything is accessible under ApolloClient.Types
switch result {
| Some(apolloQueryResult) =>
Js.log2("Got data!", apolloQueryResult.data)
| Error(_) =>
Js.log("Check out EXAMPLES/ for T-first promise solutions that don't have this problem!")
}
)
vscode-reasonml-graphql provides syntax highlighting, autocompletion, formatting and more for your graphql operations
vscode-graphiql-explorer provides a visual interface to explore the schema and generate operations
Contains partial bindings to the following:
While we strive to provide ergonomics that are intuitive and "reasonable", the intent is to also expose a 1:1 mapping to the javascript package structures if that is your preference. For instance, if you're looking in the Apollo docs and see import { setContext } from '@apollo/link-context'
and you'd prefer to interact with this library in the same way, you can always access with the same filepath and name like so:
module Apollo = {
include ApolloClient.Bindings
}
// import { setContext } from '@apollo/client/link/context'
let contextLink = Apollo.Client.Link.Context.setContext(...)
// import { createHttpLink } from '@apollo/client'
let httpLink = Apollo.Client.createHttpLink(...)
For comparison, this library packages things up into logical groups that have a consistent structure with the intent to be more disoverable and less reliant on docs:
// Make a generic link
let customLink = ApolloClient.Link.make(...)
// Specific link types are nested under the more general module
let contextLink = ApolloClient.Link.ContextLink.make(...)
// See, they're all the same :)
let httpLink = ApolloClient.Link.HttpLink.make(...)
Apollo bindings in the Reason / BuckleScript community are pretty confusing as a write this (July 14, 2020), so it's worth providing some context to help you make the right decisions about which library to use.
This library, rescript-apollo-client
, targets Apollo Client 3 and aims to take full advantage of v1.0.0 graphql-ppx
features and is intended to be a replacement for reason-apollo
and reason-apollo-hooks
. You should avoid using those libraries at the same time as this one.
If you have a large code base to migrate from reason-apollo-hooks
, it might make sense to upgrade to the reason-apollo-hooks PR that adds support for graphql-ppx 1.0 first. This PR has been used by some larger companies to gradually upgrade.
reason-apollo, despite being under the apollographql github org, doesn't have any official Apollo team support behind it and currently seems like it may be abandoned. It binds to the react-apollo
js package and some of the older apollo packages not under the @apollo
npm namespace.
reason-apollo-hooks is the hooks companion to the reason-apollo
library and binds to @apollo/react-hooks
. Given the lack of development on reason-apollo
, there has been a lot of active contribution pulling reason-apollo
features in there. It's fairly battle-tested and it provides a nice, simple interface to hooks. It's not currently compatible with graphql-ppx
v1.0.0, but there is a branch that adds basic support for it.
Lets work to make the Apollo experience in ReasonML the best experience out there! This is a solid base, but there's a lot of low-hanging fruit remaining—more bindings, docs, examples, tests, better ergonomics—there's so much left to do! Check out the Contributing Guide or issues to get started.