mirror of
https://github.com/amark/gun.git
synced 2025-03-30 15:08:33 +00:00
fixed a bunch of issues around graph mapping
This commit is contained in:
parent
09896423cb
commit
e9e8804de8
118
gun.js
118
gun.js
@ -367,7 +367,7 @@
|
||||
function load(key){
|
||||
if(Gun.fns.is(ctx.hook = gun.__.opt.hooks.get)){
|
||||
ctx.hook(key, function(err, data){ // will be called multiple times.
|
||||
console.log("chain.get ", key, "from hook", err, data);
|
||||
console.log("chain.get ", key, "from hook", err, data, '\n');
|
||||
if(err){ return cb.call(gun, err, null) }
|
||||
if(!data){
|
||||
if(ctx.data){ return }
|
||||
@ -418,7 +418,7 @@
|
||||
index({soul: opt.soul});
|
||||
} else { // will be injected via a put
|
||||
(gun.__.flag.start[key] = gun._.at('soul')).once(function($){
|
||||
console.log("chain.key");
|
||||
console.log("chain.key", key, '\n');
|
||||
(gun.__.key.s[key] = gun.__.key.s[key] || {})[$.soul] = gun.__.graph[$.soul];
|
||||
delete gun.__.flag.start[key];
|
||||
}, -1);
|
||||
@ -477,44 +477,39 @@
|
||||
Path ultimately should call .val each time, individually, for what it finds.
|
||||
Things that wait and merge many things together should be an abstraction ontop of path.
|
||||
*/
|
||||
Chain.path = function(path, cb){
|
||||
Chain.path = function(path, cb, opt){
|
||||
var gun = this.chain();
|
||||
cb = cb || function(){};
|
||||
opt = opt || {};
|
||||
if((path !== null && !path) || !Gun.text.is(path = path.join? path.join('.') : path + '')){ return }
|
||||
if(!gun.back._.at){ return cb.call(gun, {err: Gun.log("No context!")}), gun }
|
||||
// TODO: Hmmm once also? figure it out later.
|
||||
gun.back._.at('soul').event(function($){
|
||||
var ctx = {path: (Gun.text.ify(path) || '').split('.')};
|
||||
(function trace($){ // TODO: Check for field as well and merge?
|
||||
if(!ctx.path.length){ return }
|
||||
var node = gun.__.graph[$.soul], field = Gun.text.ify(ctx.path.shift()), soul, val;
|
||||
if(ctx.path.length){
|
||||
if(soul = Gun.is.soul(val = node[field])){
|
||||
gun.get(val, function(err, data){
|
||||
data = (data || {})[soul];
|
||||
if(err || !data || Gun.obj.empty(data, Gun._.meta)){ return cb.call(gun, err) }
|
||||
trace({soul: soul});
|
||||
});
|
||||
} else {
|
||||
cb.call(gun, null);
|
||||
}
|
||||
} else
|
||||
if(!Gun.obj.has(node, field)){ // TODO: THIS MAY NOT BE CORRECT BEHAVIOR!!!!
|
||||
cb.call(gun, null, null, field);
|
||||
gun._.at('soul').emit({soul: $.soul, field: field, PATH: 'SOUL', WAS: 'ON'}); // if .put is after, makes sense. If anything else, makes sense to wait.
|
||||
} else
|
||||
if(soul = Gun.is.soul(val = node[field])){
|
||||
gun.get(val, function(err, data){
|
||||
data = (data || {})[soul];
|
||||
cb.call(gun, err, data, field); // TODO: Should we attach field here, does map?
|
||||
});
|
||||
ctx.node = gun.__.graph[ctx.soul] = gun.__.graph[ctx.soul] || Gun.union.pseudo(soul);
|
||||
gun._.at('soul').emit({soul: soul, field: null, from: $.soul, at: field, PATH: 'SOUL'});
|
||||
} else {
|
||||
cb.call(gun, null, val, field);
|
||||
gun._.at('soul').emit({soul: $.soul, field: field, PATH: 'SOUL'});
|
||||
|
||||
gun.back.on(function($, node){
|
||||
if(!(node = node || gun.__.graph[$.soul])){ return }
|
||||
var chain = this || gun, src = opt.src || gun;
|
||||
var ctx = {path: path.split('.')}, field = Gun.text.ify(ctx.path.shift());
|
||||
var val = node[field], soul = Gun.is.soul(val);
|
||||
console.log("chain.path", field, node, '\n');
|
||||
if(!field && !ctx.path.length){
|
||||
cb.call(chain, null, node, field);
|
||||
return opt.step? src._.at('soul').emit({soul: $.soul, field: null, from: opt.step.soul, at: opt.step.field, gun: chain, PATH: 'SOUL'})
|
||||
: src._.at('soul').emit({soul: $.soul, field: null, gun: chain, PATH: 'SOUL'});
|
||||
}
|
||||
if(!Gun.obj.has(node, field)){
|
||||
if(opt.end || (!ctx.path.length && gun.__.meta($.soul).end)){ // TODO: Make it so you can adjust how many terminations!
|
||||
cb.call(chain, null, null, field);
|
||||
src._.at('soul').emit({soul: $.soul, field: field, gun: chain, PATH: 'SOUL'});
|
||||
}
|
||||
}($));
|
||||
});
|
||||
return;
|
||||
}
|
||||
if(soul){
|
||||
return gun.get(val, function(err, data){
|
||||
if(err){ return cb.call(chain, err) }
|
||||
}).path(ctx.path, cb, {src: src, step: {soul: $.soul, field: field}});
|
||||
}
|
||||
cb.call(chain, null, val, field);
|
||||
return src._.at('soul').emit({soul: $.soul, field: field, gun: chain, PATH: 'SOUL'});
|
||||
}, {raw: true, once: true});
|
||||
|
||||
return gun;
|
||||
}
|
||||
@ -536,11 +531,11 @@
|
||||
if($.field){
|
||||
if(ctx[$.soul + $.field]){ return }
|
||||
ctx[$.soul + $.field] = true; // TODO: unregister instead?
|
||||
return cb.call(gun, node[$.field], $.field || $.at);
|
||||
return cb.call($.gun || gun, node[$.field], $.field || $.at);
|
||||
}
|
||||
if(ctx[$.soul] || ($.key && ctx[$.key]) || !gun.__.meta($.soul).end){ return } // TODO: Add opt to change number of terminations.
|
||||
ctx[$.soul] = ctx[$.key] = true; // TODO: unregister instead?
|
||||
cb.call(gun, Gun.obj.copy(node), $.field || $.at);
|
||||
cb.call($.gun || gun, Gun.obj.copy(node), $.field || $.at);
|
||||
}, {raw: true});
|
||||
|
||||
return gun;
|
||||
@ -551,7 +546,6 @@
|
||||
var gun = this, ctx = {};
|
||||
opt = Gun.obj.is(opt)? opt : {change: opt};
|
||||
cb = cb || function(){};
|
||||
|
||||
gun._.at('soul').event(function($){ // TODO: once per soul on graph. (?)
|
||||
if(ctx[$.soul]){
|
||||
if(opt.raw){
|
||||
@ -559,13 +553,15 @@
|
||||
}
|
||||
} else {
|
||||
(ctx[$.soul] = function(delta, $$){
|
||||
var $$ = $$ || $, node = gun.__.graph[$$.soul];
|
||||
if(opt.raw){ return cb.call(gun, $$, delta, this) }
|
||||
$$ = $$ || $; var node = gun.__.graph[$$.soul];
|
||||
if(delta && $.soul != Gun.is.soul.on(delta)){ return }
|
||||
if(opt.raw){ return cb.call($$.gun || gun, $$, delta, this) }
|
||||
if(!opt.end && Gun.obj.empty(delta, Gun._.meta)){ return }
|
||||
if($$.key){ node = Gun.union.pseudo($.key, gun.__.key.s[$.key]) || node }
|
||||
cb.call(gun, Gun.obj.copy(opt.change? delta || node : node), $$.field || $$.at);
|
||||
if(opt.change){ node = delta || node }
|
||||
cb.call($$.gun || gun, Gun.obj.copy($$.field? node[$$.field] : node), $$.field || $$.at);
|
||||
})(gun.__.graph[$.soul], $);
|
||||
gun.__.on($.soul).event(ctx[$.soul]);
|
||||
if(!opt.once){ gun.__.on($.soul).event(ctx[$.soul]) }
|
||||
}
|
||||
});
|
||||
|
||||
@ -595,8 +591,9 @@
|
||||
if(gun.back.not){ gun.back.not(call) }
|
||||
|
||||
gun.back._.at('soul').event(function($){ // TODO: maybe once per soul?
|
||||
var chain = $.gun || gun;
|
||||
var ctx = {}, obj = val, $ = Gun.obj.copy($);
|
||||
console.log("chain.put", val);
|
||||
console.log("chain.put", val, '\n');
|
||||
if(Gun.is.value(obj)){
|
||||
if($.from && $.at){
|
||||
$.soul = $.from;
|
||||
@ -636,7 +633,7 @@
|
||||
env.graph[at.node._[Gun._.soul] = at.soul] = at.node;
|
||||
cb(at, at.soul);
|
||||
};
|
||||
$.empty? path() : gun.back.path(at.path.join('.'), path); // TODO: clean this up.
|
||||
$.empty? path() : gun.back.path(at.path, path, {once: true, end: true}); // TODO: clean this up.
|
||||
}
|
||||
}
|
||||
if(!at.node._[Gun._.HAM]){
|
||||
@ -645,7 +642,7 @@
|
||||
if(!at.field){ return }
|
||||
at.node._[Gun._.HAM][at.field] = drift;
|
||||
})(function(err, ify){
|
||||
console.log("chain.put PUT <----", ify.graph);
|
||||
console.log("chain.put PUT <----", ify.graph, '\n');
|
||||
if(err || ify.err){ return cb.call(gun, err || ify.err) }
|
||||
if(err = Gun.union(gun, ify.graph).err){ return cb.call(gun, err) }
|
||||
if($.from = Gun.is.soul(ify.root[$.field])){ $.soul = $.from; $.field = null }
|
||||
@ -670,26 +667,23 @@
|
||||
opt = (Gun.obj.is(opt)? opt : (opt? {node: true} : {}));
|
||||
cb = cb || function(){};
|
||||
|
||||
gun.back.on(function(node){ // oo what if this gets TODO: BUG! retriggered?
|
||||
gun.back.on(function(node){
|
||||
var soul = Gun.is.soul.on(node);
|
||||
console.log("chain.map", node, '\n');
|
||||
Gun.obj.map(node, function(val, field){ // maybe filter against known fields.
|
||||
if(Gun._.meta == field){ return }
|
||||
var s = Gun.is.soul(val);
|
||||
if(s){
|
||||
gun.get(val, function(err, data){
|
||||
data = (data || {})[s]; // TODO: should map have support for `.not`? error?
|
||||
if(err || !data || Gun.obj.empty(data, Gun._.meta)){ return }
|
||||
cb.call(this, Gun.obj.copy(data), field);
|
||||
});
|
||||
gun.__.graph[s] = gun.__.graph[s] || Gun.union.pseudo(s);
|
||||
gun._.at('soul').emit({soul: s, field: null, from: soul, at: field, MAP: 'SOUL'});
|
||||
gun.get(val).on(function(d, f){
|
||||
cb.call(this, d, f || field);
|
||||
gun._.at('soul').emit({soul: s, field: null, from: soul, at: field, MAP: 'SOUL', gun: this})
|
||||
}); //, {once: true});
|
||||
} else {
|
||||
if(opt.node){ return } // {node: true} maps over only sub nodes.
|
||||
console.log("trigger next thing", field, val);
|
||||
cb.call(gun, val, field);
|
||||
cb.call(this, val, field);
|
||||
gun._.at('soul').emit({soul: soul, field: field, MAP: 'SOUL'});
|
||||
}
|
||||
});
|
||||
}, this || gun);
|
||||
}, true);
|
||||
|
||||
return gun;
|
||||
@ -700,11 +694,11 @@
|
||||
opt = opt || {};
|
||||
|
||||
if(!gun.back){ gun = gun.put({}) }
|
||||
gun = gun.not(function(next, key){ return key? this.put({}).key(key) : this.put({}) });
|
||||
gun = gun.not(function(key){ return key? this.put({}).key(key) : this.put({}) });
|
||||
if(!val && !Gun.is.value(val)){ return gun }
|
||||
var obj = {};
|
||||
obj['I' + drift + 'R' + Gun.text.random(5)] = val;
|
||||
return gun.put(obj, cb);
|
||||
var obj = {}, index = 'I' + drift + 'R' + Gun.text.random(5);
|
||||
obj[index] = val;
|
||||
return Gun.is.value(val)? gun.put(obj, cb) : gun.put(obj, cb).path(index);
|
||||
}
|
||||
Chain.not = function(cb){
|
||||
var gun = this, ctx = {};
|
||||
@ -716,7 +710,7 @@
|
||||
var kick = function(next){
|
||||
if(++c){ return Gun.log("Warning! Multiple `not` resumes!"); }
|
||||
next._.at('soul').once(function($){ $.N0T = 'KICK SOUL'; gun._.at('soul').emit($) });
|
||||
}, chain = gun.chain(), next = cb.call(chain, kick, key), c = -1;
|
||||
}, chain = gun.chain(), next = cb.call(chain, key, kick), c = -1;
|
||||
if(Gun.is(next)){ kick(next) }
|
||||
chain._.at('soul').emit({soul: Gun.roulette.call(chain), empty: true, key: key, N0T: 'SOUL', WAS: 'ON'}); // WAS ON
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gun",
|
||||
"version": "0.2.0-alpha-2",
|
||||
"version": "0.2.0-alpha-3",
|
||||
"description": "Graph engine",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
|
131
test/common.js
131
test/common.js
@ -7,6 +7,7 @@ Gun.log.squelch = true;
|
||||
|
||||
describe('Gun', function(){
|
||||
var t = {};
|
||||
|
||||
describe('Utility', function(){
|
||||
|
||||
it('verbose console.log debugging', function(done) { console.log("TURN THIS BACK ON the DEBUGGING TEST"); done(); return;
|
||||
@ -829,7 +830,7 @@ describe('Gun', function(){
|
||||
var gun = Gun();
|
||||
|
||||
it('put', function(done){
|
||||
gun.put("hello", function(err){
|
||||
gun.put("hello", function(err, ok){
|
||||
expect(err).to.be.ok();
|
||||
done();
|
||||
});
|
||||
@ -953,12 +954,13 @@ describe('Gun', function(){
|
||||
}, 500);
|
||||
});
|
||||
|
||||
/*
|
||||
/* // not sure what this is suppose to do. Review later
|
||||
it('get key no data put', function(done){
|
||||
gun.get('this/key/definitely/does/not/exist', function(err, data){
|
||||
expect(err).to.not.be.ok();
|
||||
expect(data).to.not.be.ok();
|
||||
}).put({testing: 'stuff'}, function(err, ok){
|
||||
console.log("what?", err, ok);
|
||||
expect(err).to.not.be.ok();
|
||||
var node = gun.__.graph[done.soul];
|
||||
expect(node.hello).to.be('key');
|
||||
@ -1082,7 +1084,7 @@ describe('Gun', function(){
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
/* // Future feature!
|
||||
it('put gun node', function(done){
|
||||
var mark = gun.put({age: 23, name: "Mark Nadal"});
|
||||
var amber = gun.put({age: 23, name: "Amber Nadal"});
|
||||
@ -1548,7 +1550,7 @@ describe('Gun', function(){
|
||||
});
|
||||
|
||||
it('double not', function(done){ // from the thought tutorial
|
||||
var gun = Gun().get('thoughts').not(function(n, key){
|
||||
var gun = Gun().get('thoughts').not(function(key){
|
||||
return this.put({}).key(key);
|
||||
});
|
||||
|
||||
@ -1584,7 +1586,7 @@ describe('Gun', function(){
|
||||
});
|
||||
|
||||
gun.set(1).set(2).set(3).set(4); // if you set an object you'd have to do a `.back`
|
||||
gun.map().val(function(val){
|
||||
gun.map().val(function(val, field){
|
||||
i += 1;
|
||||
expect(val).to.be(i);
|
||||
if(i % 4 === 0){
|
||||
@ -1592,6 +1594,7 @@ describe('Gun', function(){
|
||||
done.i = 0;
|
||||
Gun.obj.map(gun.__.graph, function(){ done.i++ });
|
||||
expect(done.i).to.be(1); // make sure there isn't double.
|
||||
Gun.log.verbose = false;
|
||||
done()
|
||||
},10);
|
||||
}
|
||||
@ -1715,6 +1718,124 @@ describe('Gun', function(){
|
||||
},10);
|
||||
},10);
|
||||
});
|
||||
|
||||
it("get map val -> map val", function(done){ // Terje's bug
|
||||
var gun = Gun(); // we can test GUN locally.
|
||||
var passengers = gun.get('passengers'); // this is now a list of passengers that we will map over.
|
||||
var ctx = {n: 0, d: 0, l: 0};
|
||||
passengers.map().val(function(passenger, id){
|
||||
this.map().val(function(change, field){
|
||||
//console.log("Passenger", passenger.name, "had", field, "change to:", change, '\n\n');
|
||||
if('name' == field){ expect(change).to.be(passenger.name); ctx.n++ }
|
||||
if('direction' == field){ expect(change).to.be(passenger.direction); ctx.d++ }
|
||||
if('location' == field){
|
||||
delete change._; ctx.l++;
|
||||
if('Bob' == passenger.name){
|
||||
expect(change).to.eql({'lat': '37.6159', 'lng': '-128.5'});
|
||||
} else {
|
||||
expect(change).to.eql({'lat': 'f37.6159', 'lng': 'f-128.5'});
|
||||
}
|
||||
}
|
||||
if(ctx.n == 2 && ctx.d == 2 && ctx.l == 2){ done() }
|
||||
});
|
||||
});
|
||||
var bob = passengers.set({
|
||||
name: "Bob",
|
||||
location: {'lat': '37.6159', 'lng': '-128.5'},
|
||||
direction: '128.2'
|
||||
});
|
||||
var fred = passengers.set({
|
||||
name: "Fred",
|
||||
location: {'lat': 'f37.6159', 'lng': 'f-128.5'},
|
||||
direction: 'f128.2'
|
||||
});
|
||||
});
|
||||
|
||||
it("get map map val", function(done){ // Terje's bug
|
||||
var gun = Gun(); // we can test GUN locally.
|
||||
var passengers = gun.get('passengers/map'); // this is now a list of passengers that we will map over.
|
||||
var ctx = {n: 0, d: 0, l: 0};
|
||||
passengers.map().map().val(function(val, field){
|
||||
if('name' == field){ expect(val).to.be(!ctx.n? 'Bob' : 'Fred'); ctx.n++ }
|
||||
if('direction' == field){ expect(val).to.be(!ctx.d? '128.2' : 'f128.2'); ctx.d++ }
|
||||
if('location' == field){
|
||||
delete val._;
|
||||
if(!ctx.l){
|
||||
expect(val).to.eql({'lat': '37.6159', 'lng': '-128.5'});
|
||||
} else {
|
||||
expect(val).to.eql({'lat': 'f37.6159', 'lng': 'f-128.5'});
|
||||
}
|
||||
ctx.l++;
|
||||
}
|
||||
if(ctx.n == 2 && ctx.d == 2 && ctx.l == 2){ done() }
|
||||
});
|
||||
var bob = passengers.set({
|
||||
name: "Bob",
|
||||
location: {'lat': '37.6159', 'lng': '-128.5'},
|
||||
direction: '128.2'
|
||||
});
|
||||
setTimeout(function(){
|
||||
var fred = passengers.set({
|
||||
name: "Fred",
|
||||
location: {'lat': 'f37.6159', 'lng': 'f-128.5'},
|
||||
direction: 'f128.2'
|
||||
});
|
||||
},100);
|
||||
});
|
||||
|
||||
it("get map path val", function(done){ // Terje's bug
|
||||
var gun = Gun();
|
||||
var ctx = {l: -1, d: 0};
|
||||
var passengers = gun.get('passengers/path');
|
||||
passengers.map().path('location.lng').val(function(val, field){
|
||||
expect(field).to.be('lng');
|
||||
if(ctx.l){
|
||||
expect(val).to.be('-128.5');
|
||||
} else {
|
||||
expect(val).to.eql('f-128.5');
|
||||
}
|
||||
ctx.l++;
|
||||
if(ctx.l){ done() }
|
||||
});
|
||||
var bob = passengers.set({
|
||||
name: "Bob",
|
||||
location: {'lat': '37.6159', 'lng': '-128.5'},
|
||||
direction: '128.2'
|
||||
});
|
||||
setTimeout(function(){
|
||||
var fred = passengers.set({
|
||||
name: "Fred",
|
||||
location: {'lat': 'f37.6159', 'lng': 'f-128.5'},
|
||||
direction: 'f128.2'
|
||||
});
|
||||
},100);
|
||||
});
|
||||
|
||||
it("put path deep val -> path val", function(done){ // Terje's bug
|
||||
var gun = Gun();
|
||||
gun.put({you: {have: {got: {to: {be: {kidding: "me!"}}}}}}).path('you.have.got.to.be').val(function(val, field){
|
||||
expect(val.kidding).to.be('me!');
|
||||
this.path('kidding').val(function(val){
|
||||
expect(val).to.be('me!');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("get set path put, map path val -> path val", function(done){ // Terje's bug
|
||||
var gun = Gun();
|
||||
var ctx = {l: -1, d: 0};
|
||||
var passengers = gun.get('passengers/set/path');
|
||||
passengers.set({name: 'Bob'}).path('direction').put({lol: {just: 'kidding', dude: '!'}}, function(err, ok){});
|
||||
passengers.map().path('direction.lol').val(function(val){
|
||||
this.path('just').val(function(val){
|
||||
expect(val).to.be('kidding');
|
||||
}).back.path('dude').val(function(val){
|
||||
expect(val).to.be('!');
|
||||
done();
|
||||
});
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('Streams', function(){
|
||||
|
Loading…
x
Reference in New Issue
Block a user