BaseClient

A BaseClient instance is the main endpoint you will use for interacting with a connected storage: listing, reading, creating, updating and deleting documents, as well as handling incoming changes.

Base clients are usually used in data modules, which are loaded with two BaseClient instances by default: one for private and one for public documents.

However, you can also instantiate a BaseClient outside of a data module using the remoteStorage.scope() function. Similarly, you can create a new scoped client within another client, using the BaseClient’s own scope().

Data read/write operations

A BaseClient deals with three types of data: folders, objects and files:

  • getListing() returns a mapping of all items within a folder.
  • getObject() and storeObject() operate on JSON objects. Each object has a type.
  • getFile() and storeFile() operates on files. Each file has a MIME type.
  • getAll() returns all objects or files for the given folder path.
  • remove() operates on either objects or files (but not folders; folders are created and removed implictly).

Caching logic for read operations

All functions requesting/reading data will immediately return data from the local store, as long as it is reasonably up-to-date. The default maximum age of requested data is two times the periodic sync interval (10 seconds by default).

However, you can adjust this behavior by using the maxAge argument with any of these functions, thereby changing the maximum age or removing the requirement entirely.

  • If the maxAge requirement is set, and the last sync request for the path is further in the past than the maximum age given, the folder will first be checked for changes on the remote, and then the promise will be fulfilled with the up-to-date document or listing.
  • If the maxAge requirement is set, and cannot be met because of network problems, the promise will be rejected.
  • If the maxAge requirement is set to false, or the library is in offline mode, or no remote storage is connected (a.k.a. “anonymous mode”), the promise will always be fulfilled with data from the local store.

Hint

If caching for the folder is turned off, none of this applies and data will always be requested from the remote store directly.

List of functions

getListing(path, maxAge)

Get a list of child nodes below a given path.

Arguments:
  • path (string) – The path to query. It MUST end with a forward slash.
  • maxAge (number) – (optional) Either false or the maximum age of cached listing in milliseconds. See Caching logic for read operations.
Returns:

Promise – A promise for an object representing child nodes

Example usage:

client.getListing('')
      .then(listing => console.log(listing));

The folder listing is returned as a JSON object, with the root keys representing the pathnames of child nodes. Keys ending in a forward slash represent folder nodes (subdirectories), while all other keys represent data nodes (files/objects).

Data node information contains the item’s ETag, content type and -length.

Example of a listing object:

{
  "@context": "http://remotestorage.io/spec/folder-description",
  "items": {
    "thumbnails/": true,
    "screenshot-20170902-1913.png": {
      "ETag": "6749fcb9eef3f9e46bb537ed020aeece",
      "Content-Length": 53698,
      "Content-Type": "image/png;charset=binary"
    },
    "screenshot-20170823-0142.png": {
      "ETag": "92ab84792ef3f9e46bb537edac9bc3a1",
      "Content-Length": 412401,
      "Content-Type": "image/png;charset=binary"
    }
  }
}

Warning

At the moment, this function only returns detailed metadata, when caching is turned off (new RemoteStorage({cache: false})). With caching turned on, it will only contain the item names as properties with true as value. See issues #721 and #1108 — contributions welcome!

getObject(path, maxAge)

Get a JSON object from the given path.

Arguments:
  • path (string) – Relative path from the module root (without leading slash).
  • maxAge (number) – (optional) Either false or the maximum age of cached object in milliseconds. See Caching logic for read operations.
Returns:

Promise – A promise, which resolves with the requested object (or null if non-existent)

Example:

client.getObject('/path/to/object')
      .then(obj => console.log(obj));
storeObject(typeAlias, path, object)

Store object at given path. Triggers synchronization.

See declareType() and data types for an explanation of types

Arguments:
  • type (string) – Unique type of this object within this module.
  • path (string) – Path relative to the module root.
  • object (object) – A JavaScript object to be stored at the given path. Must be serializable as JSON.
Returns:

Promise – Resolves with revision on success. Rejects with a ValidationError, if validations fail.

