firesync-node

1.1.1 • Public • Published

Firesync - Overview

Join the chat at https://gitter.im/gngeorgiev/firesync

Build Status Code Climate GitHub license dependencies version

NPM


firesync is a library for seamless data synchronization between Firebase your local data and optionally the DOM, without the need of a framework, also known as three-way-data-binding.

The illustration below should help you understand how firesync works.

firesync

Three-way-data-binding


The three-way-data-binding is a binding where the model, view and database are all updated simulateniously without extra code. Firesync achieves this by using RactiveJS for its DOM binding. One should be familiar with RactiveJS when using the dom binding.

Requirements


firesync runs equally well in browsers and in node. Since it uses Object.observe to watch for local changes a polyfill should be used in environments that do not support it.

Installation and usage


bower

bower install firesync

<script src="bower_components/firesync/dist/firesync.js"></script>

nodejs

npm install firesync-node

var firesync = require('firesync-node');

Examples


Firebase to Firesync

Basic

var ref = new Firebase('https://example.firebaseio.com/users/admin'); // null
ref.once('value', function (snap) {
    var val = snap.val();
    val.name === 'admin';
    val.email === 'admin@admin.admin';
});
 
var admin = new firesync.FiresyncObject(ref);
admin.name = 'admin';
admin.dateCreated = new Date().valueOf().toString();
admin.email = 'admin@admin.admin';
//these changes will be automatically synced to the server

Firesync object synchronized from the database first

var ref = new Firebase('https://example.firebaseio.com/users/admin'); // {name: 'admin'}
var adminUser = new firesync.FiresyncObject(ref);
 
//the user might have already loaded
if (!adminUser.loaded()) {
    //in most cases you would not need to explicitly attach to events
    adminUser.once('loaded', function () {
        var name = adminUser.name;
    
        adminUser.once('synced', function () {
            //https://example.firebaseio.com/users/admin now is - {name: '__invalid'}
        });
    
        adminUser.name = '__invalid';
    });
}

Firesync object synchronized from local first

var ref = new Firebase('https://example.firebaseio.com/users/newUser'); // null
var newUser = new firesync.FiresyncObject(ref);
newUser.name = 'newUser';
newUser.once('synced', function () {
    //https://example.firebaseio.com/users/newUser now is - {name: 'newUser'}
});

Firesync array synchronized from database first

var ref = new Firebase('https://example.firebaseio.com/users'); // [{name: 'admin'}, {name: 'newUser'}]
var users = new firesync.FiresyncArray(ref);
 
//the array can be already loaded
if (!users.loaded()) {
    //we do not need to use loaded to add values
    users.once('loaded', function () {
        //users = [{name: 'admin'}, {name: 'newUser'}]
        users[0].name === 'admin';
        users[1].name === 'newUser';
        
        users.add({
          name: 'newUser2'
        });
        
        //this will immediately push newUser2 to the remote array
    });
}

Firebase to Firesync to DOM

Binding to an input element with inline template:

<div id="container"></div>
var ref = new Firebase('https://example.firebaseio.com');
var bindChild = ref.child('currentItem'); // { value: 'test' }
 
var currentItem = new firesync.FiresyncObject(bindChild)
    .bindTo({
        el: '#container',
        template: '<input type="text" value="{{value}}" />'
    });
 
//this results in the following html <div id="container"><input type="text" value="test" /></div>
 
currentItem.value = 'test123';
 
//this results in the following html <div id="container"><input type="text" value="test123" /></div>
 
//writing in the input will also change the .value property

Binding to an input element with external template:

<div id="container"></div>
 
<script type="text/ractive" id="template">
    <input type="text" value="{{value}}" />
</script> 
var ref = new Firebase('https://example.firebaseio.com');
var bindChild = ref.child('currentItem'); // { value: 'test' }
 
var currentItem = new firesync.FiresyncObject(bindChild)
    .bindTo({
        el: '#container',
        template: '#template'
    });
 
//this results in the following html <div id="container"><input type="text" value="test" /></div>
 
currentItem.value = 'test123';
 
//this results in the following html <div id="container"><input type="text" value="test123" /></div>
 
//writing in the input will also change the .value property

Bind to a list.

<div id="container"></div>
 
