Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

fh-wfm-sync

Package Overview
Dependencies
Maintainers
4
Versions
53
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fh-wfm-sync - npm Package Compare versions

Comparing version 0.1.0-alpha.1 to 0.1.0-alpha.2

lib/client/mediator-subscribers/create-spec.js

19

Gruntfile.js

@@ -9,8 +9,11 @@ module.exports = function(grunt) {

},
mochify: {
options: {
reporter: 'spec'
},
unit: {
src: ['lib/**/**/*-spec.js']
mochaTest: {
test: {
src: ['lib/**/*-spec.js'],
options: {
reporter: 'Spec',
logErrors: true,
timeout: 10000,
run: true
}
}

@@ -20,4 +23,4 @@ }

grunt.registerTask('test', ['eslint', 'mochify:unit']);
grunt.registerTask('default', ['eslint']);
grunt.registerTask('test', ['eslint', 'mochaTest']);
grunt.registerTask('default', ['test']);
};

@@ -24,15 +24,31 @@ 'use strict';

syncService.init = function($fh, syncOptions) {
$fh = $fh || {};
/**
*
* Initialising the sync module with any required options.
*
* @param _$fh - (Optional) A reference to the feedhenry client API
* @param _syncOptions - (Optional) Any options required for intialising the $fh.sync API.
*/
syncService.init = function(_$fh, _syncOptions) {
var fhApi = (_$fh && _syncOptions) ? _$fh : window.$fh;
var syncOptions = (_$fh && _syncOptions) ? _syncOptions : _$fh;
syncOptions = syncOptions || {};
//If the feedhenry API is passed, use this.
//Otherwise default to the global window.$fh
if ($fh.sync) {
sync.init($fh, syncOptions, mediator);
} else {
sync.init(window.$fh, syncOptions, mediator);
//If the feedhenry API is passed, initialise the sync module
if (fhApi && fhApi.sync) {
sync.init(fhApi, syncOptions, mediator);
}
};
/**
*
* Creating a manager for a single data set.
*
* @param datasetId
* @param options
* @param queryParams
* @param metaData
* @returns {Promise<TResult>}
*/
syncService.manage = function(datasetId, options, queryParams, metaData) {

@@ -39,0 +55,0 @@ return $q.when(sync.manage(datasetId, options, queryParams, metaData))

var mediator = require('fh-wfm-mediator/lib/mediator');
var sinon = require('sinon');
var assert = require('assert');
var chai = require('chai');
var expect = chai.expect;

@@ -17,2 +18,3 @@ describe("Raincatcher Sync Client Initialisation", function() {

var mockDataSetMetadataParams = {metadataParam1: "metadatavalue"};
var syncClient = require('../client');

@@ -22,5 +24,2 @@ before(function() {

//Clearing the require cache to re-require the client
self.syncClient = require('../client');
self.mock$fh = {

@@ -37,11 +36,9 @@ sync: {

it("should not allow a manager to be created if sync has not been initialised", function(done) {
it("should not allow a manager to be created if sync has not been initialised", function() {
var self = this;
self.syncClient.manage(mockDataSetId, mockSyncOptions, mockDataSetFilterParams, mockDataSetMetadataParams).then(function(message) {
assert.equal('Sync not yet initialized. Call sync-client.init() first.', message);
return syncClient.manage(mockDataSetId, mockSyncOptions, mockDataSetFilterParams, mockDataSetMetadataParams).catch(function(error) {
expect(error.message).to.equal('Sync not yet initialized. Call sync-client.init() first.');
sinon.assert.notCalled(self.mock$fh.sync.manage);
done();
});

@@ -53,3 +50,3 @@ });

self.syncClient.init(self.mock$fh, mockSyncOptions, mediator);
syncClient.init(self.mock$fh, mockSyncOptions, mediator);

@@ -66,3 +63,3 @@ sinon.assert.calledOnce(self.mock$fh.sync.init);

self.syncClient.init(self.mock$fh, mockSyncOptions, mediator);
syncClient.init(self.mock$fh, mockSyncOptions, mediator);

@@ -74,9 +71,9 @@ sinon.assert.calledOnce(self.mock$fh.sync.init);

it("should create a new data manager when managing a new data set", function(done) {
it("should create a new data manager when managing a new data set", function() {
var self = this;
self.syncClient.manage(mockDataSetId, mockSyncOptions, mockDataSetFilterParams, mockDataSetMetadataParams).then(function() {
return syncClient.manage(mockDataSetId, mockSyncOptions, mockDataSetFilterParams, mockDataSetMetadataParams).then(function(datasetManager) {
sinon.assert.calledOnce(self.mock$fh.sync.manage);
sinon.assert.calledWith(self.mock$fh.sync.manage, sinon.match(mockDataSetId), sinon.match(mockSyncOptions), sinon.match(mockDataSetFilterParams), sinon.match(mockDataSetMetadataParams));
done();
datasetManager.removeSyncDataTopicSubscribers();
});

@@ -83,0 +80,0 @@ });

@@ -7,2 +7,4 @@ var DataManager = require('./data-manager');

var Rx = require('rx');
var chai = require('chai');
var expect = chai.expect;

@@ -12,2 +14,3 @@ describe("Data Manager", function() {

var mockDataSetId = "mockdatasetid";
var dataManager;

@@ -22,6 +25,12 @@ beforeEach(function() {

afterEach(function() {
dataManager.removeSyncDataTopicSubscribers();
});
it("should initialise with a mediator", function() {
var mock$fh = {};
var dataManager = new DataManager(mockDataSetId, mock$fh, this.mockDataSetNotificationObservableStream, mediator);
dataManager = new DataManager(mockDataSetId, mock$fh, this.mockDataSetNotificationObservableStream, mediator);

@@ -39,3 +48,3 @@ sinon.assert.calledOnce(this.mockDataSetNotificationObservableStream.forEach);

var dataManager = new DataManager(mockDataSetId, mock$fh, this.mockDataSetNotificationObservableStream);
dataManager = new DataManager(mockDataSetId, mock$fh, this.mockDataSetNotificationObservableStream);

@@ -53,3 +62,3 @@ //It should not have attached a `forEach` filter to the observable stream if there is no mediator

it("should list all items", function(done) {
it("should list all items", function() {

@@ -72,5 +81,5 @@ //An example of a list API Response From the $fh.sync framework

var dataManager = new DataManager(mockDataSetId, mock$fh, this.mockDataSetNotificationObservableStream, mediator);
dataManager = new DataManager(mockDataSetId, mock$fh, this.mockDataSetNotificationObservableStream, mediator);
dataManager.list().then(function(dataSetList) {
return dataManager.list().then(function(dataSetList) {

@@ -80,8 +89,6 @@ sinon.assert.calledWith(mock$fh.sync.doList, sinon.match(mockDataSetId), sinon.match.func, sinon.match.func);

assert.strictEqual(mockSyncDataSetListAPIResponse.dataentryid.data, dataSetList[0]);
done();
}).catch(done);
});
});
it("should create a new item", function(done) {
it("should create a new item", function() {

@@ -109,6 +116,6 @@ var mockRecordUid = "syncRecordUID";

var dataManager = new DataManager(mockDataSetId, mock$fh, this.mockDataSetNotificationObservableStream, mediator);
dataManager = new DataManager(mockDataSetId, mock$fh, this.mockDataSetNotificationObservableStream, mediator);
dataManager.create(mockDataItem).then(function(createResult) {
assert.ok(_.isEqual(expectedCreatedData, createResult), "Expected the created item with the local ID to be resolved");
expect(createResult).to.deep.equal(expectedCreatedData);

@@ -122,8 +129,6 @@ sinon.assert.calledOnce(mock$fh.sync.doCreate);

sinon.assert.calledTwice(mock$fh.sync.doRead);
done();
}).catch(done);
});
});
it("should read a single item", function(done) {
it("should read a single item", function() {
var mockRecordUid = "syncRecordUID";

@@ -148,6 +153,6 @@

var dataManager = new DataManager(mockDataSetId, mock$fh, this.mockDataSetNotificationObservableStream, mediator);
dataManager = new DataManager(mockDataSetId, mock$fh, this.mockDataSetNotificationObservableStream, mediator);
dataManager.read(mockRecordUid).then(function(readRecord) {
assert.ok(_.isEqual(mockDataItem, readRecord), "Expected the data item to be resolved after reading");
return dataManager.read(mockRecordUid).then(function(readRecord) {
expect(readRecord).to.deep.equal(mockDataItem);

@@ -157,4 +162,3 @@ sinon.assert.calledOnce(mock$fh.sync.doRead);

done();
}).catch(done);
});

@@ -164,3 +168,3 @@ });

it("should update a new item", function(done) {
it("should update a new item", function() {

@@ -188,6 +192,6 @@ var mockRecordUid = "syncRecordUID";

var dataManager = new DataManager(mockDataSetId, mock$fh, this.mockDataSetNotificationObservableStream, mediator);
dataManager = new DataManager(mockDataSetId, mock$fh, this.mockDataSetNotificationObservableStream, mediator);
dataManager.update(mockDataItem).then(function(createResult) {
assert.ok(_.isEqual(expectedCreatedData, createResult), "Expected the updated item to be resolved ");
return dataManager.update(mockDataItem).then(function(createResult) {
expect(createResult).to.deep.equal(expectedCreatedData);

@@ -198,8 +202,6 @@ sinon.assert.calledOnce(mock$fh.sync.doUpdate);

sinon.assert.calledTwice(mock$fh.sync.doRead);
done();
}).catch(done);
});
});
it("should remove a single item", function(done) {
it("should remove a single item", function() {
var mockRecordUid = "syncRecordUID";

@@ -220,15 +222,13 @@

var dataManager = new DataManager(mockDataSetId, mock$fh, this.mockDataSetNotificationObservableStream, mediator);
dataManager = new DataManager(mockDataSetId, mock$fh, this.mockDataSetNotificationObservableStream, mediator);
dataManager.delete(mockDataItem).then(function() {
return dataManager.delete(mockDataItem).then(function() {
sinon.assert.calledOnce(mock$fh.sync.doDelete);
sinon.assert.calledWith(mock$fh.sync.doDelete, sinon.match(mockDataSetId), sinon.match(mockDataItem.id), sinon.match.func, sinon.match.func);
done();
}).catch(done);
});
});
});
it("should publish topics from the data set notification stream", function(done) {
it("should publish topics from the data set notification stream", function() {
var self = this;

@@ -251,3 +251,3 @@ var mockSyncNotification = {

new DataManager(mockDataSetId, mock$fh, syncNotificationStream, mediator);
dataManager = new DataManager(mockDataSetId, mock$fh, syncNotificationStream, mediator);

@@ -261,6 +261,4 @@ sinon.assert.notCalled(syncNotificationSubscriber);

sinon.assert.calledWith(syncNotificationSubscriber, mockSyncNotification);
done();
});
});
var _ = require('lodash')
, q = require('q');
var mediatorManager = require('./mediator-subscribers');
var topicGenerators = require('./topic-generators');
/**

@@ -69,12 +72,56 @@ *

this.mediator = mediator;
this.subscribers = {};
this.subscribeToSyncEvents();
this.createSyncDataTopicSubscribers();
}
/**
* Subscribing to notifications for this data set from the $fh.sync Client API
* Creating all of the mediator subscribers for this sync data set.
*/
DataManager.prototype.createSyncDataTopicSubscribers = function createSyncDataTopicSubscribers() {
var self = this;
//If there is no mediator applied, then we can't subscribe to mediator topics.
if (!self.mediator) {
return;
}
//These are the topics that the individual data sets will subscribe to.
var datasetSyncTopics = ["create", "update", "delete", "list", "read", "force_sync", "stop", "start"];
//For each of the sync topics, create mediator subscribers to implement these topics.
_.each(datasetSyncTopics, function(dataSyncTopic) {
if (mediatorManager[dataSyncTopic]) {
self.subscribers[topicGenerators.createTopic({
datasetId: self.datasetId,
topicName: dataSyncTopic
})] = mediatorManager[dataSyncTopic](self.mediator, self);
}
});
};
/**
*
* For more information on the
* Removing any subscribers associated with this data set.
*
*/
DataManager.prototype.removeSyncDataTopicSubscribers = function removeSyncDataTopicSubscribers() {
var self = this;
if (!self.mediator) {
return;
}
_.each(this.subscribers, function(subscriber, topic) {
self.mediator.remove(topic, subscriber.id);
});
};
/**
* Subscribing to notifications for this data set from the $fh.sync Client API
*
*/
DataManager.prototype.subscribeToSyncEvents = function subscribeToSyncEvents() {

@@ -184,3 +231,9 @@ var self = this;

//Handling an error returned by the doCreate API call
/**
*
* Handling an error returned by the doCreate API call
*
* @param errorCode
* @param syncErrorMessage
*/
function handleCreateError(errorCode, syncErrorMessage) {

@@ -187,0 +240,0 @@ deferred.reject(new Error(formatSyncErrorMessage(errorCode, syncErrorMessage)));

@@ -10,3 +10,7 @@ 'use strict';

var $fh, initialized = false, syncNotificationStream, syncNotifyListeners = [], mediator;
var $fh,
initialized = false,
syncNotificationStream,
syncNotifyListeners = [],
mediator;

@@ -41,3 +45,2 @@ /**

if (initialized) {
console.log('sync-client already initalized.');
return;

@@ -98,3 +101,3 @@ }

if (!initialized) {
deferred.resolve('Sync not yet initialized. Call sync-client.init() first.');
deferred.reject(new Error('Sync not yet initialized. Call sync-client.init() first.'));
return deferred.promise;

@@ -101,0 +104,0 @@ }

{
"name": "fh-wfm-sync",
"version": "0.1.0-alpha.1",
"version": "0.1.0-alpha.2",
"description": "An sync module for WFM",

@@ -33,2 +33,3 @@ "main": "lib/angular/sync-ng.js",

"bunyan": "1.8.0",
"chai": "^3.5.0",
"config-chain": "1.1.10",

@@ -40,7 +41,8 @@ "cors": "2.7.1",

"fh-wfm-mediator": "0.0.15",
"grunt": "0.4.5",
"grunt": "1.0.1",
"grunt-cli": "1.2.0",
"grunt-eslint": "18.0.0",
"grunt-mochify": "0.3.0",
"grunt-mocha-test": "0.13.2",
"load-grunt-tasks": "3.5.2",
"mochify": "2.17.0",
"mocha": "3.2.0",
"nodemon": "1.9.1",

@@ -47,0 +49,0 @@ "should": "8.3.0",

@@ -11,16 +11,14 @@ # FeedHenry WFM sync

### Client-side usage (via broswerify)
### Setup
#### Setup
This module is packaged in a CommonJS format, exporting the name of the Angular namespace. The module can be included in an angular.js as follows:
```javascript
angular.module('app', [require('fh-wfm-sync')], function(sync){
angular.module('app', [require('fh-wfm-sync')], function(syncService){
// ...
});
```
#### Integration
### Integration
##### Angular service
#### Angular service

@@ -36,6 +34,14 @@ The sync service must first be initialized using the `syncService.init()`. Generally, the syncService will be injected into another Angular service (or in a config block) :

Once initialized the syncService can manage multiple `dataset` using the following function:
##### Managing Datasets
Once initialized the syncService can manage multiple `datasets` using the following function:
```javascript
var config = {
...
datasetId: "workorders"
...
};
syncService.manage(config.datasetId, null, queryParams);

@@ -45,33 +51,342 @@

Checkout a full example [here](https://github.com/feedhenry-staff/wfm-workorder/blob/master/lib/angular/sync-service.js)
### Dataset Topic Subscriptions
#### Topics
Each `dataset` subscribes to the following topics. For a `dataset` with an ID `datasetid`, the following topics are published:
The following topics are published by the client side of the application:
##### Data Set Topics
#### wfm:sync:create:datasetid
The following topics are published by the module for each `dataset`. If the
##### Description
###### $fh.sync Client Notifications
Creating a new item in the dataset.
##### Example
```javascript
var datasetItemToCreate = {
...
id: "datasetitemid", //The "id" parameter is required by the topic
...
}
mediator.publish("wfm:sync:create:datasetid", datasetItemToCreate);
```
#### wfm:sync:update:datasetid
##### Description
Updating an existing item in the dataset.
##### Example
```javascript
var datasetItemToUpdate = {
...
id: "datasetitemid", //The "id" parameter is required by the topic
...
}
mediator.publish("wfm:sync:update:datasetid", datasetItemToUpdate);
```
#### wfm:sync:remove:datasetid
##### Description
Removing a single item from the dataset.
##### Example
```javascript
mediator.publish("wfm:sync:remove:datasetid", "idofdataitemtoremove");
```
#### wfm:sync:list:datasetid
##### Description
Listing all of the items in the dataset.
##### Example
```javascript
mediator.publish("wfm:sync:list:datasetid");
```
#### wfm:sync:start:datasetid
##### Description
Start the synchronisation process from client to cloud for this dataset.
##### Example
```javascript
mediator.publish("wfm:sync:start:datasetid");
```
#### wfm:sync:stop:datasetid
##### Description
Stop the synchronisation process from client to cloud for this dataset.
##### Example
```javascript
mediator.publish("wfm:sync:stop:datasetid");
```
#### wfm:sync:force_sync:datasetid
##### Description
Force the synchronisation of client and cloud data for this dataset.
##### Example
```javascript
mediator.publish("wfm:sync:force_sync:datasetid");
```
### Dataset Published Topics
The following topics are published by the module for each `dataset`.
#### done:wfm:sync:create:datasetid:datasetitemid
The item with ID `datasetitemid` was successfully created.
```javascript
mediator.subscribe("done:wfm:sync:create:datasetid:datasetitemid", function(createdItem) {
...
/**
*
* createdItem = {
* ...
* id: "datasetitemid"
* ...
* }
*
*/
...
});
```
#### error:wfm:sync:create:datasetid:datasetitemid
An error occurred when creating an object with ID `datasetitemid`.
```javascript
mediator.subscribe("error:wfm:sync:create:datasetid:datasetitemid", function(error) {
...
console.log(error.message);
...
});
```
#### done:wfm:sync:update:datasetid:datasetitemid
The item with ID `datasetitemid` was updated successfully.
```javascript
mediator.subscribe("done:wfm:sync:update:datasetid:datasetitemid", function(updatedItem) {
...
/**
*
* updatedItem = {
* ...
* id: "datasetitemid"
* ...
* }
*
*/
...
});
```
#### error:wfm:sync:update:datasetid:datasetitemid
An error occurred when updating an object with ID `datasetitemid`.
```javascript
mediator.subscribe("error:wfm:sync:update:datasetid:datasetitemid", function(error) {
...
console.log(error.message);
...
});
```
#### done:wfm:sync:remove:datasetid:datasetitemid
An item with ID `datasetitemid` was removed successfully.
```javascript
mediator.subscribe("done:wfm:sync:remove:datasetid:datasetitemid", function() {
...
...
});
```
#### error:wfm:sync:remove:datasetid:datasetitemid
An error occurred when removing an object with ID `datasetitemid`.
```javascript
mediator.subscribe("error:wfm:sync:remove:datasetid:datasetitemid", function(error) {
...
console.log(error.message);
...
});
```
#### done:wfm:sync:list:datasetid
A list of items for a dataset with ID `datasetid` completed successfully.
```javascript
mediator.subscribe("done:wfm:sync:list:datasetid", function(listOfItems) {
...
/**
*
* listOfItems = [{
* ...
* id: "datasetitemid1"
* ...
* }, {
* ...
* id: "datasetitemid2"
* ...
* }]
*
*/
...
});
```
#### error:wfm:sync:list:datasetid
An error occurred when listing items for a dataset with ID `datasetid`
```javascript
mediator.subscribe("error:wfm:sync:list:datasetid", function(error) {
...
console.log(error.message);
...
});
```
#### done:wfm:sync:start:datasetid
The client-cloud sync process for a dataset with ID `datasetid` started successfully.
```javascript
mediator.subscribe("done:wfm:sync:start:datasetid", function() {
...
...
});
```
#### error:wfm:sync:start:datasetid
An error occurred when starting the client cloud sync process for a dataset with ID `datasetid`
```javascript
mediator.subscribe("error:wfm:sync:start:datasetid", function(error) {
...
console.log(error.message);
...
});
```
#### done:wfm:sync:stop:datasetid
The client-cloud sync process for a dataset with ID `datasetid` stopped successfully.
```javascript
mediator.subscribe("done:wfm:sync:stop:datasetid", function() {
...
...
});
```
#### error:wfm:sync:stop:datasetid
An error occurred when stopping the client cloud sync process for a dataset with ID `datasetid`
```javascript
mediator.subscribe("error:wfm:sync:stop:datasetid", function(error) {
...
console.log(error.message);
...
});
```
#### Notification Topics
The module publishes topics covering all of the notification codes available to the $fh.sync Client API.
wfm:sync:**sync_notification_code**:**datasetId**
The list of notification codes published are:
* client_storage_failed: Loading or saving to client storage failed. This is a critical error and the Sync Client will not work properly without client storage.
* sync_started: A synchronization cycle with the server has been started.
* sync_complete: A synchronization cycle with the server has been completed.
* offline_update: An attempt was made to update or delete a record while offline.
* collision_detected: Update failed due to data collision.
* remote_update_failed: Update failed for a reason other than data collision.
* remote_update_applied: An update was applied to the remote data store.
* local_update_applied: An update was applied to the local data store.
* delta_received: A change was received from the remote data store for the dataset. It is best to listen to this notification and update the UI accordingly.
* record_delta_received: A delta was received from the remote data store for the record. It is best to listen to this notification and update UI accordingly.
* sync_failed: Synchronization loop failed to complete.
| Topic | Description |
| ------------- |:-------------:|
| wfm:sync:client_storage_failed:datasetid | Loading or saving to client storage failed. This is a critical error and the Sync Client will not work properly without client storage. |
| wfm:sync:sync_started:datasetid | A synchronization cycle with the server has been started. |
| wfm:sync:sync_complete:datasetid | A synchronization cycle with the server has been completed. |
| wfm:sync:offline_update:datasetid | An attempt was made to update or delete a record while offline. |
| wfm:sync:collision_detected:datasetid | Update failed due to data collision. |
| wfm:sync:remote_update_failed:datasetid | Update failed for a reason other than data collision. |
| wfm:sync:remote_update_applied:datasetid | An update was applied to the remote data store. |
| wfm:sync:local_update_applied:datasetid | An update was applied to the local data store. |
| wfm:sync:delta_received:datasetid | A change was received from the remote data store for the dataset. |
| wfm:sync:sync_failed:datasetid | Synchronization loop failed to complete. |
##### Topic Parameters
Each of these topics will be published with an object describing the event:

@@ -78,0 +393,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc