remoteStorage.js

repository·master·Indexed 25 days ago

https://github.com/remotestorage/remotestorage.js

A JavaScript library for local browser storage and synchronization with remoteStorage servers, Dropbox, or Google Drive. It provides the BaseClient for CRUD operations on folders, JSON objects, and files, as well as the Access class for managing scope permissions. Features include local caching with configurable maxAge, data change event handling, conflict resolution, and JSON Schema validation via declareType().

Tokens
21.5K
Snippets
61
Records
146
Agent score
81%

What's inside remotestorage.js

  1. Overview of remoteStorage.js

    master

    remoteStorage.js is a JavaScript library designed for storing user data locally in the browser and connecting to remoteStorage servers. It enables syncing data across different devices and applications.

    Key capabilities include:

    • Local browser storage.
    • Connection and synchronization with remoteStorage servers.
    • Optional connection and synchronization with Dropbox or Google Drive accounts.
  2. Understand the Remote interface

    master
    The Remote interface defines the core contract for all remote storage implementations in remoteStorage.js. Any object implementing this interface can be used by the library to perform storage operations. To use a specific storage backend (like S3, Dropbox, or a local server), you must use a class that implements this Remote interface.
  3. Manage caching and data freshness with maxAge

    master

    By default, BaseClient read operations return data from the local store if it is reasonably up-to-date (the default maximum age is 20 seconds, which is twice the 10s periodic sync interval).

    You can control this behavior using the maxAge argument in read functions:

    • Set a specific maxAge: If the last sync for the path is older than maxAge, the client will check the remote storage for changes before fulfilling the promise.
    • Set maxAge: false: The client will always return data from the local store. This is also the behavior used when the library is in offline mode or in "anonymous mode" (no remote storage connected).
    • Network Failures: If a maxAge requirement is set but cannot be met due to network issues, the promise will be rejected.

    Note: If caching for a specific folder is turned off via the Caching configuration, maxAge is ignored and data is always requested from the remote store directly.

  4. Build unhosted apps with zero backend using remoteStorage.js

    master

    remoteStorage.js is designed for creating unhosted applications. This model shifts the responsibility of data management from the developer to the user:

    • User Privacy: Users connect their own storage accounts, meaning they do not have to trust app developers with their private data.
    • Zero Infrastructure Cost: Developers can scale to millions of users without incurring storage, management, or security costs for data.
    • Longevity: If an app is abandoned, users can still access their data across devices. If the app is revived, the user data remains intact and ready for use.
  5. Enable data sharing and interoperability

    master

    Because remoteStorage.js uses a standardized approach, different applications can access and manipulate the same data. This eliminates the need for manual import/export features.

    Developers can also leverage shared, open-source data modules to add advanced capabilities to their apps. For example, integrating the shares module allows for features like client-side thumbnail generation for images.

  6. Resolve data conflicts in BaseClient

    master

    A conflict event occurs when your local changes cannot be applied to the remote store because the remote version has changed since your last sync.

    Conflict Event Structure

    A conflict event includes the following additional fields to help with resolution:

    • lastCommonValue: The body when local and remote last agreed.
    • lastCommonContentType: The content type when local and remote last agreed.

    How to Resolve

    Conflicts must be resolved on the device where the conflict surfaced. Other devices are not notified of the conflict.

    1. Manual Resolution: Display both the local and remote versions to the user and have them choose which version to keep or how to merge them.
    2. Automatic Resolution: If a merge algorithm exists for the data type, the conflict may be resolved automatically.
    3. Resolution via API: To resolve the conflict, call storeObject() or storeFile() with the resolved data. This will overwrite the remote version with your new version.
  7. Understand the concept of Data Modules

    master

    Data modules are add-on libraries designed to make app data interoperable within the remoteStorage protocol. Instead of using proprietary APIs, apps use shared data modules to handle common tasks. This allows different applications to interact with the same user data (e.g., one app creates a to-do item, and another app tracks time on that same item).

    Data modules can be used for:

    • Defining data formats and types
    • Data validation
    • Formatting and processing
    • Data transformation
    • Encryption
    • Indexing
  8. Handle data change events with BaseClient

    master

    A BaseClient emits change events whenever data is added, updated, or removed. You can subscribe to these using .on('change', handler) or .addEventListener('change', handler).

    To determine the source of a change, inspect the origin property of the event object. The possible values are:

    • local: Fired during page load to help populate views with existing local data.
    • remote: Fired when changes are discovered on the remote storage during a sync process.
    • window: Fired when a change is made via a method call on the BaseClient in the current window (disabled by default; must be enabled in RemoteStorage config).
    • conflict: Fired when a push of local changes is rejected by the server because the remote version changed in the meantime.
    client.on('change', function (evt) {
      console.log('data was added, updated, or removed:', evt)
    });
  9. Use a single JS API for multiple storage backends

    master

    remoteStorage.js provides a unified JavaScript API that works across different storage providers. This allows developers to support multiple backends without writing provider-specific logic.

    • Supported Backends: Includes Dropbox and Google Drive (and others).
    • Implementation: To support these backends, you simply need to configure OAuth app keys.
    • UI Integration: If you are not using the built-in connect widget, you will need to implement your own UI to allow users to choose and connect to their preferred backend.
  10. Define a remoteStorage data module

    master

    A data module is a JavaScript object used to extend RemoteStorage with custom logic and data management. It must contain two properties:

    1. name: A string representing the module's identifier.
    2. builder: A function that is called when the module is loaded.

    The builder function receives two BaseClient instances as arguments:

    • privateClient: For managing data stored in /[module-name]/.
    • publicClient: For managing data stored in /public/[module-name]/.

    The builder must return an object containing an exports property. The exports object defines the API (functions and properties) that will be exposed on the RemoteStorage instance.

    Example structure:

    const MyModule = {
      name: 'my-module',
      builder: function(privateClient, publicClient) {
        return {
          exports: {
            myFunction: function() {
              // Use privateClient or publicClient here
            }
          }
        };
      }
    };
    const Bookmarks = {
      name: 'bookmarks',
      builder: function(privateClient, publicClient) {
        return {
          exports: {
            addBookmark: function() {}
          }
        }
      }
    };