spincycle
Version:
A reactive message router and object manager that lets clients subscribe to object property changes on the server
278 lines (245 loc) • 7.36 kB
JavaScript
// Generated by CoffeeScript 1.12.6
(function() {
var OStore, debug, defer, error, uuid,
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
defer = require('node-promise').defer;
uuid = require('node-uuid');
error = require('./Error').error;
debug = process.env["DEBUG"];
OStore = (function() {
function OStore() {}
OStore.objects = [];
OStore.types = [];
OStore.listeners = [];
OStore.objectsByType = [];
OStore.blackList = ['id', 'createdAt', 'createdBy', 'updatedAt', 'admin'];
OStore.updateQueue = [];
OStore.listObjectsByType = function(type) {
var kk, rv, v, vv;
rv = [];
if (debug) {
console.log('OStore::listObjectsByType called for type ' + type);
}
v = OStore.objectsByType[type];
for (kk in v) {
vv = v[kk];
if (vv) {
rv.push(vv);
if (debug) {
console.log('adding ' + vv.name);
}
}
}
return rv;
};
OStore.listTypes = function() {
var k, ref, rv, v;
rv = [];
console.log('listTypes called');
console.dir(OStore.types);
ref = OStore.types;
for (k in ref) {
v = ref[k];
rv.push(v);
}
return rv;
};
OStore.storeObject = function(obj, sendUpdates) {
var objs;
if (sendUpdates == null) {
sendUpdates = true;
}
if (obj) {
OStore.objects[obj.id] = obj;
OStore.types[obj.type] = obj.type;
objs = OStore.objectsByType[obj.type] || {};
objs[obj.id] = obj;
OStore.objectsByType[obj.type] = objs;
if (debug) {
console.log('storeObject storing ' + obj.id + ' with type ' + obj.type);
}
return OStore.sendUpdatesFor(obj, sendUpdates);
}
};
OStore.getObject = function(id, type) {
var hash, obj, q;
q = defer();
hash = OStore.objectsByType[type] || {};
obj = hash[id];
if (obj) {
} else {
}
q.resolve(obj);
return q;
};
OStore.removeObject = function(obj) {
var objs;
if (obj && obj.id) {
delete OStore.objects[obj.id];
objs = OStore.objectsByType[obj.type] || [];
if (objs[obj.id]) {
delete objs[obj.id];
}
return OStore.objectsByType[obj.type] = obj;
}
};
OStore.updateObj = function(record, force) {
var changed, clean, diff, obj, p, pp, whitelist;
if (debug) {
console.log('+ oStore.updateObj called for obj ' + record.id + ' force = ' + force);
}
obj = OStore.objects[record.id];
if (obj) {
whitelist = obj.getRecord();
delete whitelist.id;
delete whitelist.type;
diff = {};
changed = false;
record.modifiedAt = Date.now();
for (p in whitelist) {
for (pp in record) {
if (pp === p) {
if (indexOf.call(OStore.blackList, pp) < 0) {
if (obj[pp] !== record[pp] || (record[pp] && obj[pp].length && obj[pp].length !== record[pp].length) || force === true) {
clean = this.makeClean(record[pp]);
if (clean) {
diff[pp] = clean;
changed = true;
obj[pp] = clean;
if (debug) {
console.log('** updating property "' + pp + '" on ' + obj.type + ' id ' + record.id + ' to ' + clean);
}
}
}
}
}
}
}
OStore.objects[record.id] = obj;
if (OStore.anyoneIsListening(obj.id) || force) {
if (!changed) {
changed = force;
}
return OStore.sendUpdatesFor(obj, changed, force);
}
} else {
return console.log('OStore: tried to update an object which we did not have in cache!');
}
};
OStore.makeClean = function(property) {
var rv;
rv = "";
if (property && property !== null && property !== "undefined" && property !== "null") {
if (property.filter) {
rv = property.filter(function(item) {
return item && item !== null && item !== "undefined" && item !== "null";
});
} else {
rv = property;
}
}
return rv;
};
OStore.sendUpdatesFor = function(obj, changed, force) {
if ((changed || force) && OStore.anyoneIsListening(obj.id)) {
OStore.updateQueue.push(obj);
return OStore.sendAtInterval();
}
};
OStore.sendAllUpdatesFor = function(obj, changed) {
var count, sendobj;
sendobj = {
id: obj.id,
type: obj.type,
list: [],
toClient: function() {
return {
id: obj.id,
type: obj.type,
list: sendobj.list
};
}
};
count = obj.list.length;
return obj.list.forEach(function(id) {
return OStore.getObject(id, obj.type).then(function(o) {
sendobj.list.push(o.toClient());
if (--count === 0) {
if (changed) {
if (OStore.anyoneIsListening(sendobj.id)) {
return OStore.updateQueue.push(sendobj);
}
}
}
});
});
};
OStore.anyoneIsListening = function(id) {
var l, larr, rv;
rv = false;
larr = OStore.listeners[id];
if (larr) {
for (l in larr) {
rv = true;
}
}
return rv;
};
OStore.addListenerFor = function(id, type, cb) {
var list, listenerId;
list = OStore.listeners[id] || [];
listenerId = uuid.v4();
list[listenerId] = cb;
OStore.listeners[id] = list;
return listenerId;
};
OStore.removeListenerFor = function(id, listenerId) {
var cb, i, list, tmp;
list = OStore.listeners[id] || [];
delete list[listenerId];
tmp = [];
for (i in list) {
cb = list[i];
if (cb) {
tmp[i] = cb;
}
}
OStore.listeners[id] = tmp;
if (debug) {
console.log('removing listener for object ' + id);
}
if (debug) {
console.log('listeners list is now');
}
if (debug) {
return console.dir(OStore.listeners[id]);
}
};
OStore.sendAtInterval = function() {
var count, l, lid, listeners, obj;
if (OStore.updateQueue.length > 0) {
if (debug) {
console.log('OStore.sendAtInterval queue length = ' + OStore.updateQueue.length);
}
l = OStore.updateQueue.length;
count = 0;
while (count < l) {
count++;
obj = OStore.updateQueue.shift();
listeners = OStore.listeners[obj.id] || [];
for (lid in listeners) {
listeners[lid](obj);
}
}
if (debug) {
console.log('queue length after send = ' + OStore.updateQueue.length);
}
}
return setTimeout(OStore.sendAtInterval, 50);
};
OStore.sendAtInterval();
return OStore;
})();
module.exports = OStore;
}).call(this);
//# sourceMappingURL=OStore.js.map