AeroBase Apollo GraphQL Voyager client

Usage no npm install needed!

<script type="module">
  import aerobaseDatasyncJs from 'https://cdn.skypack.dev/@aerobase/datasync-js';


AeroBase Apollo GraphQL Voyager client

Client SDK for Apollo Voyager Server

Getting Started

Importing the package

import {
} from '@aerobase/datasync-js';


To provide custom configuration to the client, the following options are available. If you wish, these are also available by using the DataSyncConfig interface from the SDK.

let config: DataSyncConfig = {
  httpUrl: "http://localhost:4000/graphql",
  wsUrl: "ws://localhost:4000/graphql",
Config Description Default
httpUrl The URL of your http server N/A
wsUrl The URL of your websocket N/A
storage The storage you want your client to use window.localStorage
conflictStrategy The conflict resolution strategy your client should use N/A
customLinkBuilder Enables providing custom Apollo Link for processing requests See LinksBuilder
networkStatus Implementation of NetworkStatus Interface See WebNetworkStatus and CordovaNetworkStatus
mutationsQueueName The name to store requests under in your offline queue "offline-mutation-store"
mergeOfflineMutations Whether or not you wish to squash mutations in your queue true
offlineQueueListener listener that can be configured to receive events from offline queue undefined

Creating a Client

let client = createClient(config);

Example application

Try SDK using sample application: https://github.com/aerobase/apollo-voyager-ionic-example

Basic concepts

Client is basing on Apollo GraphQL client that can be used with various web and mobile frameworks. We provide version for web and Apache Cordova. For basic concepts about Apollo GraphQL please refer to documentation for your own platform.

For React: https://www.apollographql.com/docs/react/

For Angular: https://www.apollographql.com/docs/angular/


Client is strongly leveraging Apollo Cache layer. Please follow documentation for more information about caching in Apollo GraphQL


Querying your data

Cache is used to hold data that can be fetched when client is offline. To effectively work with cache users can use cache-first fetchPolicy when performing queries. This policy will try to use local cache in situations when cache was already populated with the server side data.

    return this.apollo.watchQuery<YourType>({
      query: YOUR_QUERY,
      fetchPolicy: 'cache-first',

Cache is going to be refueled by subscriptions, pooling or regular queries happening in UI.

Designing your types

When designing your GraphQL schema types id field will be always required. We also expect that id will be always queried back from server. Library will perform business logic assuming that id field will be supplied and returned from server. Without this field some offline functionalities will not work properly.

Offline support

SDK provides first class support for performing GraphQL operations while offline. Queries and mutations are hold in queue that is being configured to hold requests when client goes offline. When client goes offline for long periods of time clients will be able still negotiate local updates with the server state thanks to powerful conflict resolution strategies.

Client offers comprehensive set of features to perform data operations when offline. Thanks to offline mutation store users can stage their changes to be replicated back to server when becoming online:

Please follow chapters bellow for more information.

Querying local cache

By default client will save all performed query results in the cache. Data will be available to be used when application goes offline. Queries are cached out of the box based on the type and id field. When performing mutations that affects some queries users can use refetchQueries or update methods:

      mutation: ADD_TASK, variables: item,
      optimisticResponse: createOptimisticResponse('createTask', 'Task', item),
      update: this.updateCacheOnAdd

Making modifications when offline

AeroBase Sync SDK provides queue that stores mutations performed when offline. By default queue saves data in storage to be available after application restarts. Queue will hold requests until application will come back online.

Developers can adjust how queue will process new mutations by supplying custom NetworkStatus implementation.

Online Only Queries

To ensure certain queries are not queued and are always delivered to the network layer, you must make use of Graphql directives. To do so on your client, ensure the query has the annotation attached like so:

exampleQuery(...) @onlineOnly {

Squashing Mutations

Multiple changes performed on the same object ID and with the same mutation will automatically be joined by the AeroBase Sync SDK when your client is offline. This is beneficial as the client will not have to queue a large amount of mutations to replay once it returns online.

Global Squashing

This feature is on by default at a global level. To disable it on a global level simply do so in your config:

let config = {
  mergeOfflineMutations: false

Mutation Level Squashing

To disable this feature at a mutation level be sure to include the annotation on the mutation like so:

exampleMutation(...) @noSquash {


SDK offers way to detect conflicts that happened on the server.

Conflict strategies

You can provide your custom conflict resolution strategies to the client in the config by using the provided ConflictResolutionStrategy type from the SDK. An example custom strategy is shown below.

let clientWins = (serverData, clientData) => {
  return Object.assign(server, client);

To use this strategy pass this function as conflictStrategy in your config object like so:

let config = {
  conflictStrategy: clientWins

Advanced topics

Implementing Custom Apollo Links

To use your own custom apollo links to create your own set of operation processors, simply follow the documentation for creating links here: https://www.apollographql.com/docs/link/index.html. You can pass this building mechanism to your client in the config, under the customLinkBuilder parameter.

export const linkBuilder: LinkChainBuilder = (): ApolloLink => {
    const httpLink = new HttpLink({ uri: "someUri" });
    const customLink = new YourCustomLink();

    let links: ApolloLink[] = [customLink, httpLink];

    let compositeLink = ApolloLink.from(links);
    return compositeLink;

Implementing Custom Network Status checks

To use your own custom network checks, implement the NetworkStatus interface which provides two functions;

  onStatusChangeListener(callback: NetworkStatusChangeCallback): void;

  isOffline(): boolean;

Logging debug messages

Sync package is using debug package to print out debug messages

To enable debug please execute in console localStorage.debug = 'AeroBaseSync:*'

Some certain features can be enabled separately

localStorage.debug = 'AeroBaseSync:OfflineMutations*'

Optimistic UI

By default user changes that are made when offline will not appear in the app until they going to be synced to server. In some circumstances users may want to see them instantly to perform various operations on the data When performing mutations users can decide to supply optimisticResponse object that will appear instantly in the application UI. SDK provides helper method to work with optimistic responses.

 import { createOptimisticResponse } from "@aerobase/datasync-js";

 createOptimisticResponse("updateTest", "Test", { data: "test" });

Users can detect if the provided data is optimistic response by checking optimisticResponse flag is set to true.

Note: pending changes created by helper are read only. Performing any additional operations on pending objects will result in error due to fact that next changes will be missing actual ID that can be created on server side.

Mapping Client and Server ID for Optimistic Reponses

When using OptimisticReponse helper from SDK specific mutations that create new element response is going to have client side generated id. Subsequent edits for this objects will also refer to this id. When becoming online, all offline changes are going to be performed in specific order invalidating client side id for subsequent edits. If edits for objects created when offline are required, developers need to support a way to map them in their resolvers.

Listening to the offline queue events

Developers can implement offlineQueueListener that can be passed as config element. This listener is going to be notified about new items that were added to offline queue. Listener can be used to build UI support and show pending changes. This feature can be mixed together with OptimisticResponse to deliver great offline experience See example application for more information.