This module consists of two components for achieving offline capability, a DataCache for reads and an UpdateQueue for writes:
- DataCache is a cache for HTTP (GET) data, backed by a PouchDB database that's continuously synced from a remote master database so that the cache contains all your data when you're offline.
- UpdateQueue is a persistent queue for HTTP (POST and PUT) requests that will handle queing requests to the server and sending them when a connection becomes available.
The DataCache is designed to act as a transparent proxy to your remote backend. The cache interface is similar to jQuery's ajax method, so it's often trivially easy to switch to loading data from the cache.
import DataCache from 'offline-data/data-cache';
var cache = new DataCache('dbname', 'http://my-replication-master/dbname');
cache.get('/api/products/1')
.then(function(json) {
console.log(json); // => {name: 'buy me'}
});
You should populate a CouchDB (or pouch-server) with the documents that you want to be available offline, and the DataCache will replicate these documents down to all of your clients. The documents in the cache should have the following structure:
{
_id: '/api/endpoint', // the ID is the URI
data: {} // the data property contains the body of the response
}
There's also an ember-cli addon for use with Ember, and which also provides a Mixin for integrating with Ember Data.
Creates a new DataCache instance for accessing the data in the upstream
database.
@param dbName {string|PouchDB}
Defines the name of the PouchDB database to be used to store the local data.@param upstream {string|PouchDB}
The remote (CouchDB-ish) server that contains the data to be replicated into the local database.@param [opts] {object}
An options hash.pouch
options for the call to thePouchDB
constructor.verbose
Log all replication events to the console
Performs a lookup in the cache for the specified URI.
@param uri {string}
The URI to return from the cache@param options {object}
A hash of options, uses the same structure as the jQuery#ajaxsettings
parameter. Request parameters should be provided inoptions.data
.@returns Promise
A Promise that yields the response. The promise will fail withstatus: 404
if the URI is not found.
Allows a fallback function to be used to provide the content if it's not in the cache. For example, this can be used to fallback to an HTTP request on cache misses. fn
may return a value or a Promise.
cache.fallbackTo(function(uri, options) {
return jQuery.json(uri, options);
});
Allows you to use a function to handle a call to get()
the specified uri
. This is a core feature, for example:
- You can use a route handler to construct a listing, e.g. of products. This allows you to avoid having to cache (and replicate) big listings of data - just keep the individual items and construct the listing on the client.
- Providing search and filtering functionality on the client side
cache.route('/api/products', function(dataCache, uri, options) {
return Promise.resolve({the: 'response'});
});
You can provide a handler function, but you'll generally want to use a instance of the Handler
class (see below).
@param uri {string|RegExp}
The URI to be handled, or a RegExp@param fn {function|object}
A handlerfunction(DataCache, options)
(theoptions
argument from the call toget()
).
If an object is provided then itsget()
method will be called, with the same arguments.@return {Promise}
A Promise that yields the response.
Returns a map function that emits any documents whose keys match the provided regular expression.
Returns a map function that emits any documents whose keys start with the specified prefix.
The json-api
package provides a handler, formatter and filter suitable for using with RESTful endpoints that use the jsonapi.org format (used by Ember Data).
import {JsonApiHandler} from 'offline-data/json-api';
// select all records which have a URI that matches /api/products/:id
var map = new RegExp('^/api/products/\\d+$');
// and return a JSON API-formatted listing from /api/products
cache.route('/api/products', new JsonApiHandler(map, 'product'));
UpdateQueue is a persistent queue for HTTP update requests (POST and PUT) that will handle queing requests and sending them when a connection becomes available. Updates are guaranteed to be sent in the same order that they're created (FIFO).
import UpdateQueue from 'offline-data/update-queue';
var queue = new UpdateQueue('dbname', jQuery.ajax);
queue.push({
type: 'POST',
url: '/api/order',
data: {
products: [1, 2, 3]
}
}); // this POST request will be queued and send as soon as a connection is available
Creates a new UpdateQueue instance that will use the senderFn
thunk to send requests.
@param dbName {string|PouchDB}
Defines the name of the PouchDB database to be used to store the local data.@param senderFn {function}
A function that is responsible for sending the requests. Takes a single argument which is the value that was provided topush()
@param [opts] {object}
An options hash.pouch
options for the call to thePouchDB
constructor.autoDrain
Controls whether calls topush()
will automatically schedule updates to be sent (defaults totrue
)
Adds an update to the queue, to be sent as soon as a connection is available. Updates are guaranteed to be sent in the same order that they're created (FIFO). Will also schedule an attempt to send any pending updates to be sent.
@param update {object}
The data be provided to thesenderFn
when the update is sent.@returns {Promise}
Resolves when the update has been successfully saved into persistent storage to be sent as soon as possible.
Schedule updates to be sent after later
milliseconds.
@param [later] {int}
Defaults to now@return {Promise}
Resolves with the result of the call todrain()
Sends any pending updates in the order that they were created. Prevents more than one drain operation from happening in parallel.
@return {Promise}
Resolves when all pending updates have been sent.