Example:

var bookmark = {
  url: 'http://unhosted.org',
  description: 'Unhosted Adventures',
  tags: ['unhosted', 'remotestorage', 'no-backend']
}
var path = MD5Hash(bookmark.url);

client.storeObject('bookmark', path, bookmark)
      .then(() => console.log('bookmark saved'))
      .catch((err) => console.log(err));
getAll(path, maxAge)

Get all objects directly below a given path.

Arguments:
  • path (string) – Path to the folder. Must end in a forward slash.
  • maxAge (number) – (optional) Either false or the maximum age of cached objects in milliseconds. See Caching logic for read operations.
Returns:

Promise – A promise for an object

Example response object:

// TODO

For items that are not JSON-stringified objects (e.g. stored using storeFile instead of storeObject), the object’s value is filled in with true.

Example usage:

client.getAll('').then(objects => {
  for (var path in objects) {
    console.log(path, objects[path]);
  }
});
getFile(path, maxAge)

Get the file at the given path. A file is raw data, as opposed to a JSON object (use getObject() for that).

Arguments:
  • path (string) – Relative path from the module root (without leading slash).
  • maxAge (number) – (optional) Either false or the maximum age of the cached file in milliseconds. See Caching logic for read operations.
Returns:

Promise – A promise for an object

The response object contains two properties:

mimeType String representing the MIME Type of the document.
data Raw data of the document (either a string or an ArrayBuffer)

Example usage (displaying an image):

client.getFile('path/to/some/image').then(file => {
  var blob = new Blob([file.data], { type: file.mimeType });
  var targetElement = document.findElementById('my-image-element');
  targetElement.src = window.URL.createObjectURL(blob);
});
storeFile(mimeType, path, body)

Store raw data at a given path.

Arguments:
  • mimeType (string) – MIME media type of the data being stored
  • path (string) – Path relative to the module root
  • body (string|ArrayBuffer|ArrayBufferView) – Raw data to store
Returns:

Promise – A promise for the created/updated revision (ETag)

Example (UTF-8 data):

client.storeFile('text/html', 'index.html', '<h1>Hello World!</h1>')
      .then(() => { console.log("Upload done") });

Example (Binary data):

var input = document.querySelector('form#upload input[type=file]');
var file = input.files[0];
var fileReader = new FileReader();

fileReader.onload = function () {
  client.storeFile(file.type, file.name, fileReader.result)
        .then(() => { console.log("Upload done") });
};

fileReader.readAsArrayBuffer(file);
remove(path)

Remove node at given path from storage. Triggers synchronization.

Arguments:
  • path (string) – Path relative to the module root.
Returns:

Promise

Example:

client.remove('path/to/object')
      .then(() => console.log('item successfully deleted'));

Change events

BaseClient offers a single event, named change, which you can add a handler for using the .on() function (same as in RemoteStorage):

client.on('change', function (evt) {
  console.log('data was added, updated, or removed:', evt)
});

Using this event, you can stay informed about data changes, both remote (from other devices or browsers), as well as locally (e.g. other browser tabs).

In order to determine where a change originated from, look at the origin property of the incoming event. Possible values are window, local, remote, and conflict, explained in detail below.

Example:

{
  // Absolute path of the changed node, from the storage root
  path: path,
  // Path of the changed node, relative to this baseclient's scope root
  relativePath: relativePath,
  // See origin descriptions below
  origin: 'window|local|remote|conflict',
  // Old body of the changed node (local version in conflicts; undefined if creation)
  oldValue: oldBody,
  // New body of the changed node (remote version in conflicts; undefined if deletion)
  newValue: newBody,
  // Old contentType of the changed node (local version for conflicts; undefined if creation)
  oldContentType: oldContentType,
  // New contentType of the changed node (remote version for conflicts; undefined if deletion)
  newContentType: newContentType
}

local

Events with origin local are fired conveniently during the page load, so that you can fill your views when the page loads.

Example:

