Using the GraphQL Client

Last updated 28 days ago

Sample

Since the GraphQL API is just a regular HTTP API, any HTTP client can send GraphQL queries. To make it easier to get started, Realm provides a few helper and convenience APIs for the Apollo Client, a popular Javascript client that supports a variety of web frameworks as well as Node.js.

Here's a minimal getting started example:

const credentials = Credentials.usernamePassword('SOME-USERNAME', 'SOME-PASSWORD');
const user = await User.authenticate(credentials, 'http://my-ros-instance:9080');
const config = await GraphQLConfig.create({
user: user,
realmPath: '/~/test'
});
const client = config.createApolloClient();
// You can now query the GraphQL API
const response = await client.query({
query: gql`
query {
people(query: "age > 18", sortBy: "name") {
name
age
}
}
`
});
const people = response.data.people;

Looking for the client API reference docs? They're here.

Prerequisites

Add the Realm GraphQL client package:

npm install realm-graphql-client --save

Authenticating the user

To start consuming the GraphQL API, you'll need to login a User:

The sample below uses our Javascript SDK. It is likely that you'll want to authenticate via a REST call. For more details, head over to the auth section of the GraphQL API.

Node.js
const credentials = Credentials.usernamePassword('SOME-USERNAME', 'SOME-PASSWORD');
const user = await User.authenticate(credentials, 'http://my-ros-instance:9080');

Other credential providers are supported, such as JWT, Facebook, Google, etc. They are all exposed as factories on the Credentials class. If you passed disableAuthentication: true when creating the GraphQL service, you can also authenticate with an anonymous user:

const credentials = Credentials.anonymous();
const user = await User.authenticate(credentials, 'http://my-ros-instance:9080');

After you have your user, you can create a GraphQLConfig that will handle token refreshes and authentication by passing in the user and the realmPath

const config = await GraphQLConfig.create({
user,
`/~/test`
});

Note that each config is created per Realm path, so if you need to query multiple Realms, you'll need to obtain a config instance for each of them.

Setting up the Client

Once you have a config, you can use that to create an Apollo client instance and configure it. The config exposes 4 properties:

  • httpEndpoint: This is the endpoint you'll use to execute queries and mutations against. It can be used to configure Apollo's httpLink.

  • authLink: This is a link that provides an Authorization header for the user/path combination. It should be composed together with your httpLink.

  • webSocketEndpoint: This is the endpoint you'll use to execute subscriptions against. It can be used to configure Apollo's WebSocket Link.

  • connectionParams: This is a function that will provide an authorization object each time a websocket connection is established. You should pass that directly (without invoking it) to the WebSocketLink's constructor's options.

const httpLink = concat(
config.authLink,
// Note: if using node.js, you'll need to provide fetch as well.
new HttpLink({ uri: config.httpEndpoint })
);
// Note: if using node.js, you'll need to provide webSocketImpl as well.
const subscriptionLink = new WebSocketLink({
uri: config.webSocketEndpoint,
options: {
connectionParams: config.connectionParams,
}
});

Queries

Querying data is as simple as invoking client.query():

const response = await client.query({
query: gql`
query {
companies {
companyId
name
address
}
}
`
});
const companies = response.data.companies;

For a complete list of supported query operations, refer to the GraphQL API docs.

For a detailed documentation on the Apollo Client query capabilities, refer to the Apollo docs.

Mutations

Mutating data happens when you invoke the client.mutate()method:

const response = await client.mutate({
mutation: gql`
mutation {
result: addCompany(input: {
companyId: "some-unique-id"
name: "My Amazing Company"
address: "Mars"
}) {
companyId
name
address
}
}
`
});
const addedCompany = response.data.result;

For a complete list of supported mutation operations, refer to the GraphQL API docs.

For a detailed documentation on the Apollo Client mutation capabilities, refer to the Apollo docs.

Subscriptions

Subscribing for changes happens when you invoke the client.subscribe() method. You get an Observable sequence you can then add an observer to:

const observable = await client.subscribe({
query: gql`
subscription {
companies {
companyId
name
address
}
}
`
});
observable.subscribe({
next(data) {
const companies = data.data.companies;
// Update you UI
},
error(value) {
// Notify the user of the failure
}
});

For a complete list of supported subscription operations, refer to the GraphQL API docs.

For a detailed documentation on the Apollo Client subscription capabilities, refer to the Apollo docs.

Query-Based Sync Support

As of the 1.3.0 release of the GraphQL client, we offer beta support for working with query-based sync Realms. We aim to continue to improve performance before upgrading to official support.

To open a Realm in query-based mode, supply true as 4th argument to the GraphQLConfig.create call:

GraphQLConfig.create(
user,
"/someReferenceRealm",
/* authErrorHandler */ (err) => {
console.error(err);
},
/* isQueryBasedSync */ true,

Just like our other SDKs, you will need to create subscriptions to view your data. Subscriptions can be created by invoking a createMyModelSubscription mutation, deleted by invoking a deleteQueryBasedSubscription mutation, and viewed by invoking the queryBasedSubscriptionsquery.

More details in the release notes.

Errors:

Cannot access realm that has been closed.

Realm's GraphQL Service works by querying cached Realm files from the server. While these cached files should always be available, there are a few rare conditions where they may get closed. In this event, you'll want to reach out to our support team. When you do this please provide the following: instance information (i.e. cloud URL or self-hosting version information for all packages) and a reproduction case.

Schema appears to be cached to an old version

Over time, we will automatically invalidate and update your schema for you. You can also do this manually via a specific endpoint call.

Invalid options provided to ApolloServer: Type "Some-Type" not found in document.

This error can occur if you have a model which has no properties and another model links to it. For example, you might be creating your Realms and schema via Studio piece by piece. To resolve this, simply add some properties to your empty model.