mirror of
https://github.com/amark/gun.git
synced 2025-03-30 15:08:33 +00:00
all core tests passing.
This commit is contained in:
parent
6908df0405
commit
85ee6fd07c
@ -2,11 +2,11 @@
|
||||
|
||||
## 0.3
|
||||
|
||||
Migration Guide! Migrate by changing `.attach(` to `.wsp(` on your server if you have one with gun. Change `.set()` (empty call) to `` (aka delete it), and change `.set($DATA)` (where you call set with something) to `.path('I' + Date.now() + 'R' + Gun.text.random(5)).put($DATA)`. If you have NodeJS style callbacks in your `.get` (which documentation previously recommended that you shouldn't) they previous took `err, graph` and now they take `err, node` (which means now using callback style is fine to use). If you are a module developer, use `opt.wire` now instead of `opt.hooks` and message Mark since he needs to talk to you since the wire protocol has changed.
|
||||
Migration Guide! Migrate by changing `.attach(` to `.wsp(` on your server if you have one with gun. Change `.set()` (empty call) to `` (aka delete it), and change `.set($DATA)` (where you call set with something) to `.path('I' + Date.now() + 'R' + Gun.text.random(5)).put($DATA)`. If you have NodeJS style callbacks in your `.get` (which documentation previously recommended that you shouldn't) they previous took `err, graph` and now they take `err, node` (which means now using callback style is fine to use). Inside of `.not()` no longer use `return` or `this`, instead (probably) use `gun` and no `return`. If you are a module developer, use `opt.wire` now instead of `opt.hooks` and message Mark since he needs to talk to you since the wire protocol has changed.
|
||||
|
||||
- Server side default `.wsp()` renamed from `.attach()`.
|
||||
- `.set()` deprecated because it did a bunch of random inconsistent things. Its useful behavior has now become implicit (see below) or can be done explicitly.
|
||||
- `.not()` it was previously common to `return` the chain inside of .not, beware that if you have code like `gun.get(key).not(function(){ return this.put({}).key(key) }).val()` it will cause `.val()` to be triggered twice (this is intentional, because it funnels two separate chains together) which previously didn't happen. To fix this, just don't return the chain.
|
||||
- `.not()` it was previously common to `return` the chain inside of .not, beware that if you have code like `gun.get(key).not(function(){ return this.put({}).key(key) }).val()` cause `.val()` to be triggered twice (this is intentional, because it funnels two separate chains together) which previously didn't happen. To fix this, just don't return the chain.
|
||||
- `.put()` and `.path()` do implicit `.init()` by default, turn on explicit behavior with `Gun({init: true})`.
|
||||
- `.get(soul, cb)` cb is called back with `err, node` rather than `err, graph`.
|
||||
- Options `opt.wire` renamed from `opt.hooks`.
|
||||
|
138
gun.js
138
gun.js
@ -345,9 +345,7 @@
|
||||
if(!ctx.graph){ ctx.err = {err: Gun.log("No graph!") } }
|
||||
if(!prime){ ctx.err = {err: Gun.log("No data to merge!") } }
|
||||
if(ctx.soul = Gun.is.node.soul(prime)){ prime = Gun.is.graph.ify(prime) }
|
||||
if(!Gun.is.graph(prime, function(node, soul){
|
||||
//ctx.graph[soul] = ctx.graph[soul] || Gun.is.node.ify({}, soul); // TODO: BUG! Without this path thinks it has to load it.
|
||||
}, function(val, field, node){ var meta;
|
||||
if(!Gun.is.graph(prime, null, function(val, field, node){ var meta;
|
||||
if(!(meta = (node||{})[Gun._.meta]) || !(meta = meta[Gun._.state]) || !Gun.num.is(meta[field])){
|
||||
return ctx.err = {err: Gun.log("No state on '" + field + "'!") }
|
||||
}
|
||||
@ -356,8 +354,13 @@
|
||||
Gun.on('operating').emit(gun, at);
|
||||
}
|
||||
(function union(graph, prime){
|
||||
var prime = Gun.obj.map(prime, function(n,s,t){t(n)}).sort(function(A,B){
|
||||
var s = Gun.is.node.soul(A);
|
||||
if(graph[s]){ return 1 }
|
||||
return 0;
|
||||
});
|
||||
ctx.count += 1;
|
||||
ctx.err = Gun.obj.map(prime, function(node, soul){
|
||||
ctx.err = Gun.list.map(prime, function(node, soul){
|
||||
soul = Gun.is.node.soul(node);
|
||||
if(!soul){ return {err: Gun.log("Soul missing or mismatching!")} }
|
||||
ctx.count += 1;
|
||||
@ -386,7 +389,6 @@
|
||||
}
|
||||
|
||||
Gun.union.ify = function(gun, prime, cb, opt){
|
||||
/*
|
||||
if(gun){ gun = (gun.__ && gun.__.graph)? gun.__.graph : gun }
|
||||
if(Gun.text.is(prime)){
|
||||
if(gun && gun[prime]){
|
||||
@ -396,16 +398,6 @@
|
||||
}
|
||||
}
|
||||
var vertex = Gun.is.node.soul.ify({}, Gun.is.node.soul(prime)), prime = Gun.is.graph.ify(prime) || prime;
|
||||
*/
|
||||
if(gun){ gun = (gun.__ && gun.__.graph)? gun.__.graph : gun }
|
||||
if(Gun.text.is(prime)){
|
||||
if(gun && gun[prime]){
|
||||
prime = gun[prime];
|
||||
} else {
|
||||
return Gun.is.node.ify({_: Gun.obj.put({}, 'key', 1) }, prime);
|
||||
}
|
||||
}
|
||||
var vertex = Gun.is.node.soul.ify({_: Gun.obj.put({}, 'key', 1)}, Gun.is.node.soul(prime)), prime = Gun.is.graph.ify(prime) || prime;
|
||||
if(Gun.is.graph(prime, null, function(val, field){ var node;
|
||||
function merge(a, f, v){ Gun.is.node.state.ify(a, f, v) }
|
||||
if(Gun.is.rel(val)){ node = gun? gun[field] || prime[field] : prime[field] }
|
||||
@ -496,7 +488,7 @@
|
||||
return Gun.obj.map(proxy.mem[proxy.e], function(at){
|
||||
i.stat = {first: true};
|
||||
cb.call(i, at);
|
||||
}), i;
|
||||
}), i.stat = {}, i;
|
||||
}
|
||||
proxy.map = function(cb, i){
|
||||
return proxy.event(cb, i);
|
||||
@ -560,10 +552,11 @@
|
||||
ctx.soul = at.field? at.soul : (at.at && at.at.soul) || at.soul; // figure out where we are
|
||||
ctx.field = at.field? at.field : (at.at && at.at.field) || at.field; // did we come from some where?
|
||||
ctx.by = chain.__.by(ctx.soul);
|
||||
ctx.not = at.not || (at.at && at.at.not);
|
||||
Gun.obj.del(at, 'not'); Gun.obj.del(at.at || at, 'not'); // the data is no longer not known! // TODO: BUG! It could have been asynchronous by the time we now delete these properties. Don't other parts of the code assume their deletion is synchronous?
|
||||
if(ctx.field){ Gun.obj.as(ctx.obj = {}, ctx.field, val) } // if there is a field, then data is actually getting put on the parent.
|
||||
else if(!Gun.obj.is(val)){ return cb.call(chain, ctx.err = {err: Gun.log("No node exists to put " + (typeof val) + ' "' + val + '" in!')}), chain._.at('err').emit(ctx.err) } // if the data is a primitive and there is no context for it yet, then we have an error.
|
||||
// TODO: BUG? gun.get(key).path(field).put() isn't doing it as pseudo.
|
||||
console.debug(1, 'chain.put', val, at);
|
||||
function soul(env, cb, map){ var eat;
|
||||
if(!env || !(eat = env.at) || !env.at.node){ return }
|
||||
if(!eat.node._){ eat.node._ = {} }
|
||||
@ -571,11 +564,9 @@
|
||||
if(!Gun.is.node.soul(eat.node)){
|
||||
if(ctx.obj === eat.obj){
|
||||
Gun.obj.as(env.graph, eat.soul = Gun.obj.as(eat.node._, Gun._.soul, Gun.is.node.soul(eat.obj) || ctx.soul), eat.node);
|
||||
console.debug(2, 'chain.put soul root', eat.soul);
|
||||
cb(eat, eat.soul);
|
||||
} else {
|
||||
var path = function(err, node){
|
||||
console.debug(4, 'chain.put soul path RESOLVED', err, node);
|
||||
if(path.opt && path.opt.on && path.opt.on.off){ path.opt.on.off() }
|
||||
if(path.opt.done){ return }
|
||||
path.opt.done = true;
|
||||
@ -583,9 +574,8 @@
|
||||
eat.soul = Gun.is.node.soul(node) || Gun.is.node.soul(eat.obj) || Gun.is.node.soul(eat.node) || Gun.text.random();
|
||||
Gun.obj.as(env.graph, Gun.obj.as(eat.node._, Gun._.soul, eat.soul), eat.node);
|
||||
cb(eat, eat.soul);
|
||||
}; path.opt = {once: true, rel: true, stun: true, init: true};
|
||||
console.debug(3, 'chain.put soul path', eat.path, at);
|
||||
(at.not)? path() : ((at.field || at.at)? gun.back : gun).path(eat.path || [], path, path.opt);
|
||||
}; path.opt = {put: true};
|
||||
(ctx.not)? path() : ((at.field || at.at)? gun.back : gun).path(eat.path || [], path, path.opt);
|
||||
}
|
||||
}
|
||||
if(!eat.field){ return }
|
||||
@ -609,9 +599,13 @@
|
||||
if(!Gun.log.count('no-wire-put')){ Gun.log("Warning! You have no persistence layer to save to!") }
|
||||
cb.call(chain, null); // This is in memory success, hardly "success" at all.
|
||||
}
|
||||
Gun.obj.del(at, 'not'); Gun.obj.del(at.at || at, 'not'); // the data is no longer not known!
|
||||
ctx.field? chain.get(ctx.soul).path(ctx.field, null, {chain: opt.chain || chain, via: 'put end'})
|
||||
: chain.get(ctx.soul, null, {chain: opt.chain || chain});
|
||||
if(ctx.field){
|
||||
return gun.back.path(ctx.field, null, {chain: opt.chain || chain});
|
||||
}
|
||||
if(ctx.not){
|
||||
return gun.__.gun.get(ctx.soul, null, {chain: opt.chain || chain});
|
||||
}
|
||||
chain.get(ctx.soul, null, {chain: opt.chain || chain, at: gun._.at })
|
||||
}
|
||||
Gun.ify(ctx.obj, soul, {pure: true})(end); // serialize the data!
|
||||
}
|
||||
@ -620,34 +614,35 @@
|
||||
} else { // else if we are on an existing chain then...
|
||||
gun._.at('soul').map(put); // put data on every soul that flows through this chain.
|
||||
var back = function(gun){
|
||||
if(gun.back === gun){ return }
|
||||
if(gun.back === gun || gun._.not){ return } // TODO: CLEAN UP! Would be ideal to accomplish this in a more ideal way.
|
||||
gun._.at('null').event(function(at){
|
||||
if(opt.init || gun.__.opt.init){ return Gun.log("Warning! You have no context to `.put`", val, "!") }
|
||||
gun.init();
|
||||
});
|
||||
}, -999);
|
||||
return back(gun.back);
|
||||
};
|
||||
back(gun)
|
||||
if(!opt.init && !gun.__.opt.init){ back(gun) }
|
||||
}
|
||||
chain.back = gun.back;
|
||||
return chain;
|
||||
}
|
||||
|
||||
Gun.chain.get = (function(){
|
||||
Gun.on('operating').event(function(gun, at){
|
||||
if(gun.__.by && !gun.__.by(at.soul).node){ gun.__.by(at.soul).node = gun.__.graph[at.soul] }
|
||||
if(!gun.__.by(at.soul).node){ gun.__.by(at.soul).node = gun.__.graph[at.soul] }
|
||||
if(at.field){ return } // TODO: It would be ideal to reuse HAM's field emit.
|
||||
console.debug(1, 'HAM emitted to operating state', at);
|
||||
gun.__.on(at.soul).emit(at);
|
||||
});
|
||||
Gun.on('get').event(function(gun, at, ctx, opt, cb){
|
||||
if(ctx.halt){ ctx.halt = false; return } // TODO: CLEAN UP with event emitter option?
|
||||
if(ctx.halt){ return } // TODO: CLEAN UP with event emitter option?
|
||||
at.change = at.change || gun.__.by(at.soul).node;
|
||||
if(opt.raw){ return cb.call(opt.on, at) }
|
||||
console.debug(3, 'get on.get', at);
|
||||
cb.call(ctx.by.chain, null, Gun.obj.copy(at.change));
|
||||
if(!ctx.cb.no){ cb.call(ctx.by.chain, null, Gun.obj.copy(ctx.node || gun.__.by(at.soul).node)) }
|
||||
gun._.at('soul').emit(at).chain(opt.chain);
|
||||
console.debug(4, 'get done on.get', at);
|
||||
},0);
|
||||
Gun.on('get').event(function(gun, at, ctx){
|
||||
if(ctx.halt){ ctx.halt = false; return } // TODO: CLEAN UP with event emitter option?
|
||||
}, Infinity);
|
||||
return function(lex, cb, opt){ // get opens up a reference to a node and loads it.
|
||||
var gun = this, ctx = {
|
||||
opt: opt || {},
|
||||
@ -655,11 +650,11 @@
|
||||
lex: (Gun.text.is(lex) || Gun.num.is(lex))? Gun.is.rel.ify(lex) : lex,
|
||||
};
|
||||
ctx.force = ctx.opt.force;
|
||||
if(cb !== ctx.cb){ ctx.cb.no = true }
|
||||
if(!Gun.obj.is(ctx.lex)){ return ctx.cb.call(gun = gun.chain(), {err: Gun.log('Invalid get request!', lex)}), gun }
|
||||
if(!(ctx.soul = ctx.lex[Gun._.soul])){ return ctx.cb.call(gun = this.chain(), {err: Gun.log('No soul to get!')}), gun } // TODO: With `.all` it'll be okay to not have an exact match!
|
||||
ctx.by = gun.__.by(ctx.soul);
|
||||
ctx.by.chain = ctx.by.chain || gun.chain();
|
||||
ctx.by.at = ctx.by.at || gun.__.at(ctx.soul);
|
||||
function load(lex){
|
||||
var cached = gun.__.by(lex[Gun._.soul]).node;
|
||||
if(ctx.force){ ctx.force = false }
|
||||
@ -691,10 +686,9 @@
|
||||
function on(at){
|
||||
if(on.ran = true){ ctx.opt.on = this }
|
||||
if(load(ctx.lex)){ return }
|
||||
console.debug(2, 'chain.get', at);
|
||||
Gun.on('get').emit(ctx.by.chain, at, ctx, ctx.opt, ctx.cb, ctx.lex);
|
||||
}
|
||||
ctx.opt.on = ctx.by.at.event(on);
|
||||
ctx.opt.on = (ctx.opt.at || gun.__.at)(ctx.soul).event(on);
|
||||
if(!ctx.opt.ran && !on.ran){ on.call(ctx.opt.on, {soul: ctx.soul}) }
|
||||
return ctx.by.chain;
|
||||
}
|
||||
@ -718,14 +712,14 @@
|
||||
if(ctx.halt){ return } // TODO: CLEAN UP with event emitter option?
|
||||
if(opt.key && opt.key.soul){
|
||||
at.soul = opt.key.soul;
|
||||
var pseudo = gun.__.by(opt.key.soul).node = Gun.union.ify(gun, opt.key.soul); // TODO: Check performance?
|
||||
(pseudo||{_:{}})._['key'] = 'pseudo';
|
||||
at.change = pseudo;
|
||||
gun.__.by(opt.key.soul).node = Gun.union.ify(gun, opt.key.soul); // TODO: Check performance?
|
||||
gun.__.by(opt.key.soul).node._['key'] = 'pseudo';
|
||||
at.change = Gun.is.node.soul.ify(at.change || gun.__.by(at.soul).node, at.soul, true);
|
||||
return;
|
||||
}
|
||||
var node = at.change || gun.__.graph[at.soul];
|
||||
if(!(Gun.is.node.soul(node, 'key') === 1)){ return }
|
||||
function map(rel, soul){ gun.__.gun.get(rel, cb, {raw: false, key: ctx, chain: opt.chain || gun, force: opt.force}) }
|
||||
function map(rel, soul){ gun.__.gun.get(rel, cb, {key: ctx, chain: opt.chain || gun, force: opt.force}) }
|
||||
ctx.halt = true;
|
||||
Gun.is.node(node, map);
|
||||
},-999);
|
||||
@ -738,9 +732,9 @@
|
||||
var ctx = {node: gun.__.graph[at.soul]};
|
||||
if(at.soul === key || at.key === key){ return }
|
||||
if(cb.hash[at.hash = at.hash || Gun.on.at.hash(at)]){ return } cb.hash[at.hash] = true;
|
||||
ctx.obj = (1 === Gun.is.node.soul(ctx.node, 'key'))? ctx.node : Gun.obj.put({}, at.soul, Gun.is.rel.ify(at.soul));
|
||||
ctx.obj = (1 === Gun.is.node.soul(ctx.node, 'key'))? Gun.obj.copy(ctx.node) : Gun.obj.put({}, at.soul, Gun.is.rel.ify(at.soul));
|
||||
Gun.obj.as((ctx.put = Gun.is.node.ify(ctx.obj, key, null, true))._, 'key', 1);
|
||||
gun.__.gun.put(ctx.put, function(err, ok){cb.call(this, err, ok)}, {chain: opt.chain, key: true});
|
||||
gun.__.gun.put(ctx.put, function(err, ok){cb.call(this, err, ok)}, {chain: opt.chain, key: true, init: true});
|
||||
}
|
||||
if(opt.soul){
|
||||
index({soul: opt.soul});
|
||||
@ -761,8 +755,9 @@
|
||||
cb = cb || function(){};
|
||||
function map(at){
|
||||
opt.on = opt.on || this;
|
||||
if(opt.raw){ return cb.call(opt.on, at) }
|
||||
var ctx = {by: gun.__.by(at.soul)}, change = ctx.by.node;
|
||||
if(opt.on.stat && opt.on.stat.first){ (at = Gun.on.at.copy(at)).change = ctx.by.node }
|
||||
if(opt.raw){ return cb.call(opt.on, at) }
|
||||
if(opt.once){ this.off() }
|
||||
if(opt.change){ change = at.change }
|
||||
if(!opt.empty && Gun.obj.empty(change, Gun._.meta)){ return }
|
||||
@ -779,54 +774,56 @@
|
||||
if(opt.path){ at.at = opt.path }
|
||||
var xtc = {soul: lex[Gun._.soul], field: lex[Gun._.field]};
|
||||
xtc.change = at.change || gun.__.by(at.soul).node;
|
||||
/*
|
||||
if(xtc.field){ // TODO: future feature!
|
||||
console.log("there is never a lexical field", lex);
|
||||
if(!Gun.obj.has(xtc.change, xtc.field)){ return }
|
||||
ctx.node = Gun.is.node.soul.ify({}, at.soul); // TODO: CLEAN UP! ctx.node usage.
|
||||
Gun.is.node.state.ify([ctx.node, xtc.change], xtc.field, xtc.change[xtc.field]);
|
||||
at.change = ctx.node; at.field = xtc.field;
|
||||
}
|
||||
*/
|
||||
},-99);
|
||||
Gun.on('get').event(function(gun, at, ctx, opt, cb, lex){
|
||||
if(ctx.halt){ return } // TODO: CLEAN UP with event emitter option?
|
||||
var xtc = {}; xtc.change = at.change || gun.__.by(at.soul).node;
|
||||
console.debug(5, 'path on.get', at);
|
||||
Gun.is.node(xtc.change, function(v,f){
|
||||
var fat = Gun.on.at.copy(at); fat.field = f; fat.value = v;
|
||||
Gun.obj.del(fat, 'at'); // TODO: CLEAN THIS UP! It would be nice in every other function every where else it didn't matter whether there was a cascading at.at.at.at or not, just and only whether the current context as a field or should rely on a previous field. But maybe that is the gotcha right there?
|
||||
fat.change = fat.change || xtc.change;
|
||||
if(v = Gun.is.rel(fat.value)){ fat = {soul: v, at: fat} }
|
||||
gun._.at('path:' + f).emit(fat).chain(opt.chain);
|
||||
});
|
||||
if(!opt.put){ // TODO: CLEAN UP be nice if path didn't have to worry about this.
|
||||
Gun.is.node(xtc.change, function(v,f){
|
||||
var fat = Gun.on.at.copy(at); fat.field = f; fat.value = v;
|
||||
Gun.obj.del(fat, 'at'); // TODO: CLEAN THIS UP! It would be nice in every other function every where else it didn't matter whether there was a cascading at.at.at.at or not, just and only whether the current context as a field or should rely on a previous field. But maybe that is the gotcha right there?
|
||||
fat.change = fat.change || xtc.change;
|
||||
if(v = Gun.is.rel(fat.value)){ fat = {soul: v, at: fat} }
|
||||
gun._.at('path:' + f).emit(fat).chain(opt.chain);
|
||||
});
|
||||
}
|
||||
if(!ctx.end && ctx.by.end){
|
||||
ctx.end = gun._.at('end').emit(at).chain(opt.chain);
|
||||
}
|
||||
},99);
|
||||
return function(path, cb, opt){
|
||||
opt = opt || {};
|
||||
cb = cb || function(){}; cb.hash = {};
|
||||
cb = cb || (function(){ var cb = function(){}; cb.no = true; return cb }()); cb.hash = {};
|
||||
var gun = this, chain = gun.chain(), 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
|
||||
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.
|
||||
if(gun === gun.back){
|
||||
cb.call(chain, {err: Gun.log('You have no context to `.path`', path, '!')});
|
||||
cb.call(chain, opt.put? null : {err: Gun.log('You have no context to `.path`', path, '!')});
|
||||
return chain;
|
||||
}
|
||||
gun._.at('path:' + path[0]).event(function(at){
|
||||
console.log("path", path, opt.stun);
|
||||
if(opt.once || opt.stun){ this.off() }
|
||||
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 on = Gun.obj.as(cb.hash, at.hash, {off: function(){}});
|
||||
if(at.soul === on.soul){ return }
|
||||
else { on.off() }
|
||||
if(ctx.rel = (Gun.is.rel(at.value) || Gun.is.rel(at.at && at.at.value))){
|
||||
var get = function(err, node){ if(err || 1 === path.length){ cb.call(this, err, node? node : u, field) } };
|
||||
ctx.opt = {opt: opt, chain: opt.chain || chain, path: {soul: (at.at && at.at.soul) || at.soul, stun: opt.stun, field: field}};
|
||||
gun.__.gun.get(ctx.rel || at.soul, get, ctx.opt);
|
||||
if(opt.put && 1 === path.length){
|
||||
return cb.call(ctx.by.chain || chain, null, Gun.is.node.soul.ify({}, ctx.rel));
|
||||
}
|
||||
var get = function(err, node){
|
||||
if(!err && 1 !== path.length){ return }
|
||||
cb.call(this, err, node, field);
|
||||
};
|
||||
ctx.opt = {chain: opt.chain || chain, put: opt.put, path: {soul: (at.at && at.at.soul) || at.soul, field: field }};
|
||||
gun.__.gun.get(ctx.rel || at.soul, cb.no? null : get, ctx.opt);
|
||||
(opt.on = cb.hash[at.hash] = on = ctx.opt.on).soul = at.soul; // TODO: BUG! CB getting reused as the hash point for multiple paths potentially! Could cause problems!
|
||||
return;
|
||||
}
|
||||
@ -835,6 +832,10 @@
|
||||
});
|
||||
gun._.at('null').only(function(at){
|
||||
if(!at.field){ return }
|
||||
if(at.not){
|
||||
gun.put({}, null, {init: true});
|
||||
if(opt.init || gun.__.opt.init){ return }
|
||||
}
|
||||
(at = Gun.on.at.copy(at)).field = path[0];
|
||||
at.not = true;
|
||||
chain._.at('null').emit(at).chain(opt.chain);
|
||||
@ -887,7 +888,7 @@
|
||||
Gun.on('operating').event(function(gun, at, end){
|
||||
if(!Gun.obj.empty(at.change, Gun._.meta)){ return }
|
||||
(end = gun.__.by(at.soul)).end = (end.end || 0) + 1;
|
||||
});
|
||||
},-999);
|
||||
return function(cb, opt){
|
||||
var gun = this, args = Gun.list.slit.call(arguments);
|
||||
cb = Gun.fns.is(cb)? cb : function(val, field){ root.console.log.apply(root.console, args.concat([field && (field += ':'), val])) }; cb.hash = {};
|
||||
@ -898,7 +899,7 @@
|
||||
if(at.field && Gun.obj.has(node, at.field)){
|
||||
return cb.hash[hash] = true, cb.call(ctx.by.chain || gun, Gun.obj.copy(node[at.field]), at.field);
|
||||
}
|
||||
if(!opt.empty && Gun.obj.empty(node, Gun._.meta)){ return } // TODO: CLEAN THIS UP? .on already does this without the .raw!
|
||||
if(!opt.empty && Gun.obj.empty(node, Gun._.meta)){ return } // TODO: CLEAN UP! .on already does this without the .raw!
|
||||
if(!ctx.by.end){ return }
|
||||
return cb.hash[hash] = true, cb.call(ctx.by.chain || gun, Gun.obj.copy(node), field);
|
||||
}
|
||||
@ -932,13 +933,14 @@
|
||||
}
|
||||
gun._.at.all(not);
|
||||
if(gun === gun.back){ Gun.log('You have no context to `.not`!') }
|
||||
chain._.not = true; // TODO: CLEAN UP! Would be ideal if we could accomplish this in a more elegant way.
|
||||
return chain;
|
||||
}
|
||||
|
||||
Gun.chain.init = function(cb, opt){
|
||||
var gun = this;
|
||||
gun._.at('null').event(function(at){
|
||||
if(!at.not){ return }
|
||||
if(!at.not){ return } // TODO: BUG! This check is synchronous but it could be asynchronous!
|
||||
var ctx = {by: gun.__.by(at.soul)};
|
||||
if(at.field){
|
||||
if(Gun.obj.has(ctx.by.node, at.field)){ return }
|
||||
@ -948,10 +950,10 @@
|
||||
if(at.soul){
|
||||
if(ctx.by.node){ return }
|
||||
var soul = Gun.text.random();
|
||||
gun.__.gun.put(Gun.is.node.soul.ify({}, soul));
|
||||
gun.__.gun.put(Gun.is.node.soul.ify({}, soul, {init: true}));
|
||||
gun.__.gun.key(at.soul, null, soul);
|
||||
}
|
||||
});
|
||||
}, {raw: true});
|
||||
return gun;
|
||||
}
|
||||
|
||||
@ -1162,7 +1164,7 @@
|
||||
tab.peers = function(cb, o){
|
||||
if(Gun.text.is(cb)){ return (o = {})[cb] = {}, o }
|
||||
if(cb && !cb.peers){ setTimeout(function(){
|
||||
if(!cb.local){ console.log("Warning! You have no peers to connect to!") }
|
||||
if(!cb.local){ if(!Gun.log.count('no-peers')){ Gun.log("Warning! You have no peers to connect to!") } }
|
||||
if(!(cb.graph || cb.node)){ cb(null) }
|
||||
},1)}
|
||||
}
|
||||
|
139
test/common.js
139
test/common.js
@ -1054,7 +1054,7 @@ describe('Gun', function(){
|
||||
done(); done.c = 1;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('timeywimey', function(){ return;
|
||||
|
||||
it('kitty', function(done){
|
||||
@ -1236,6 +1236,16 @@ describe('Gun', function(){
|
||||
}
|
||||
});
|
||||
|
||||
it('get key no override', function(done){
|
||||
var gun = Gun();
|
||||
gun.put({cream: 'pie'}).key('cream/pie').get('cream/pie', function(err, node){
|
||||
expect(Gun.is.node.soul(node)).to.be('cream/pie');
|
||||
if(done.c){ done(); } done.c = 1;
|
||||
});
|
||||
gun.get('cream/pie').key('pie/cream');
|
||||
gun.get('pie/cream').put({pie: 'cream'});
|
||||
});
|
||||
|
||||
it('get key', function(done){
|
||||
gun.get('yes/key', function(err, node){
|
||||
expect(err).to.not.be.ok();
|
||||
@ -1427,7 +1437,7 @@ describe('Gun', function(){
|
||||
});
|
||||
});
|
||||
|
||||
it.skip('put node get field', function(done){ // future feature.
|
||||
it('put node get field', function(done){ // future feature.
|
||||
var gun = Gun();
|
||||
gun.put({_:{'#': 'soul/field'}, hi: 'lol', foo: 'bar'});//.key('key/field');
|
||||
gun.get({'#': 'soul/field', '.': 'hi'}, function(err, val){
|
||||
@ -1559,7 +1569,7 @@ describe('Gun', function(){
|
||||
},50);
|
||||
},50);
|
||||
});
|
||||
|
||||
|
||||
it('get path wire shallow swoop', function(done){
|
||||
var gun = Gun();
|
||||
var get = gun.get('slightly/shallow/path/swoop');
|
||||
@ -1597,7 +1607,9 @@ describe('Gun', function(){
|
||||
var get = gun.get('hello/key/iso');
|
||||
var puthi = get.put({hi: 'you'});
|
||||
puthi.on(function(node){
|
||||
if(done.hi){ return }
|
||||
expect(node.hi).to.be('you');
|
||||
done.hi = 1;
|
||||
});
|
||||
setTimeout(function(){
|
||||
var get2 = gun.get('hello/key/iso');
|
||||
@ -1765,7 +1777,7 @@ describe('Gun', function(){
|
||||
done();
|
||||
}, 1);
|
||||
});
|
||||
|
||||
|
||||
it('get path put', function(done){
|
||||
gun.get('hello/world').path('hello').put('World').val(function(val){
|
||||
expect(val).to.be('World');
|
||||
@ -2198,85 +2210,90 @@ describe('Gun', function(){
|
||||
});
|
||||
});
|
||||
|
||||
it.only('path should not slowdown', function(done){
|
||||
it('path should not slowdown', function(done){
|
||||
this.timeout(5000);
|
||||
//this.timeout(60000);
|
||||
|
||||
Gun.log.debug = 100; console.log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
//Gun.log.debug = 100; console.log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
|
||||
var gun = Gun({init: true}).put({
|
||||
history: {}
|
||||
});
|
||||
console.log("---------- setup data done -----------");
|
||||
var prev, diff, max = 25, total = 10, largest = -1, gone = {};
|
||||
//console.log("---------- setup data done -----------");
|
||||
var prev, diff, max = 25, total = 100, largest = -1, gone = {};
|
||||
// TODO: It would be nice if we could change these numbers for different platforms/versions of javascript interpreters so we can squeeze as much out of them.
|
||||
gun.path('history').map(function(time, index){
|
||||
//if(turns != index){ return }
|
||||
diff = Gun.time.is() - time;
|
||||
//expect(gone[index]).to.not.be.ok();
|
||||
diff = Gun.time.is() - time;
|
||||
expect(gone[index]).to.not.be.ok();
|
||||
gone[index] = diff;
|
||||
largest = (largest < diff)? diff : largest;
|
||||
console.log(turns, index, largest, diff);
|
||||
//expect(diff > max).to.not.be.ok();
|
||||
//console.log(turns, index, 'largest', largest, diff);
|
||||
expect(diff > max).to.not.be.ok();
|
||||
});
|
||||
//var p = gun.path('history');
|
||||
console.log("-------- map set up -----------");
|
||||
//console.log("-------- map set up -----------");
|
||||
var turns = 0;
|
||||
var many = setInterval(function(){
|
||||
if(turns > total || (diff || 0) > (max + 5)){
|
||||
return;
|
||||
clearTimeout(many);
|
||||
expect(diff).to.be.ok();
|
||||
clearTimeout(many);
|
||||
expect(Gun.num.is(diff)).to.be.ok();
|
||||
if(done.c){ return } done(); done.c = 1;
|
||||
//console.log(turns, largest);
|
||||
return;
|
||||
}
|
||||
//if(turns === 233){ Gun.log.debug = 1; console.log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~") }
|
||||
prev = Gun.time.is();
|
||||
Gun.log.base = Gun.log.ref = Gun.log.fer = prev;
|
||||
var put = {}; put[turns += 1] = prev;
|
||||
//{11: 123456789}
|
||||
console.log("------------------", turns,"---------------------------")
|
||||
if(turns === 9){ Gun.log.debug = 1; console.log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~") }
|
||||
gun.put({history: put});
|
||||
//p.put(put);
|
||||
//gun.path('history').put(put);
|
||||
}, 1);
|
||||
});
|
||||
//return;
|
||||
|
||||
it('path rel should not slowdown', function(done){
|
||||
this.timeout(5000);
|
||||
//this.timeout(60000);
|
||||
|
||||
//Gun.log.debug = 1; console.log("~~~~~ START ~~~~~~");
|
||||
var gun = Gun(gopt).put({
|
||||
history: {}
|
||||
});
|
||||
var prev, diff, max = 100, total = 100;
|
||||
//console.log("-------- DATA SET UP -----------");
|
||||
var prev, diff, max = 100, total = 100, largest = -1, gone = {};
|
||||
gun.path('history').map(function(entry, index){
|
||||
//if(!entry){ return } // TODO: BUG! KNOWN BUG!!!!!!! FIX!!!!!
|
||||
//console.log("WAT", index, entry);
|
||||
//console.log("THE GRAPH\n", gun.__.graph);
|
||||
//expect(gone[index]).to.not.be.ok();
|
||||
gone[index] = diff;
|
||||
diff = Gun.time.is() - (entry.time || prev);
|
||||
//console.log('turn', turns, 'diff', diff);
|
||||
largest = (largest < diff)? diff : largest;
|
||||
//console.log('turn', turns, 'index', index, 'diff', diff, 'largest', largest);
|
||||
expect(diff > max).to.not.be.ok();
|
||||
});
|
||||
|
||||
var turns = 0;
|
||||
|
||||
//console.log("------------ PATH MAP SET UP --------------");
|
||||
var many = setInterval(function(){
|
||||
if(turns > total || diff > (max + 5)){
|
||||
clearTimeout(many);
|
||||
expect(diff).to.be.ok();
|
||||
expect(Gun.num.is(diff)).to.be.ok();
|
||||
if(done.c){ return } done(); done.c = 1;
|
||||
return;
|
||||
}
|
||||
prev = Gun.time.is();
|
||||
Gun.log.base = Gun.log.ref = Gun.log.fer = prev;
|
||||
//console.log("-------------- TEST PUT BEGIN", turns + 1, "-----------------");
|
||||
gun.path(['history', turns += 1]).put({
|
||||
//if(turns === 0){ Gun.log.debug = 1; console.log("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); }
|
||||
//console.log("-------------- ", turns + 1, "-----------------");
|
||||
var val = {
|
||||
x: 1,
|
||||
y: 1,
|
||||
axis: 'y',
|
||||
direction: 1,
|
||||
time: prev
|
||||
});
|
||||
}, 1);
|
||||
}
|
||||
var put = {}; put[turns += 1] = val;
|
||||
gun.put({history: put});
|
||||
//gun.path(['history', turns += 1]).put({
|
||||
},1);
|
||||
});
|
||||
|
||||
it('val path put val', function(done){
|
||||
@ -2469,7 +2486,7 @@ describe('Gun', function(){
|
||||
});
|
||||
|
||||
it('node path node path node path', function(done){
|
||||
var gun = Gun();
|
||||
var gun = Gun(gopt);
|
||||
var data = gun.get('data');
|
||||
gun.put({
|
||||
a: 1,
|
||||
@ -2578,8 +2595,7 @@ describe('Gun', function(){
|
||||
it('implicit put on empty get explicit not', function(done){
|
||||
var gun = Gun().get('init/not').not();
|
||||
gun.on(function(val){
|
||||
expect(val.not).to.be(true);
|
||||
if(done.c){ return } done.c = 1;
|
||||
done.c = 1;
|
||||
});
|
||||
gun.put({not: true});
|
||||
setTimeout(function(){
|
||||
@ -2679,7 +2695,6 @@ describe('Gun', function(){
|
||||
expect(Gun.obj.empty(keynode, Gun._.meta)).to.not.be.ok();
|
||||
});
|
||||
gun.set(1); //.set(2).set(3).set(4); // if you set an object you'd have to do a `.back`
|
||||
Gun.log.debug = 1; console.log("~~~~~~ START ~~~~~~~~");
|
||||
gun.map(function(val, field){
|
||||
//gun.map().val(function(val, field){ // TODO: SEAN! DON'T LET ME FORGET!
|
||||
console.log("\n TEST 2+", field, val);
|
||||
@ -2704,12 +2719,13 @@ describe('Gun', function(){
|
||||
var users = Gun().get('example').path('users');
|
||||
users.path(Gun.text.random()).put('bob');
|
||||
users.path(Gun.text.random()).put('sam');
|
||||
|
||||
users.val(function(v){
|
||||
expect(Gun.is.rel(v)).to.not.be.ok();
|
||||
expect(Object.keys(v).length).to.be(3);
|
||||
done();
|
||||
});
|
||||
setTimeout(function(){
|
||||
users.val(function(v){
|
||||
expect(Gun.is.rel(v)).to.not.be.ok();
|
||||
expect(Object.keys(v).length).to.be(3);
|
||||
done();
|
||||
});
|
||||
},100);
|
||||
});
|
||||
|
||||
it('peer 1 get key, peer 2 put key, peer 1 val', function(done){
|
||||
@ -2847,9 +2863,7 @@ describe('Gun', function(){
|
||||
}); // 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){
|
||||
//console.log("~~~~~~~~ START ~~~~~~~~~"); Gun.log.debug = 1;
|
||||
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){
|
||||
@ -2865,10 +2879,25 @@ describe('Gun', function(){
|
||||
});
|
||||
});
|
||||
|
||||
it("put map", function(done){
|
||||
var gun = Gun();
|
||||
var get = gun.get('map/that');
|
||||
var put = gun.put({a: 1, b: 2, c: 3}).key('map/that');
|
||||
get.map(function(v,f){
|
||||
if(1 === v){ done.a = true }
|
||||
if(2 === v){ done.b = true }
|
||||
if(3 === v){ done.c = true }
|
||||
if(done.a && done.b && done.c){
|
||||
if(done.done){ return }
|
||||
done(); done.done = 1;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("get map map val", function(done){ // Terje's bug
|
||||
var gun = Gun({init: true}); // we can test GUN locally.
|
||||
var passengers = gun.get('passengers/map').not(function(key){
|
||||
this.put({randombob: {
|
||||
gun.put({randombob: {
|
||||
name: "Bob",
|
||||
location: {'lat': '37.6159', 'lng': '-128.5'},
|
||||
direction: '128.2'
|
||||
@ -2970,7 +2999,7 @@ describe('Gun', function(){
|
||||
}, 100);
|
||||
});
|
||||
|
||||
it.skip('gun get put, sub path put, original val', function(done){ // bug from Jesse working on Trace //
|
||||
it('gun get put, sub path put, original val', function(done){ // bug from Jesse working on Trace //
|
||||
var gun = Gun(gopt).get('players');
|
||||
|
||||
gun.put({
|
||||
@ -2987,9 +3016,8 @@ describe('Gun', function(){
|
||||
|
||||
// TODO: BUG! There is a variation of this, where we just do `.val` rather than `gun.val` and `.val` by itself (chained off of the sub-paths) doesn't even get called. :(
|
||||
gun.on(function(players){ // this val is subscribed to the original put and therefore does not get any of the sub-path listeners, therefore it gets called EARLY with the original/old data rather than waiting for the sub-path data to "finish" and then get called.
|
||||
console.log("DEM PLAYERS", players);
|
||||
expect(players.taken).to.be(false);
|
||||
expect(players.history).to.be(null);
|
||||
expect(players.taken).to.be(false);
|
||||
if(done.c){ return } done(); done.c = 1;
|
||||
});
|
||||
});
|
||||
@ -3285,7 +3313,7 @@ describe('Gun', function(){
|
||||
},t || 10);
|
||||
};
|
||||
put({on: 'bus', not: 'transparent'});
|
||||
put({on: null, not: 'torrent'}, 200);return;
|
||||
put({on: null, not: 'torrent'}, 200);
|
||||
put({on: 'sub', not: 'parent'}, 250, true);
|
||||
});
|
||||
|
||||
@ -3459,8 +3487,8 @@ describe('Gun', function(){
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
describe('Streams', function(){ return; // TODO: BUG! UNDO THIS!
|
||||
|
||||
describe('Streams', function(){
|
||||
var gun = Gun(), g = function(){
|
||||
return Gun({wire: {get: ctx.get}});
|
||||
}, ctx = {gen: 9, extra: 100, network: 2};
|
||||
@ -3472,13 +3500,13 @@ describe('Gun', function(){
|
||||
var c = 0;
|
||||
cb = cb || function(){};
|
||||
key = key[Gun._.soul];
|
||||
if('big' !== key){ return cb(null, null) }
|
||||
if('big' !== key){ return cb(null) }
|
||||
setTimeout(function badNetwork(){
|
||||
c += 1;
|
||||
var soul = Gun.is.node.soul(ref);
|
||||
var graph = {};
|
||||
var data = /*graph[soul] = */ {_: {'#': soul, '>': {}}};
|
||||
if(!ref['f' + c]){
|
||||
if(!ref['f' + c]){
|
||||
return cb(null, data), cb(null, {});
|
||||
}
|
||||
data._[Gun._.state]['f' + c] = ref._[Gun._.state]['f' + c];
|
||||
@ -3501,7 +3529,7 @@ describe('Gun', function(){
|
||||
gun.opt({wire: {get: ctx.get}});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('map chain', function(done){
|
||||
var set = gun.put({a: {here: 'you'}, b: {go: 'dear'}, c: {sir: '!'} });
|
||||
set.map().val(function(obj, field){
|
||||
@ -3593,7 +3621,7 @@ describe('Gun', function(){
|
||||
}
|
||||
}, true);
|
||||
});
|
||||
|
||||
|
||||
it('get val', function(done){
|
||||
this.timeout(ctx.gen * ctx.extra);
|
||||
g().get('big').val(function(obj){
|
||||
@ -3603,10 +3631,11 @@ describe('Gun', function(){
|
||||
var raw = Gun.obj.copy(ctx.get.fake);
|
||||
delete raw._;
|
||||
expect(obj).to.be.eql(raw);
|
||||
Gun.log.debug = 0;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('get big map val', function(done){
|
||||
this.timeout(ctx.gen * ctx.extra);
|
||||
var test = {c: 0, seen: {}};
|
||||
|
Loading…
x
Reference in New Issue
Block a user