Advanced Topics

Network Status

The NetworkStatus interface can be used to check the current network status, or register a listener to perform certain actions when the status of the network changes.

Two default implementations are provided to support web browsers and Cordova. The following example demonstrates how to register a listener using CordovaNetworkStatus:

import { CordovaNetworkStatus, NetworkInfo } from '@aerogear/voyager-client';
const networkStatus = new CordovaNetworkStatus();

networkStatus.onStatusChangeListener({
  onStatusChange: info => {
    const online = info.online;
    if (online) {
      //client is online, perform some actions
    } else {
      //client is offline
    }
  }
});

let config = {
  ...
  networkStatus: networkStatus,
  ...
};

//create a new client using the config

Logging Debug Messages

The Voyager Client uses the debug module to log debug messages.

To enable debug logs, run the following code in a browser’s console:

localStorage.debug = 'AeroGearSync:*'

Certain features can be enabled separately:

localStorage.debug = 'AeroGearSync:OfflineMutations*'

Optimistic UI

By default mutations are not applied to the UI until responses are received from the server. To provide better user experience, an application may want to update the UI immediately. Optimistic response is an easy way to achieve this goal, and Voyager Client provides a helper method to work with optimistic responses:

 import { createOptimisticResponse } from "@aerogear/voyager-client";

 client.mutate({
   mutation: ADD_TASK,
   variables: item,
   optimisticResponse: createOptimisticResponse("createTask", "Task", item);
 });

To detect if the provided data is an optimistic response, the optimisticResponse flag can be used.

The OptimisticResponse feature and the offlineQueueListener can be used together to deliver great offline experience for an application.

See the Showcase Apps section for more information.

Cache Update Helpers

Voyager Client provides an out of the box solution for managing updates to your application’s cache. It can intelligently generate cache update methods for both mutations and subscriptions.

Mutations

The following example shows how to use these helper methods for mutations. To use these methods, create an offline client as described in [offline-client] and then use the offlineMutation method. The offlineMutation function accepts a MutationHelperOptions object as a parameter.

const { createMutationOptions, CacheOperation } = require('@aerogear/voyager-client');

const mutationOptions = {
  mutation: ADD_TASK,
  variables: {
    title: 'item title'
  },
  updateQuery: {
    query: GET_TASKS,
    variables: {
      filterBy: 'some filter'
    }
  },
  typeName: 'Task',
  operationType: CacheOperation.ADD,
  idField: 'id'
};

We can also provide more than one query to update in the cache by providing an array to the updateQuery parameter:

const mutationOptions = {
  ...
  updateQuery: [
    { query: GET_TASKS, variables: {} }
  ]
  ,
  ...
};

The following example shows how to prepare an offline mutation to add a task using the mutationOptions object and how to update the GET_TASK query for the client’s cache.

const { createMutationOptions, CacheOperation } = require('@aerogear/voyager-client');

client.offlineMutation<Task>(mutationOptions);

If you do not wish to use the offline client you can also use the createMutationOptions function directly. This function provides an Apollo compatible MutationOptions object to pass to your pre-existing client. This is shown below where mutationOptions is the same object shown in the above code example.

const options = createMutationOptions(mutationOptions);

client.mutate<Task>(options);

Subscriptions

Voyager Client also provides a subscription helper which can generate the necessary options to be used with Apollo Client’s subscribeToMore function.

To use this helper, we first need to create some options. These options should take the folowing form:

const { CacheOperation } = require('@aerogear/voyager-client');

const options = {
  subscriptionQuery: TASK_ADDED_SUBSCRIPTION,
  cacheUpdateQuery: GET_TASKS,
  operationType: CacheOperation.ADD
}

This options object will be used to inform the subscription helper that for every data object received because of the TASK_ADDED_SUBSCRIPTION the GET_TASKS query should also be kept up to date in the cache.

We can then create the required cache update functions in the following way:

const { createSubscriptionOptions } = require('@aerogear/voyager-client');

const subscriptionOptions = createSubscriptionOptions(options);

To use this helper we then pass this subscriptionOptions variable to the subscribeToMore function of our ObservableQuery.

const query = client.watchQuery<AllTasks>({
  query: GET_TASKS
});

query.subscribeToMore(subscriptionOptions);

The cache will now be kept up to date with automatic data deduplication being performed.

Multiple Subscriptions

Voyager Client also provides the ability to automatically call subscribeToMore on your ObservableQuery. This can be useful in a situation where you may have multiple subscriptions which can affect one single query. For example, if you have a TaskAdded, TaskDeleted and a TaskUpdated subscription you would need three separate subscribeToMore function calls. This can become tedious as your number of subscriptions grow. To combat this, we can use the subscribeToMoreHelper function from Voyager Client to automatically handle this for us by passing it an array of subscriptions and their corresponding queries which need to be updated.

const { CacheOperation } = require('@aerogear/voyager-client');

const addOptions = {
  subscriptionQuery: TASK_ADDED_SUBSCRIPTION,
  cacheUpdateQuery: GET_TASKS,
  operationType: CacheOperation.ADD
}

const deleteOptions = {
  subscriptionQuery: TASK_DELETED_SUBSCRIPTION,
  cacheUpdateQuery: GET_TASKS,
  operationType: CacheOperation.DELETE
}

const updateOptions = {
  subscriptionQuery: TASK_UPDATED_SUBSCRIPTION,
  cacheUpdateQuery: GET_TASKS,
  operationType: CacheOperation.REFRESH
}

const query = client.watchQuery<AllTasks>({
  query: GET_TASKS
});

subscribeToMoreHelper(query, [addOptions, deleteOptions, updateOptions]);