{
  path: '/public/design/color.txt',
  relativePath: 'color.txt',
  origin: 'local',
  oldValue: undefined,
  newValue: 'white',
  oldContentType: undefined,
  newContentType: 'text/plain'
}

Hint

You may also use for example getAll() instead, and choose to deactivate these.

remote

Events with origin remote are fired when remote changes are discovered during sync.

Note

Automatically receiving remote changes depends on the caching settings for your module/paths.

window

Events with origin window are fired whenever you change a value by calling a method on the BaseClient; these are disabled by default.

Hint

You can enable them by configuring changeEvents for your RemoteStorage instance.

conflict

Events with origin conflict are fired when a conflict occurs while pushing out your local changes to the remote store.

Say you changed ‘color.txt’ from ‘white’ to ‘blue’; if you have set config.changeEvents.window to true (by passing it to the RemoteStorage constructor, see the Constructor section of the RemoteStorage API doc), then you will receive:

{
   path: '/public/design/color.txt',
   relativePath: 'color.txt',
   origin: 'window',
   oldValue: 'white',
   newValue: 'blue',
   oldContentType: 'text/plain',
   newContentType: 'text/plain'
 }

But when this change is pushed out by asynchronous synchronization, this change may be rejected by the server, if the remote version has in the meantime changed from ‘white’ to for instance ‘red’; this will then lead to a change event with origin ‘conflict’ (usually a few seconds after the event with origin ‘window’, if you have those activated). Note that since you already changed it from ‘white’ to ‘blue’ in the local version a few seconds ago, oldValue is now your local value of ‘blue’:

{
   path: '/public/design/color.txt',
   relativePath: 'color.txt',
   origin: 'conflict',
   oldValue: 'blue',
   newValue: 'red',
   oldContentType: 'text/plain',
   newContentType: 'text/plain',
   // Most recent known common ancestor body of local and remote
   lastCommonValue: 'white',
   // Most recent known common ancestor contentType of local and remote
   lastCommonContentType: 'text/plain'
 }

Data types

declareType(alias, uri, schema)

Declare a remoteStorage object type using a JSON schema.

See Defining data types for more info.

Arguments:
  • alias (string) – A type alias/shortname
  • uri (uri) – (optional) JSON-LD URI of the schema. Automatically generated if none given
  • schema (object) – A JSON Schema object describing the object type

Example:

client.declareType('todo-item', {
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "title": {
      "type": "string"
    },
    "finished": {
      "type": "boolean"
      "default": false
    },
    "createdAt": {
      "type": "date"
    }
  },
  "required": ["id", "title"]
})

Visit http://json-schema.org for details on how to use JSON Schema.

validate(object)

Validate an object against the associated schema.

Arguments:
  • object (Object) – JS object to validate. Must have a @context property.
Returns:

Object – An object containing information about validation errors

Example:

var result = client.validate(document);

// result:
// {
//   error: null,
//   missing: [],
//   valid: true
// }

Caching

cache(path, strategy)

Set caching strategy for a given path and its children.

See Caching strategies for a detailed description of the available strategies.

Arguments:
  • path (string) – Path to cache
  • strategy (string) – Caching strategy. One of ‘ALL’, ‘SEEN’, or ‘FLUSH’. Defaults to ‘ALL’.
Returns:

BaseClient – The same instance this is called on to allow for method chaining

Example:

client.cache('documents/', 'ALL');
flush(path)

TODO: document

Arguments:
  • path (string) –

Example:

client.flush('documents/');

Other functions

getItemURL(path)

Retrieve full URL of a document. Useful for example for sharing the public URL of an item in the /public folder.

Arguments:
  • path (string) – Path relative to the module root.
Returns:

string – The full URL of the item, including the storage origin

Warning

This method currently only works for remoteStorage backends. The issues for implementing it for Dropbox and Google Drive can be found at #1052 and #1054.

scope(path)

Instantiate a new client, scoped to a subpath of the current client’s path.

Arguments:
  • path (string) – The path to scope the new client to.
Returns:

BaseClient – A new client operating on a subpath of the current base path.