Skip to main content

Getting Started

Note that ResGraph is currently alpha grade software. Help us out as we work out the details for a stable release.

Setup

You're encouraged to use our dedicated VSCode extension that provides in-editor error messages, autocomplete, hovers, snippets, and more.

Let's start by setting up ResGraph in your project.

You can either follow these instructions below, if you want to understand how everything fits together. Or you can use our project template to get started quickly.

Installation

ResGraph relies on features in ReScript v11, which is currently in alpha. Make sure you run >= rescript@11.0.0-alpha.6 and for the best results, set "uncurried": true in your rescript.json or bsconfig.json.

# Install both `graphql` and `graphql-yoga` so we can set your server up
npm i resgraph graphql graphql-yoga @rescript/core @glennsl/rescript-fetch

We rely on @glennsl/rescript-fetch for various fetch related things needed in GraphQL Yoga. We also rely on @rescript/core, the (future) standard library for ReScript.

Configure your rescript.json (or bsconfig.json if you haven't migrated yet), including adding the various dependencies to your bs-dependencies:

{
"uncurried": true,
"bs-dependencies": ["resgraph", "@rescript/core", "@glennsl/rescript-fetch"],
"bsc-flags": ["-open RescriptCore"],
"suffix": ".mjs"
}

resgraph.json

Add a resgraph.json file in the root of your ReScript project, and paste this into it:

{
"src": "./src",
"outputFolder": "./src/schema/__generated__"
}
  • src is the folder where code that can define GraphQL lives
  • outputFolder is where you want ResGraph to output the files it generates. Ensure that this folder exists. Create it if you don't already have it.

ResGraphContext.res

Create a ResGraphContext.res file anywhere in your project, and add a context type in there. The context can have anything you'd like in it:

// ResGraphContext.res
type context = {currentUserId: option<string>}

This is the type of your per-request GraphQL context, and ResGraph will ensure you fill out and provide this to every request as you create your server.

Define a query type

Somewehere in your project, define a GraphQL Query type, and a field for it. This is the bare minimum to get a GraphQL server going.

// Schema.res - Called `Schema` here, but this can be called anything
@gql.type
type query

/** The current time on the server, as a timestamp. */
@gql.field
let currentTime = (_: query) => {
Some(Date.now())
}

The root Query type is mandatory in a GraphQL schema, and is the base from where all queries will be made.

Make sure ReScript has built your changes (npx rescript build). Then run npx resgraph build. This should generate your first schema, looking like this:

type Query {
"""
The current time on the server, as a timestamp.
"""
currentTime: Float
}

ResGraph will automatically generate a number of things by default:

  1. The ResGraphSchema.res and ResGraphSchema.resi files. These hold the optimized graphql-js schema generated from your types and resolvers, that you then expose through your server.
  2. Interface_<interfaceName>.res for each interface you use. These files hold generated helpers and assets for each interface you have and use.
  3. schema.graphql. This is a schema SDL file dumped from ResGraph. This is intended to be used as a debug utility primarily.

Build and watch mode

Notice we built our schema using the one-shot command resgraph build. If you want to watch for changes and automatically rerun ResGraph, run resgraph watch. However, if you're also using VSCode, you're encouraged to instead use the ResGraph VSCode extension (Not yet available, coming very soon), which will run ResGraph in watch mode for you, show you errors and so on, directly inside of VSCode.

Excellent, we now have a schema! Let's hook it up to your server.

Hooking up your schema to GraphQL Yoga

ResGraph ships with GraphQL Yoga bindings, and we're using it to expose your schema. This is because Yoga is well maintained and well established in the ecosystem. However, hooking up ResGraph to other servers should be simple as well, since the primary artifact of ResGraph is just a graphql-js schema.

Let's expose your schema through GraphQL Yoga. Paste this into App.res:

// App.res
open GraphQLYoga

let yoga = createYoga({
schema: ResGraphSchema.schema,
context: async ({request}) => {
open ResGraphContext

{
currentUserId: request
->Request.headers
->Headers.get("x-user-id"),
}
},
})

let server = NodeHttpServer.createServer(yoga)

let port = 4555

server->NodeHttpServer.listen(port, () => {
Console.info(`Server is running on http://localhost:${port->Int.toString}/graphql`)
})

After this builds (npx rescript build, or just run the compiler in watch mode), you can go ahead and run node src/App.mjs and you have yourself the simplest possible server running.

Before we break down what we did and why, you can ensure everything works by going to GraphiQL and trying this query:

query {
currentTime
}

...which should give you back the current timestamp.

Now, let's break down what we did and why:

let yoga = createYoga({
schema: ResGraphSchema.schema,
context: async ({request}) => {
open ResGraphContext

{
currentUserId: request
->Request.headers
->Headers.get("x-user-id"),
}
},
})

Pulling out currentUserId is just to examplify that this is per-request context.

This creates your Yoga server by linking together your schema (from the generated file ResGraphSchema) to a function that produces your specific app context type.

We then create and start the http server exposing our schema:

let server = NodeHttpServer.createServer(yoga)

let port = 3000

server->NodeHttpServer.listen(port, () => {
Console.info(`Server is running on http://localhost:${port->Int.toString}/graphql`)
})

How does ResGraph work

At a high level, ResGraph works like this:

  • Scans your projects for @gql annotations
  • Reads type information, transforms the types and values annotated with @gql into a graphql-js schema

ResGraph runs on the compiled artifacts ReScript's compiler produces. So, ResGraph needs to run after the compiler runs. Don't worry though, ResGraph has it's own watcher and build process that's easy to use and handles all of this.

Next steps

There! We're all set up and your server is running. We can now continue our ResGraph journey by talking about how to define the primary building block of GraphQL - object types.