mirror of
https://github.com/amark/gun.git
synced 2025-03-30 15:08:33 +00:00
0.7 with .val(cb) also hearing .not
This commit is contained in:
parent
9786579eb3
commit
181b6bd767
18
CHANGELOG.md
18
CHANGELOG.md
@ -1,5 +1,23 @@
|
||||
# CHANGELOG
|
||||
|
||||
## 0.7.x
|
||||
|
||||
Small breaking change to `.val(cb)`:
|
||||
|
||||
Previously `.val(cb)` would ONLY be called when data exists, like `.on(cb)`.
|
||||
|
||||
However, due to popular demand, people wanted `.val(cb)` to also get called for `.not(cb)` rather than (before) it would "wait" until data arrived.
|
||||
|
||||
NOTE: For dynamic paths, `.val(cb)` will still wait, like:
|
||||
|
||||
`gun.get('users').map().val(cb)` because the behavior of the `map()` is simply to not fire anything down the chain unless items are found.
|
||||
|
||||
## 0.6.x
|
||||
|
||||
Introduced experimental features, chaining `.val()` (no callback) and `.map(cb)` behaving as a map/reduce function.
|
||||
|
||||
It also upgraded the socket adapters and did end-to-end load testing and correctness testing.
|
||||
|
||||
## 0.5.9
|
||||
|
||||
GUN 0.3 -> 0.4 -> 0.5 Migration Guide:
|
||||
|
177
gun.js
177
gun.js
@ -674,7 +674,7 @@
|
||||
if(!(is = valid(v,f,n, at,env))){ return }
|
||||
if(!f){
|
||||
at.node = at.node || n || {};
|
||||
if(obj_has(v, Node._) && !Gun.is(v)){
|
||||
if(obj_has(v, Node._)){
|
||||
at.node._ = obj_copy(v._);
|
||||
}
|
||||
at.node = Node.soul.ify(at.node, Val.rel.is(at.rel));
|
||||
@ -812,7 +812,7 @@
|
||||
|
||||
Gun.is = function(gun){ return (gun instanceof Gun) }
|
||||
|
||||
Gun.version = 0.6;
|
||||
Gun.version = 0.7;
|
||||
|
||||
Gun.chain = Gun.prototype;
|
||||
Gun.chain.toJSON = function(){};
|
||||
@ -882,6 +882,7 @@
|
||||
function get(at, cat){
|
||||
var soul = at.get[_soul], node = cat.graph[soul], field = at.get[_field], tmp;
|
||||
var next = cat.next || (cat.next = {}), as = /*(at.gun||empty)._ ||*/ (next[soul] || (next[soul] = cat.gun.get(soul)))._;
|
||||
//console.log("GET", soul, field);
|
||||
if(!node){ return }
|
||||
if(field){
|
||||
if(!obj_has(node, field)){ return }
|
||||
@ -964,176 +965,6 @@
|
||||
module.exports = Gun;
|
||||
})(require, './root');
|
||||
|
||||
;require(function(module){
|
||||
return;
|
||||
var Gun = require('./root');
|
||||
var onto = require('./onto');
|
||||
function Chain(back){
|
||||
var at = this._ = {back: back, on: onto, $: this, next: {}};
|
||||
at.root = back? back.root : at;
|
||||
at.on('in', input, at);
|
||||
at.on('out', output, at);
|
||||
}
|
||||
var chain = Chain.prototype;
|
||||
chain.back = function(arg){ var tmp;
|
||||
if(tmp = this._.back){
|
||||
return tmp.$;
|
||||
}
|
||||
}
|
||||
chain.next = function(arg){
|
||||
var at = this._, cat;
|
||||
if(cat = at.next[arg]){
|
||||
return cat.$;
|
||||
}
|
||||
cat = (new Chain(at)._);
|
||||
at.next[arg] = cat;
|
||||
cat.key = arg;
|
||||
return cat.$;
|
||||
}
|
||||
chain.get = function(arg){
|
||||
if(typeof arg == 'string'){
|
||||
var at = this._, cat;
|
||||
if(cat = at.next[arg]){
|
||||
return cat.$;
|
||||
}
|
||||
cat = (this.next(arg)._);
|
||||
if(at.get || at === at.root){
|
||||
cat.get = arg;
|
||||
}
|
||||
return cat.$;
|
||||
} else {
|
||||
var at = this._;
|
||||
var out = {'#': Gun.text.random(), get: {}, cap: 1};
|
||||
var to = at.root.on(out['#'], get, {next: arg})
|
||||
at.on('in', get, to);
|
||||
at.on('out', out);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
function get(env){
|
||||
var as = this.as;
|
||||
if(as.next){
|
||||
as.next(env, this);
|
||||
}
|
||||
}
|
||||
chain.map = function(cb){
|
||||
var at = this._;
|
||||
var chain = new Chain(at);
|
||||
var cat = chain._;
|
||||
var u;
|
||||
at.on('in', function(env){ var tmp;
|
||||
if(!env){ return }
|
||||
var cat = this.as;
|
||||
var to = this.to;
|
||||
if(tmp = env.put){
|
||||
to.next(env);
|
||||
Gun.obj.map(tmp, function(data, key){
|
||||
if('_' == key){ return }
|
||||
if(cb){
|
||||
data = cb(data, key);
|
||||
if(u === data){ return }
|
||||
}
|
||||
cat.on('in', Gun.obj.to(env, {put: data}));
|
||||
});
|
||||
}
|
||||
}, cat);
|
||||
return chain;
|
||||
}
|
||||
function input(env){ var tmp;
|
||||
if(!env){ return }
|
||||
var cat = this.as;
|
||||
var to = this.to;
|
||||
if(tmp = env.put){
|
||||
if(tmp && tmp['#'] && (tmp = Gun.val.rel.is(tmp))){
|
||||
//input.call(this, Gun.obj.to(env, {put: cat.root.put[tmp]}));
|
||||
return;
|
||||
}
|
||||
cat.put = tmp;
|
||||
to.next(env);
|
||||
var next = cat.next;
|
||||
Gun.obj.map(tmp, function(data, key){
|
||||
if(!(key = next[key])){ return }
|
||||
key.on('in', Gun.obj.to(env, {put: data}))
|
||||
});
|
||||
}
|
||||
}
|
||||
function output(env){ var tmp;
|
||||
var u;
|
||||
if(!env){ return }
|
||||
var cat = this.as;
|
||||
var to = this;
|
||||
if(!cat.back){
|
||||
env.test = true;
|
||||
env.gun = cat.root.$;
|
||||
Gun.on('out', env);
|
||||
return;
|
||||
}
|
||||
if(tmp = env.get){
|
||||
if(cat.get){
|
||||
env = Gun.obj.to(env, {get: {'#': cat.get, '.': tmp}});
|
||||
} else
|
||||
if(cat.key){
|
||||
env = Gun.obj.to(env, {get: Gun.obj.put({}, cat.key, tmp)});
|
||||
} else {
|
||||
env = Gun.obj.to(env, {get: {'*': tmp}})
|
||||
}
|
||||
}
|
||||
cat.back.on('out', env);
|
||||
}
|
||||
chain.val = function(cb, opt){
|
||||
var at = this._;
|
||||
if(cb){
|
||||
if(opt){
|
||||
} else {
|
||||
if(at.val){
|
||||
cb(at.put, at.get, at);
|
||||
}
|
||||
}
|
||||
this.get(function(env, ev){
|
||||
cb(env.put, env.get, env);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
var graph = {
|
||||
app: {_:{'#':'app'},
|
||||
foo: {_:{'#':'foo'},
|
||||
bar: {'#': 'asdf'},
|
||||
rab: {'#': 'fdsa'}
|
||||
}/*,
|
||||
oof: {_:{'#':'oof'},
|
||||
bar: {bat: "really"},
|
||||
rab: {bat: "nice!"}
|
||||
}*/
|
||||
},
|
||||
asdf: {_:{'#': 'asdf'}, baz: "hello world!"},
|
||||
fdsa: {_:{'#': 'fdsa'}, baz: "world hello!"}
|
||||
}
|
||||
Gun.on('out', function(env){
|
||||
if(!env.test){ return }
|
||||
setTimeout(function(){
|
||||
console.log("reply", env.get);
|
||||
env.gun._.on('in', {'@': env['#'],
|
||||
put: Gun.graph.node(graph[env.get['#']])
|
||||
});
|
||||
return;
|
||||
env.gun._.on('in', {put: graph, '@': env['#']});
|
||||
},100);
|
||||
});
|
||||
setTimeout(function(){
|
||||
|
||||
//var c = new Chain(), u;
|
||||
//c.get('app').map().map(x => x.bat? {baz: x.bat} : u).get('baz').val(function(data, key, env){
|
||||
// console.log("envelope", env);
|
||||
//});
|
||||
|
||||
},1000);
|
||||
|
||||
})(require, './experiment');
|
||||
|
||||
;require(function(module){
|
||||
var Gun = require('./root');
|
||||
Gun.chain.back = function(n, opt){ var tmp;
|
||||
@ -2113,7 +1944,7 @@
|
||||
function val(at, ev, to){
|
||||
var opt = this.as, cat = opt.cat, gun = at.gun, coat = gun._, data = coat.put || at.put, tmp;
|
||||
if(u === data){
|
||||
return;
|
||||
//return;
|
||||
}
|
||||
if(data && data[rel._] && (tmp = rel.is(data))){
|
||||
tmp = (cat.root.get(tmp)._);
|
||||
|
2
gun.min.js
vendored
2
gun.min.js
vendored
File diff suppressed because one or more lines are too long
@ -3,7 +3,7 @@
|
||||
Gun.serve = require('./serve');
|
||||
require('./nts');
|
||||
require('./s3');
|
||||
try{require('./uws');}catch(e){require('./wsp/server');}
|
||||
try{require('./ws');}catch(e){require('./wsp/server');}
|
||||
require('./file');
|
||||
module.exports = Gun;
|
||||
}());
|
||||
|
118
lib/ws.js
Normal file
118
lib/ws.js
Normal file
@ -0,0 +1,118 @@
|
||||
var Gun = require('../gun');
|
||||
|
||||
var WebSocket = require('ws');
|
||||
|
||||
var url = require('url');
|
||||
|
||||
Gun.on('opt', function mount(at){
|
||||
this.to.next(at);
|
||||
if(at.once){ return }
|
||||
var opt = at.opt.ws || (at.opt.ws = {});
|
||||
var cat = (at.gun.back(-1)._);
|
||||
|
||||
opt.server = opt.server || at.opt.web;
|
||||
opt.path = opt.path || at.opt.path || '/gun';
|
||||
|
||||
opt.web = new WebSocket.Server(opt);
|
||||
var peers = cat.opt.peers;
|
||||
|
||||
opt.web.on('connection', function(ws){
|
||||
ws.upgradeReq = ws.upgradeReq || {};
|
||||
ws.url = url.parse(ws.upgradeReq.url||'', true);
|
||||
ws.id = ws.id || Gun.text.random(6);
|
||||
peers[ws.id] = {wire: ws};
|
||||
ws.on('message', function(msg){
|
||||
//console.log("MESSAGE", msg);
|
||||
receive(msg, ws, cat);
|
||||
});
|
||||
ws.on('close', function(){
|
||||
Gun.obj.del(peers, ws.id);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
var message;
|
||||
|
||||
Gun.on('out', function(at){
|
||||
this.to.next(at);
|
||||
var cat = at.gun._.root._;
|
||||
message = JSON.stringify(at);
|
||||
if(cat.udrain){
|
||||
cat.udrain.push(message);
|
||||
return;
|
||||
}
|
||||
cat.udrain = [];
|
||||
setTimeout(function(){
|
||||
if(!cat.udrain){ return }
|
||||
//if(count += cat.udrain.length){ console.log("msg out:", count) }
|
||||
var tmp = cat.udrain;
|
||||
cat.udrain = null;
|
||||
message = JSON.stringify(tmp);
|
||||
Gun.obj.map(cat.opt.peers, send, cat);
|
||||
},1);
|
||||
Gun.obj.map(cat.opt.peers, send, cat);
|
||||
});
|
||||
|
||||
var count = 0;
|
||||
function receive(msg, wire, cat){
|
||||
if(!cat){ return }
|
||||
try{msg = JSON.parse(msg);
|
||||
}catch(e){}
|
||||
|
||||
if(msg instanceof Array){
|
||||
var i = 0, m; while(m = msg[i++]){
|
||||
receive(m, wire, cat);
|
||||
}
|
||||
return;
|
||||
}
|
||||
//if(++count){ console.log("msg in:", count) }
|
||||
|
||||
//msg.url = wire.url;
|
||||
cat.gun.on('in', msg.body || msg);
|
||||
}
|
||||
|
||||
// EVERY message taken care of. The "extra" ones are from in-memory not having "asked" for it yet - which we won't want it to do for foreign requests. Likewise, lots of chattyness because the put/ack replies happen before the `get` syncs so everybody now has it in-memory already to reply with.
|
||||
function send(peer){
|
||||
var msg = message, cat = this;
|
||||
var wire = peer.wire || open(peer, cat);
|
||||
if(!wire){ return }
|
||||
if(wire.readyState === wire.OPEN){
|
||||
wire.send(msg);
|
||||
return;
|
||||
}
|
||||
(peer.queue = peer.queue || []).push(msg);
|
||||
}
|
||||
|
||||
function open(peer, as){
|
||||
if(!peer || !peer.url){ return }
|
||||
var url = peer.url.replace('http', 'ws');
|
||||
var wire = peer.wire = new WebSocket(url);
|
||||
wire.on('close', function(){
|
||||
reconnect(peer, as);
|
||||
});
|
||||
wire.on('error', function(error){
|
||||
if(!error){ return }
|
||||
if(error.code === 'ECONNREFUSED'){
|
||||
reconnect(peer, as);
|
||||
}
|
||||
});
|
||||
wire.on('open', function(){
|
||||
var queue = peer.queue;
|
||||
peer.queue = [];
|
||||
Gun.obj.map(queue, function(msg){
|
||||
message = msg;
|
||||
send.call(as, peer);
|
||||
});
|
||||
});
|
||||
wire.on('message', function(msg){
|
||||
receive(msg, wire, as);
|
||||
});
|
||||
return wire;
|
||||
}
|
||||
|
||||
function reconnect(peer, as){
|
||||
clearTimeout(peer.defer);
|
||||
peer.defer = setTimeout(function(){
|
||||
open(peer, as);
|
||||
}, 2 * 1000);
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gun",
|
||||
"version": "0.6.9",
|
||||
"version": "0.7.0",
|
||||
"description": "Graph engine",
|
||||
"main": "index.js",
|
||||
"browser": "gun.min.js",
|
||||
@ -49,10 +49,10 @@
|
||||
"dependencies": {
|
||||
"aws-sdk": "~>2.15.0",
|
||||
"formidable": "~>1.0.15",
|
||||
"uws": "~>0.14.1",
|
||||
"ws": "~>2.2.1 "
|
||||
"ws": "~>2.2.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"uws": "~>0.14.1",
|
||||
"express": "~>4.13.4",
|
||||
"hapi": "^16.1.0",
|
||||
"inert": "^4.1.0",
|
||||
|
@ -1,169 +0,0 @@
|
||||
|
||||
return;
|
||||
var Gun = require('./root');
|
||||
var onto = require('./onto');
|
||||
function Chain(back){
|
||||
var at = this._ = {back: back, on: onto, $: this, next: {}};
|
||||
at.root = back? back.root : at;
|
||||
at.on('in', input, at);
|
||||
at.on('out', output, at);
|
||||
}
|
||||
var chain = Chain.prototype;
|
||||
chain.back = function(arg){ var tmp;
|
||||
if(tmp = this._.back){
|
||||
return tmp.$;
|
||||
}
|
||||
}
|
||||
chain.next = function(arg){
|
||||
var at = this._, cat;
|
||||
if(cat = at.next[arg]){
|
||||
return cat.$;
|
||||
}
|
||||
cat = (new Chain(at)._);
|
||||
at.next[arg] = cat;
|
||||
cat.key = arg;
|
||||
return cat.$;
|
||||
}
|
||||
chain.get = function(arg){
|
||||
if(typeof arg == 'string'){
|
||||
var at = this._, cat;
|
||||
if(cat = at.next[arg]){
|
||||
return cat.$;
|
||||
}
|
||||
cat = (this.next(arg)._);
|
||||
if(at.get || at === at.root){
|
||||
cat.get = arg;
|
||||
}
|
||||
return cat.$;
|
||||
} else {
|
||||
var at = this._;
|
||||
var out = {'#': Gun.text.random(), get: {}, cap: 1};
|
||||
var to = at.root.on(out['#'], get, {next: arg})
|
||||
at.on('in', get, to);
|
||||
at.on('out', out);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
function get(env){
|
||||
var as = this.as;
|
||||
if(as.next){
|
||||
as.next(env, this);
|
||||
}
|
||||
}
|
||||
chain.map = function(cb){
|
||||
var at = this._;
|
||||
var chain = new Chain(at);
|
||||
var cat = chain._;
|
||||
var u;
|
||||
at.on('in', function(env){ var tmp;
|
||||
if(!env){ return }
|
||||
var cat = this.as;
|
||||
var to = this.to;
|
||||
if(tmp = env.put){
|
||||
to.next(env);
|
||||
Gun.obj.map(tmp, function(data, key){
|
||||
if('_' == key){ return }
|
||||
if(cb){
|
||||
data = cb(data, key);
|
||||
if(u === data){ return }
|
||||
}
|
||||
cat.on('in', Gun.obj.to(env, {put: data}));
|
||||
});
|
||||
}
|
||||
}, cat);
|
||||
return chain;
|
||||
}
|
||||
function input(env){ var tmp;
|
||||
if(!env){ return }
|
||||
var cat = this.as;
|
||||
var to = this.to;
|
||||
if(tmp = env.put){
|
||||
if(tmp && tmp['#'] && (tmp = Gun.val.rel.is(tmp))){
|
||||
//input.call(this, Gun.obj.to(env, {put: cat.root.put[tmp]}));
|
||||
return;
|
||||
}
|
||||
cat.put = tmp;
|
||||
to.next(env);
|
||||
var next = cat.next;
|
||||
Gun.obj.map(tmp, function(data, key){
|
||||
if(!(key = next[key])){ return }
|
||||
key.on('in', Gun.obj.to(env, {put: data}))
|
||||
});
|
||||
}
|
||||
}
|
||||
function output(env){ var tmp;
|
||||
var u;
|
||||
if(!env){ return }
|
||||
var cat = this.as;
|
||||
var to = this;
|
||||
if(!cat.back){
|
||||
env.test = true;
|
||||
env.gun = cat.root.$;
|
||||
Gun.on('out', env);
|
||||
return;
|
||||
}
|
||||
if(tmp = env.get){
|
||||
if(cat.get){
|
||||
env = Gun.obj.to(env, {get: {'#': cat.get, '.': tmp}});
|
||||
} else
|
||||
if(cat.key){
|
||||
env = Gun.obj.to(env, {get: Gun.obj.put({}, cat.key, tmp)});
|
||||
} else {
|
||||
env = Gun.obj.to(env, {get: {'*': tmp}})
|
||||
}
|
||||
}
|
||||
cat.back.on('out', env);
|
||||
}
|
||||
chain.val = function(cb, opt){
|
||||
var at = this._;
|
||||
if(cb){
|
||||
if(opt){
|
||||
} else {
|
||||
if(at.val){
|
||||
cb(at.put, at.get, at);
|
||||
}
|
||||
}
|
||||
this.get(function(env, ev){
|
||||
cb(env.put, env.get, env);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
var graph = {
|
||||
app: {_:{'#':'app'},
|
||||
foo: {_:{'#':'foo'},
|
||||
bar: {'#': 'asdf'},
|
||||
rab: {'#': 'fdsa'}
|
||||
}/*,
|
||||
oof: {_:{'#':'oof'},
|
||||
bar: {bat: "really"},
|
||||
rab: {bat: "nice!"}
|
||||
}*/
|
||||
},
|
||||
asdf: {_:{'#': 'asdf'}, baz: "hello world!"},
|
||||
fdsa: {_:{'#': 'fdsa'}, baz: "world hello!"}
|
||||
}
|
||||
Gun.on('out', function(env){
|
||||
if(!env.test){ return }
|
||||
setTimeout(function(){
|
||||
console.log("reply", env.get);
|
||||
env.gun._.on('in', {'@': env['#'],
|
||||
put: Gun.graph.node(graph[env.get['#']])
|
||||
});
|
||||
return;
|
||||
env.gun._.on('in', {put: graph, '@': env['#']});
|
||||
},100);
|
||||
});
|
||||
setTimeout(function(){
|
||||
|
||||
//var c = new Chain(), u;
|
||||
//c.get('app').map().map(x => x.bat? {baz: x.bat} : u).get('baz').val(function(data, key, env){
|
||||
// console.log("envelope", env);
|
||||
//});
|
||||
|
||||
},1000);
|
||||
|
||||
|
@ -58,7 +58,7 @@ var Graph = {};
|
||||
if(!(is = valid(v,f,n, at,env))){ return }
|
||||
if(!f){
|
||||
at.node = at.node || n || {};
|
||||
if(obj_has(v, Node._) && !Gun.is(v)){
|
||||
if(obj_has(v, Node._)){
|
||||
at.node._ = obj_copy(v._);
|
||||
}
|
||||
at.node = Node.soul.ify(at.node, Val.rel.is(at.rel));
|
||||
|
@ -77,7 +77,7 @@ Gun.chain.val = function(cb, opt){
|
||||
function val(at, ev, to){
|
||||
var opt = this.as, cat = opt.cat, gun = at.gun, coat = gun._, data = coat.put || at.put, tmp;
|
||||
if(u === data){
|
||||
return;
|
||||
//return;
|
||||
}
|
||||
if(data && data[rel._] && (tmp = rel.is(data))){
|
||||
tmp = (cat.root.get(tmp)._);
|
||||
|
@ -8,7 +8,7 @@ function Gun(o){
|
||||
|
||||
Gun.is = function(gun){ return (gun instanceof Gun) }
|
||||
|
||||
Gun.version = 0.6;
|
||||
Gun.version = 0.7;
|
||||
|
||||
Gun.chain = Gun.prototype;
|
||||
Gun.chain.toJSON = function(){};
|
||||
@ -78,6 +78,7 @@ Gun._ = { // some reserved key words, these are not the only ones.
|
||||
function get(at, cat){
|
||||
var soul = at.get[_soul], node = cat.graph[soul], field = at.get[_field], tmp;
|
||||
var next = cat.next || (cat.next = {}), as = /*(at.gun||empty)._ ||*/ (next[soul] || (next[soul] = cat.gun.get(soul)))._;
|
||||
//console.log("GET", soul, field);
|
||||
if(!node){ return }
|
||||
if(field){
|
||||
if(!obj_has(node, field)){ return }
|
||||
|
@ -3500,6 +3500,32 @@ describe('Gun', function(){
|
||||
},1700);
|
||||
});
|
||||
});
|
||||
|
||||
it('val should now get called if no data is found', function(done){
|
||||
var gun = Gun();
|
||||
|
||||
gun.get('nv/foo').get('bar').get('baz').val(function(val, key){
|
||||
//console.log('*******', key, val);
|
||||
expect(val).to.be(undefined);
|
||||
done.fbb = true;
|
||||
});
|
||||
|
||||
gun.get('nv/totesnothing').val(function(val, key){
|
||||
//console.log('***********', key, val);
|
||||
expect(val).to.be(undefined);
|
||||
done.t = true;
|
||||
});
|
||||
|
||||
gun.get('nv/bz').get('lul').val(function(val, key){
|
||||
//console.log('*****************', key, val);
|
||||
expect(val).to.be(undefined);
|
||||
done.bzl = true;
|
||||
if(done.fbb && done.t && done.bzl){
|
||||
if(done.c){ return } done.c = 1;
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
return;
|
||||
it.only('Custom extensions are chainable', function(done){
|
||||
Gun.chain.filter = function(filter){
|
||||
|
Loading…
x
Reference in New Issue
Block a user