mirror of
https://github.com/amark/gun.git
synced 2025-06-15 18:46:39 +00:00
Merge branch 'master' into develop
This commit is contained in:
commit
738bc7f3fa
46
gun.js
46
gun.js
@ -527,6 +527,12 @@
|
|||||||
|
|
||||||
Gun.on.at.copy = function(at){ return Gun.obj.del(at, 'hash'), Gun.obj.map(at, function(v,f,t){t(f,v)}) }
|
Gun.on.at.copy = function(at){ return Gun.obj.del(at, 'hash'), Gun.obj.map(at, function(v,f,t){t(f,v)}) }
|
||||||
|
|
||||||
|
Gun.root = function(gun) {
|
||||||
|
if (!Gun.is(gun)) return null;
|
||||||
|
if (gun.back === gun) return gun;
|
||||||
|
return Gun.root(gun.back);
|
||||||
|
};
|
||||||
|
|
||||||
}(Gun));
|
}(Gun));
|
||||||
|
|
||||||
;(function(Gun){ // Gun prototype chain methods.
|
;(function(Gun){ // Gun prototype chain methods.
|
||||||
@ -800,7 +806,7 @@
|
|||||||
}());
|
}());
|
||||||
|
|
||||||
Gun.chain.on = function(cb, opt){ // on subscribes to any changes on the souls.
|
Gun.chain.on = function(cb, opt){ // on subscribes to any changes on the souls.
|
||||||
var gun = this, u;
|
var gun = this, u, oldoff = this.off;
|
||||||
opt = Gun.obj.is(opt)? opt : {change: opt};
|
opt = Gun.obj.is(opt)? opt : {change: opt};
|
||||||
cb = cb || function(){};
|
cb = cb || function(){};
|
||||||
function map(at){
|
function map(at){
|
||||||
@ -815,6 +821,7 @@
|
|||||||
};
|
};
|
||||||
opt.on = gun._.at('soul').map(map);
|
opt.on = gun._.at('soul').map(map);
|
||||||
if(gun === gun.back){ Gun.log('You have no context to `.on`!') }
|
if(gun === gun.back){ Gun.log('You have no context to `.on`!') }
|
||||||
|
gun.off = oldoff ? function() { oldoff(); opt.on.off(); } : opt.on.off // Chain offs
|
||||||
return gun;
|
return gun;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -850,7 +857,7 @@
|
|||||||
return function(path, cb, opt){
|
return function(path, cb, opt){
|
||||||
opt = opt || {};
|
opt = opt || {};
|
||||||
cb = cb || (function(){ var cb = function(){}; cb.no = true; return cb }()); cb.hash = {};
|
cb = cb || (function(){ var cb = function(){}; cb.no = true; return cb }()); cb.hash = {};
|
||||||
var gun = this, chain = gun.chain(), f, c, u;
|
var gun = this, chain = gun.chain(), ons = [], f, c, u;
|
||||||
if(!Gun.list.is(path)){ if(!Gun.text.is(path)){ if(!Gun.num.is(path)){ // if not a list, text, or number
|
if(!Gun.list.is(path)){ if(!Gun.text.is(path)){ if(!Gun.num.is(path)){ // if not a list, text, or number
|
||||||
return cb.call(chain, {err: Gun.log("Invalid path '" + path + "'!")}), chain; // then complain
|
return cb.call(chain, {err: Gun.log("Invalid path '" + path + "'!")}), chain; // then complain
|
||||||
} else { return this.path(path + '', cb, opt) } } else { return this.path(path.split('.'), cb, opt) } } // else coerce upward to a list.
|
} else { return this.path(path + '', cb, opt) } } else { return this.path(path.split('.'), cb, opt) } } // else coerce upward to a list.
|
||||||
@ -858,7 +865,7 @@
|
|||||||
cb.call(chain, opt.put? null : {err: Gun.log('You have no context to `.path`', path, '!')}, opt.put? gun.__.graph[(path||[])[0]] : u);
|
cb.call(chain, opt.put? null : {err: Gun.log('You have no context to `.path`', path, '!')}, opt.put? gun.__.graph[(path||[])[0]] : u);
|
||||||
return chain;
|
return chain;
|
||||||
}
|
}
|
||||||
gun._.at('path:' + path[0]).event(function(at){
|
ons.push(gun._.at('path:' + path[0]).event(function(at){
|
||||||
if(opt.done){ this.off(); return } // TODO: BUG - THIS IS A FIX FOR A BUG! TEST #"context no double emit", COMMENT THIS LINE OUT AND SEE IT FAIL!
|
if(opt.done){ this.off(); return } // TODO: BUG - THIS IS A FIX FOR A BUG! TEST #"context no double emit", COMMENT THIS LINE OUT AND SEE IT FAIL!
|
||||||
var ctx = {soul: at.soul, field: at.field, by: gun.__.by(at.soul)}, field = path[0];
|
var ctx = {soul: at.soul, field: at.field, by: gun.__.by(at.soul)}, field = path[0];
|
||||||
var on = Gun.obj.as(cb.hash, at.hash, {off: function(){}});
|
var on = Gun.obj.as(cb.hash, at.hash, {off: function(){}});
|
||||||
@ -879,8 +886,8 @@
|
|||||||
}
|
}
|
||||||
if(1 === path.length){ cb.call(ctx.by.chain || chain, null, at.value, ctx.field) }
|
if(1 === path.length){ cb.call(ctx.by.chain || chain, null, at.value, ctx.field) }
|
||||||
chain._.at('soul').emit(at).chain(opt.chain);
|
chain._.at('soul').emit(at).chain(opt.chain);
|
||||||
});
|
}));
|
||||||
gun._.at('null').only(function(at){
|
ons.push(gun._.at('null').only(function(at){
|
||||||
if(!at.field){ return }
|
if(!at.field){ return }
|
||||||
if(at.not){
|
if(at.not){
|
||||||
gun.put({}, null, {init: true});
|
gun.put({}, null, {init: true});
|
||||||
@ -889,8 +896,8 @@
|
|||||||
(at = Gun.on.at.copy(at)).field = path[0];
|
(at = Gun.on.at.copy(at)).field = path[0];
|
||||||
at.not = true;
|
at.not = true;
|
||||||
chain._.at('null').emit(at).chain(opt.chain);
|
chain._.at('null').emit(at).chain(opt.chain);
|
||||||
});
|
}));
|
||||||
gun._.at('end').event(function(at){
|
ons.push(gun._.at('end').event(function(at){
|
||||||
this.off();
|
this.off();
|
||||||
if(at.at && at.at.field === path[0]){ return } // TODO: BUG! THIS FIXES SO MANY PROBLEMS BUT DOES IT CATCH VARYING SOULS EDGE CASE?
|
if(at.at && at.at.field === path[0]){ return } // TODO: BUG! THIS FIXES SO MANY PROBLEMS BUT DOES IT CATCH VARYING SOULS EDGE CASE?
|
||||||
var ctx = {by: gun.__.by(at.soul)};
|
var ctx = {by: gun.__.by(at.soul)};
|
||||||
@ -899,10 +906,15 @@
|
|||||||
at.not = true;
|
at.not = true;
|
||||||
cb.call(ctx.by.chain || chain, null);
|
cb.call(ctx.by.chain || chain, null);
|
||||||
chain._.at('null').emit(at).chain(opt.chain);
|
chain._.at('null').emit(at).chain(opt.chain);
|
||||||
});
|
}));
|
||||||
if(path.length > 1){
|
if(path.length > 1){
|
||||||
(c = chain.path(path.slice(1), cb, opt)).back = gun;
|
(c = chain.path(path.slice(1), cb, opt)).back = gun;
|
||||||
}
|
}
|
||||||
|
(c || chain).off = function() {
|
||||||
|
ons.forEach(function(on) {
|
||||||
|
on.off();
|
||||||
|
})
|
||||||
|
};
|
||||||
return c || chain;
|
return c || chain;
|
||||||
}
|
}
|
||||||
}());
|
}());
|
||||||
@ -923,7 +935,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cb.hash[this.soul + field] = cb.hash[this.soul + field] || this.gun.path(field, path, {chain: chain, via: 'map'}); // TODO: path should reuse itself! We shouldn't have to do it ourselves.
|
cb.hash[this.soul + field] = cb.hash[this.soul + field] || (pathon = this.gun.path(field, path, {chain: chain, via: 'map'})); // TODO: path should reuse itself! We shouldn't have to do it ourselves.
|
||||||
// TODO:
|
// TODO:
|
||||||
// 1. Ability to turn off an event. // automatically happens within path since reusing is manual?
|
// 1. Ability to turn off an event. // automatically happens within path since reusing is manual?
|
||||||
// 2. Ability to pass chain context to fire on. // DONE
|
// 2. Ability to pass chain context to fire on. // DONE
|
||||||
@ -934,7 +946,11 @@
|
|||||||
var ref = gun.__.by(at.soul).chain || gun;
|
var ref = gun.__.by(at.soul).chain || gun;
|
||||||
Gun.is.node(at.change, each, {gun: ref, soul: at.soul});
|
Gun.is.node(at.change, each, {gun: ref, soul: at.soul});
|
||||||
}
|
}
|
||||||
gun.on(map, {raw: true, change: true}); // TODO: ALLOW USER TO DO map change false!
|
on = gun.on(map, {raw: true, change: true}); // TODO: ALLOW USER TO DO map change false!
|
||||||
|
chain.off = function() {
|
||||||
|
if (pathon) pathon.off();
|
||||||
|
on.off();
|
||||||
|
}
|
||||||
if(gun === gun.back){ Gun.log('You have no context to `.map`!') }
|
if(gun === gun.back){ Gun.log('You have no context to `.map`!') }
|
||||||
return chain;
|
return chain;
|
||||||
}
|
}
|
||||||
@ -1000,8 +1016,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
Gun.chain.set = function(item, cb, opt){
|
Gun.chain.set = function(item, cb, opt){
|
||||||
var gun = this, ctx = {}, chain;
|
var gun = this, ctx = {}, chain, rel;
|
||||||
cb = cb || function(){};
|
cb = cb || function(){};
|
||||||
|
if(Gun.is.node(item) && (rel=Gun.is.rel(item._))){
|
||||||
|
// Resolve set with a node
|
||||||
|
return gun.set(gun.get(rel), cb, opt);
|
||||||
|
}
|
||||||
|
if(typeof(item)=='object'&&!Gun.is(item)&&!Gun.is.rel(item)&&!Gun.is.lex(item)&&!Gun.is.node(item)&&!Gun.is.graph(item)){
|
||||||
|
// Resolve set with a new soul
|
||||||
|
return gun.set(Gun.root(gun).put(item), cb, opt);
|
||||||
|
}
|
||||||
if(!Gun.is(item)){ return cb.call(gun, {err: Gun.log('Set only supports node references currently!')}), gun } // TODO: Bug? Should we return not gun on error?
|
if(!Gun.is(item)){ return cb.call(gun, {err: Gun.log('Set only supports node references currently!')}), gun } // TODO: Bug? Should we return not gun on error?
|
||||||
(ctx.chain = item.chain()).back = gun;
|
(ctx.chain = item.chain()).back = gun;
|
||||||
ctx.chain._ = item._;
|
ctx.chain._ = item._;
|
||||||
|
@ -3757,9 +3757,18 @@ describe('Gun', function(){
|
|||||||
bob.path('friends').set(alice);
|
bob.path('friends').set(alice);
|
||||||
dave.path('friends').set(alice).back.set(carl);
|
dave.path('friends').set(alice).back.set(carl);
|
||||||
|
|
||||||
|
// Test set with new object
|
||||||
|
var alan = users.set({name: 'alan', birth: Math.random()}).key('person/alan');
|
||||||
|
alan.val(function(alan) {
|
||||||
|
// Test set with node
|
||||||
|
dave.path('friends').set(alan);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
var team = gun.get('team/lions').put({name: "Lions"});
|
var team = gun.get('team/lions').put({name: "Lions"});
|
||||||
team.path('members').set(alice);
|
team.path('members').set(alice);
|
||||||
team.path('members').set(bob);
|
team.path('members').set(bob);
|
||||||
|
team.path('members').set(alan);
|
||||||
|
|
||||||
alice.path('team').put(team);
|
alice.path('team').put(team);
|
||||||
bob.path('team').put(team);
|
bob.path('team').put(team);
|
||||||
@ -3771,10 +3780,14 @@ describe('Gun', function(){
|
|||||||
} else
|
} else
|
||||||
if('bob' === member.name){
|
if('bob' === member.name){
|
||||||
done.bob = true;
|
done.bob = true;
|
||||||
} else {
|
} else
|
||||||
|
if('alan' === member.name){
|
||||||
|
done.alan = true;
|
||||||
|
} else
|
||||||
|
{
|
||||||
expect(member).to.not.be.ok();
|
expect(member).to.not.be.ok();
|
||||||
}
|
}
|
||||||
if(done.alice && done.bob){
|
if(done.alice && done.bob && done.alan){
|
||||||
setTimeout(function(){
|
setTimeout(function(){
|
||||||
done();
|
done();
|
||||||
},10);
|
},10);
|
||||||
@ -4191,3 +4204,50 @@ describe('Gun', function(){
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
describe('On', function(){
|
||||||
|
it('emits to former subscribers', function() {
|
||||||
|
var recv = null;
|
||||||
|
Gun.on('on-test-1').event(function(val) {
|
||||||
|
recv = val;
|
||||||
|
});
|
||||||
|
Gun.on('on-test-1').emit('foo');
|
||||||
|
expect(recv).to.be('foo');
|
||||||
|
});
|
||||||
|
it('does not emit to future subscribers', function() {
|
||||||
|
var recv = null;
|
||||||
|
Gun.on('on-test-1').emit('foo');
|
||||||
|
Gun.on('on-test-1').event(function(val) {
|
||||||
|
recv = val;
|
||||||
|
});
|
||||||
|
expect(recv).to.be(null);
|
||||||
|
});
|
||||||
|
it('on subscriptions can unsubscribe', function() {
|
||||||
|
var gun = Gun();
|
||||||
|
var recv;
|
||||||
|
gun.get('on-test-3').put({v: 'foo'});
|
||||||
|
var sub = gun.get('on-test-3').on(function(o) {
|
||||||
|
recv = o.v;
|
||||||
|
});
|
||||||
|
expect(recv).to.be('foo');
|
||||||
|
gun.get('on-test-3').put({v: 'bar'});
|
||||||
|
expect(recv).to.be('bar');
|
||||||
|
sub.off();
|
||||||
|
gun.get('on-test-3').put({v: 'off'});
|
||||||
|
expect(recv).to.be('bar');
|
||||||
|
});
|
||||||
|
it('map subscriptions can unsubscribe', function() {
|
||||||
|
var gun = Gun();
|
||||||
|
var recv;
|
||||||
|
gun.get('on-test-4').put({v: 'foo'});
|
||||||
|
var sub = gun.get('on-test-4').map(function(v, k) {
|
||||||
|
if (v == 'off') throw new Error('unexpected');
|
||||||
|
recv = v;
|
||||||
|
});
|
||||||
|
expect(recv).to.be('foo');
|
||||||
|
gun.get('on-test-4').put({v: 'bar'});
|
||||||
|
expect(recv).to.be('bar');
|
||||||
|
sub.off();
|
||||||
|
gun.get('on-test-4').put({v: 'off'});
|
||||||
|
expect(recv).to.be('bar');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user