<script type="text/ractive" id="template">
    <ul>
        {{#iterator}} //iterator is a built-in variable of FiresyncArray which is an iteratable array compatible with ractivejs since ractivejs does not support array mixins.
        <li>{{value}}</li>
        {{/iterator}}
    </ul>
</script> 
var ref = new Firebase('https://example.firebaseio.com');
var bindChild = ref.child('currentItem'); // { '-Ju5kIB-e3ZABIccrOjK': { value: 'test' }, '-Mb4kIBa-3ZABIaarOjK': { value: 'test2' } }
 
var array = new firesync.FiresyncArray(bindChild)
    .bindTo({
        el: '#container',
        template: '#template'
    });
 
/* 
* this results in the following html:
* <div id="container">
*   <ul>
*       <li>test</li>
*       <li>test2</li>
*   </ul>
* </div>
*/
 
array.add({value: 'test3'});
 
/* 
* this results in the following html:
* <div id="container">
*   <ul>
*       <li>test</li>
*       <li>test2</li>
*       <li>test3</li>
*   </ul>
* </div>
*
* And to something like this in the firebase: 
* { '-Ju5kIB-e3ZABIccrOjK': { value: 'test' }, '-Mb4kIBa-3ZABIaarOjK': { value: 'test2' }, '-Vb6kFBa-3ZABIaarOmH': { value: 'test2' } }
*/

Firesync utility methods

firesync.create - Automatically creates a synchronized object or array based on the underlying firebase value. The created objects are guaranteed to be loaded.

var ref = new Firebase('https://example.firebaseio.com/users/fred'); //{name: 'fred'}
firesync.create(ref)
    .then(function (firesyncObj) {
        firesyncObj.name === 'fred';
        firesyncObj.loaded() === true;
    });
    
var usersRef = new Firebase('https://example.firebaseio.com/users'); //[{name: 'admin'}, {name: 'fred'}];
firesync.create(usersRef)
    .then(function (firesyncArr) {
        firesyncArr.lenght() === 2;
        firesyncArr.loaded() === true;
        firesyncArr[0].name === 'admin';
    });
 

firesync.map - Returns a non-synchronized object or array, depending on the underlying firebase value. Each object in the returned object/array is a synchronized FiresyncObject or FiresyncArray depending on the underlying firebase value. The objects are guaranteed to be loaded.

    var usersRef = new Firebase('https://example.firebaseio.com/users'); //[{name: 'admin'}, {name: 'fred'}];
    firesync.map(usersRef)
        .then(function (arr) {
            Array.isArray(arr) === true;
            arr[0] instanceof firesync.FiresyncObject === true;
            arr[1] instanceof firesync.FiresyncObject === true;
            
            //changes to arr will not reflect the changes to the remote data, but changing any of the inner objects will
        });
        
    var someRef = new Firebase('https://example.firebaseio.com/someRef'); //{someObj: {name: 'admin'}, someArr: [1, 2]};
    firesync.map(someRef)
        .then(function (obj) {
            typeof obj === 'object';
            obj.someObj instanceof firesync.FiresyncObject;
            obj.someArr instanceof firesync.FiresyncArray;
            
            //changes to obj will not reflect the changes to the remote data, but changing any of the inner objects will
        });

Important !!!


Whenever you are done with any FiresyncObject or FiresyncArray make sure to call the detach() method as it will unattach the inner firebase listeners.

API Reference


Classes

firesync

The entry point of firesync.

## External
FirebaseRef

FirebaseRef object

RactiveJs

RactiveJs object

## firesync The entry point of firesync.

Kind: global class

firesync.FiresyncArray ⇐ FiresyncBase

An array which keeps its values synchronized with the remote. One should use the FiresyncArray methods to manipulate the values.

Kind: static class of firesync
Extends: FiresyncBase
Mixes: Array
Access: protected

firesyncArray.iterator : Array

A simple array which is in sync with the FiresyncArray.

Kind: instance property of FiresyncArray
Example

firesyncArray.bindTo({el: 'body', template: '{{#iterator}}<div>{{value}}</div>{{/iterator}}'});

firesyncArray.key() ⇒ string

Returns a key by a specified index.

Kind: instance method of FiresyncArray
Returns: string - The key of the object at the specified index.
Example

firesyncArray.key(0) === '-Ju5kIB-e3ZABIccrOjK';

firesyncArray.update(value, identifier) ⇒ Promise

Update an object using a specified identifier. This is the only supported way to update an element inside {FiresyncArray}. Keeps the synchronization.

Kind: instance method of FiresyncArray
Returns: Promise - For when the synchronization is complete.

Param Type Description
value any The update value.
identifier Identifier The identifier to be used to find the element.

firesyncArray.add(value, [key], [index]) ⇒ Promise

Adds an element to the {FiresyncArray}. By default generates Firebase arrays with standard Firebase-generated keys. This is the only supported way to add an element inside {FiresyncArray}. Keeps the synchronization.

Kind: instance method of FiresyncArray
Returns: Promise - For when the synchronization is complete.

Param Type Default Description
value any The value to add to the arary.
[key] string "ref.push().key()" The key to be used for the element. Default key is recommended.
[index] number last The index at which to add the element to the local array.

firesyncArray.remove(identifier) ⇒ Promise

Removes an element from the array by an {Identifier}

Kind: instance method of FiresyncArray
Returns: Promise - For when the synchronization is complete.

Param Type Description
identifier Identifier The identifier to find the array by.

firesyncArray.move(oldIdentifier, newIdentifier) ⇒ Promise

Moves an element from one index to another.

Kind: instance method of FiresyncArray
Returns: Promise - For when the synchronization is complete.

Param Type Description
oldIdentifier Identifier The identifier for the old object.
newIdentifier Identifier The identifier for the new object.

firesyncArray.loaded() ⇒ boolean

Indicates whether the object has loaded its data from Firebase.

Kind: instance method of FiresyncArray

firesyncArray.ref() ⇒ FirebaseRef

Returns the ref set in the constructor

Kind: instance method of FiresyncArray

firesyncArray.detach()

Detaches from the subscribed Firebase and DOM events. Must be called if the object will no longer be used.

Kind: instance method of FiresyncArray

firesyncArray.bindTo(settings) ⇒ FiresyncBase

Binds to DOM templates using RactiveJs. The settings are passed directly to RactiveJs.

Kind: instance method of FiresyncArray
Returns: FiresyncBase - The current instance.

Param Type Description
settings Object The settings passed to RactiveJs. Refer to the RactiveJs docs for more details

Example

new (FiresyncObject|FiresyncArray).bindTo({ el: 'body', template: '<input value={{value}}/>' })

"changed"

Fired the local object changes, regardless whether it is a result of direct local change or remote change.

Kind: event emitted by FiresyncArray
Example

firesyncObject.on('changed', function(){});

"loaded"

Fired when the initial value of the object is loaded from the remote.

Kind: event emitted by FiresyncArray
Example

firesyncObject.on('loaded', function(){});

"synced" (err)

Fired when the local object's value is sucesfully set to the remote.

Kind: event emitted by FiresyncArray

Param Type Description
err Error Synchronization error

Example

firesyncObject.on('synced', function(err){});

firesync.FiresyncObject ⇐ FiresyncBase

An object which keeps its values synchronized with the remote Firebase.

Kind: static class of firesync
Extends: FiresyncBase
Access: protected

firesyncObject.loaded() ⇒ boolean

Indicates whether the object has loaded its data from Firebase.

Kind: instance method of FiresyncObject

firesyncObject.ref() ⇒ FirebaseRef

Returns the ref set in the constructor

Kind: instance method of FiresyncObject

firesyncObject.detach()

Detaches from the subscribed Firebase and DOM events. Must be called if the object will no longer be used.

Kind: instance method of FiresyncObject

firesyncObject.bindTo(settings) ⇒ FiresyncBase

Binds to DOM templates using RactiveJs. The settings are passed directly to RactiveJs.

Kind: instance method of FiresyncObject
Returns: FiresyncBase - The current instance.

Param Type Description
settings Object The settings passed to RactiveJs. Refer to the RactiveJs docs for more details

Example

new (FiresyncObject|FiresyncArray).bindTo({ el: 'body', template: '<input value={{value}}/>' })

"changed"

Fired the local object changes, regardless whether it is a result of direct local change or remote change.

Kind: event emitted by FiresyncObject
Example

firesyncObject.on('changed', function(){});

"loaded"

Fired when the initial value of the object is loaded from the remote.

Kind: event emitted by FiresyncObject
Example

firesyncObject.on('loaded', function(){});

"synced" (err)

Fired when the local object's value is sucesfully set to the remote.

Kind: event emitted by FiresyncObject

Param Type Description
err Error Synchronization error

Example

firesyncObject.on('synced', function(err){});

firesync.create(ref) ⇒ Promise

Creates a FiresyncObject or FiresyncArray from the specified ref depending on the underlying value. The returned object is guaranteed to be loaded.

Kind: static method of firesync

Param Type Description
ref FirebaseRef from a specified ref

Example

firesync.create(ref).then(function(firesyncObj) {}); //if ref's underlying value is array a FiresyncArray is returned
otherwise a FiresyncObject

firesync.map(ref) ⇒ Promise

Returns a non-synchronized array or an object of FiresyncObject or FiresyncArray objects. The objects are guaranteed to be loaded.

Kind: static method of firesync

Param Type Description
ref FirebaseRef from a specified ref

Example

firesync.map(ref).then(function(objOrArr){});

FirebaseRef

FirebaseRef object

Kind: global external
See: https://www.firebase.com/docs/web/api/firebase/child.html

RactiveJs

RactiveJs object

Kind: global external
See: http://docs.ractivejs.org/latest/get-started

License


The MIT License (MIT)

Copyright (c) 2015 Firesync

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Readme

Keywords

none

Package Sidebar

Install

npm i firesync-node

Weekly Downloads

7

Version

1.1.1

License

MIT

Last publish

Collaborators

  • gngeorgiev