From 9b752c3937ba3a9d2ec417fb06f6cdb6edd344ca Mon Sep 17 00:00:00 2001 From: Mark Nadal Date: Fri, 21 Apr 2017 15:42:39 -0700 Subject: [PATCH] clarify root more for SEA, lots more to go --- gun.js | 374 ++++++++++++++--------------------- gun.min.js | 2 +- lib/file.js | 7 +- package.json | 2 +- src/HAM.js | 8 +- src/adapters/localStorage.js | 8 +- src/chain.js | 49 +++-- src/graph.js | 4 +- src/index.js | 16 +- src/key.js | 166 ---------------- src/node.js | 3 +- src/not.js | 1 + src/path.js | 1 + src/put.js | 8 +- src/root.js | 90 ++++++--- src/state.js | 17 +- test/common.js | 27 ++- 17 files changed, 317 insertions(+), 466 deletions(-) delete mode 100644 src/key.js diff --git a/gun.js b/gun.js index 997a21cbc..53137704d 100644 --- a/gun.js +++ b/gun.js @@ -406,7 +406,9 @@ } if(incomingState === currentState){ - if(Lexical(incomingValue) === Lexical(currentValue)){ // Note: while these are practically the same, the deltas could be technically different + incomingValue = Lexical(incomingValue) || ""; + currentValue = Lexical(currentValue) || ""; + if(incomingValue === currentValue){ // Note: while these are practically the same, the deltas could be technically different return {state: true}; } /* @@ -417,10 +419,10 @@ because convergence (data integrity) is generally more important. Any difference in this algorithm must be given a new and different name. */ - if(Lexical(incomingValue) < Lexical(currentValue)){ // Lexical only works on simple value types! + if(incomingValue < currentValue){ // Lexical only works on simple value types! return {converge: true, current: true}; } - if(Lexical(currentValue) < Lexical(incomingValue)){ // Lexical only works on simple value types! + if(currentValue < incomingValue){ // Lexical only works on simple value types! return {converge: true, incoming: true}; } } @@ -492,6 +494,7 @@ n._[soul_] = o.soul || n._[soul_] || text_random(); // put the soul on it. return n; } + Node.soul._ = Val.rel._; ;(function(){ Node.is = function(n, cb, as){ var s; // checks to see if an object is a valid node. if(!obj_is(n)){ return false } // must be an object. @@ -533,7 +536,7 @@ }()); var obj = Type.obj, obj_is = obj.is, obj_del = obj.del, obj_map = obj.map; var text = Type.text, text_random = text.random; - var soul_ = Val.rel._; + var soul_ = Node.soul._; var u; module.exports = Node; })(require, './node'); @@ -557,6 +560,11 @@ var perf = (typeof performance !== 'undefined')? (performance.timing && performance) : false, start = (perf && perf.timing && perf.timing.navigationStart) || (perf = false); State._ = '>'; State.drift = 0; + State.is = function(n, f, o){ // convenience function to get the state on a field on a node and return it. + var tmp = (f && n && n[N_] && n[N_][State._]) || o; + if(!tmp){ return } + return num_is(tmp = tmp[f])? tmp : -Infinity; + } State.ify = function(n, f, s, v, soul){ // put a field's state on a node. if(!n || !n[N_]){ // reject if it is not node-like. if(!soul){ // unless they passed a soul @@ -575,10 +583,12 @@ } return n; } - State.is = function(n, f, o){ // convenience function to get the state on a field on a node and return it. - var tmp = (f && n && n[N_] && n[N_][State._]) || o; - if(!tmp){ return } - return num_is(tmp[f])? tmp[f] : -Infinity; + State.to = function(from, f, to){ + var val = from[f]; + if(obj_is(val)){ + val = obj_copy(val); + } + return State.ify(to, f, State.is(from, f), val, Node.soul(from)); } ;(function(){ State.map = function(cb, s, as){ var u; // for use with Node.ify @@ -607,7 +617,7 @@ State.ify(this.o, f, this.s) ; } }()); - var obj = Type.obj, obj_as = obj.as, obj_has = obj.has, obj_is = obj.is, obj_map = obj.map; + var obj = Type.obj, obj_as = obj.as, obj_has = obj.has, obj_is = obj.is, obj_map = obj.map, obj_copy = obj.copy; var num = Type.num, num_is = num.is; var fn = Type.fn, fn_is = fn.is; var N_ = Node._, u; @@ -624,8 +634,8 @@ if(!g || !obj_is(g) || obj_empty(g)){ return false } // must be an object. return !obj_map(g, map, {cb:cb,fn:fn,as:as}); // makes sure it wasn't an empty object. } - function map(n, s){ // we invert this because the way we check for this is via a negation. - if(!n || s !== Node.soul(n) || !Node.is(n, this.fn)){ return true } // it is true that this is an invalid graph. + function map(n, s){ // we invert this because the way'? we check for this is via a negation. + if(!n || s !== Node.soul(n) || !Node.is(n, this.fn, this.as)){ return true } // it is true that this is an invalid graph. if(!this.cb){ return } nf.n = n; nf.as = this.as; // sequential race conditions aren't races. this.cb.call(nf.as, n, s, nf); @@ -855,39 +865,84 @@ //console.log("add to.next(at)"); // TODO: BUG!!! var ev = this, cat = ev.as, coat; if(!at.gun){ at.gun = cat.gun } - if(!at['#'] && at['@']){ - at['#'] = Gun.text.random(); // TODO: Use what is used other places instead. - // TODO: BUG! For multi-instances, the "ack" system is globally shared, but it shouldn't be. + if(!at['#']){ at['#'] = Gun.text.random() } // TODO: Use what is used other places instead. + if(cat.dup.check(at['#'])){ return } + if(at['@']){ + // TODO: BUG! For multi-instances, the "ack" system is globally shared, but it shouldn't be. if(cat.ack(at['@'], at)){ return } // TODO: Consider not returning here, maybe, where this would let the "handshake" on sync occur for Holy Grail? cat.dup.track(at['#']); Gun.on('out', obj_to(at, {gun: cat.gun})); return; } - if(at['#'] && cat.dup.check(at['#'])){ return } cat.dup.track(at['#']); - if(cat.ack(at['@'], at)){ return } + //if(cat.ack(at['@'], at)){ return } //cat.ack(at['@'], at); coat = obj_to(at, {gun: cat.gun}); if(at.get){ - if(!get(at, cat)){ - Gun.on('get', coat); - } + //Gun.on.GET(coat); + Gun.on('get', coat); } if(at.put){ - Gun.HAM.synth(at, ev, cat.gun); // TODO: Clean up, just make it part of on('put')! + //Gun.on.PUT(coat); Gun.on('put', coat); } Gun.on('out', coat); } - 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 } + }()); + + ;(function(){ + Gun.on('put', function(at){ + //Gun.on.PUT = function(at){ + if(!at['#']){ return this.to.next(at) } // for tests. + var ev = this, ctx = {gun: at.gun, graph: at.gun._.graph, put: {}, at: {}, machine: Gun.state()}; + if(!Gun.graph.is(at.put, null, verify, ctx)){ ctx.err = "Error: Invalid graph!" } + if(ctx.err){ return ctx.gun.on('in', {'@': at['#'], err: Gun.log(ctx.err) }) } + obj_map(ctx.put, merge, ctx); + obj_map(ctx.at, map, ctx); + if(!ctx.diff){ return } + ev.to.next(obj_to(at, {put: ctx.diff})); + }); + function verify(val, key, node, soul){ var ctx = this; + var state = Gun.state.is(node, key), tmp; + if(!state){ return ctx.err = "Error: No state on '"+key+"' in node '"+soul+"'!" } + var vertex = ctx.graph[soul] || empty, was = Gun.state.is(vertex, key, true), known = vertex[key]; + var HAM = Gun.HAM(ctx.machine, state, was, val, known); + if(!HAM.incoming){ return } + ctx.put[soul] = Gun.state.to(node, key, ctx.put[soul]); + (ctx.diff || (ctx.diff = {}))[soul] = Gun.state.to(node, key, ctx.diff[soul]); // TODO: Bug? If val is a relation, it is an object and therefore passed by reference. Will this be a problem? + } + function merge(node, soul){ + var ref = ((this.gun._).next || empty)[soul]; + if(!ref){ return } + var at = this.at[soul] = { + put: this.node = node, + get: this.soul = soul, + gun: this.ref = ref + }; + obj_map(node, each, this); + Gun.on('node', at); + } + function each(val, key){ + var graph = this.graph, soul = this.soul, cat = (this.ref._), tmp; + graph[soul] = Gun.state.to(this.node, key, graph[soul]); + (cat.put || (cat.put = {}))[key] = val; + } + function map(at, soul){ + if(!at.gun){ return } + (at.gun._).on('in', at); + } + }()); + var tmpev = {to:{next:function(){}}}; // temporary while we have to switch event hooks. + ;(function(){ + Gun.on('get', function(at){ + var ev = this, soul = at.get[_soul], cat = at.gun._, node = cat.graph[soul], field = at.get[_field], tmp; + var next = cat.next || (cat.next = {}), as = ((next[soul] || empty)._); + if(!node || !as){ return ev.to.next(at) } if(field){ - if(!obj_has(node, field)){ return } - tmp = Gun.obj.put(Gun.node.soul.ify({}, soul), field, node[field]); - node = Gun.state.ify(tmp, field, Gun.state.is(node, field)); + if(!obj_has(node, field)){ return ev.to.next(at) } + node = Gun.state.to(node, field); + } else { + node = Gun.obj.copy(node); } //if(at.gun === cat.gun){ node = Gun.graph.node(node); // TODO: BUG! Clone node? @@ -902,9 +957,10 @@ gun: as.gun }); if(0 < tmp){ - return true; + return; } - } + ev.to.next(at); + }); }()); ;(function(){ @@ -947,9 +1003,9 @@ var text_is = Gun.text.is; var list_is = Gun.list.is; - var obj = Gun.obj, obj_is = obj.is, obj_has = obj.has, obj_to = obj.to, obj_map = obj.map; - var _soul = Gun._.soul, _field = Gun._.field; - //var u; + var obj = Gun.obj, obj_is = obj.is, obj_has = obj.has, obj_to = obj.to, obj_map = obj.map, obj_copy = obj.copy; + var _soul = Gun._.soul, _field = Gun._.field, rel_is = Gun.val.rel.is; + var empty = {}, u; console.debug = function(i, s){ return (console.debug.i && i === console.debug.i && console.debug.i++) && (console.log.apply(console, arguments) || s) }; @@ -1021,13 +1077,24 @@ at.gun = gun; } if(get = at.get){ - if(!get[_soul]){ + if(tmp = get[_soul]){ + tmp = (root.get(tmp)._); + if(obj_has(get, _field)){ + if(obj_has(put = tmp.put, get = get[_field])){ + tmp.on('in', {get: tmp.get, put: Gun.state.to(put, get), gun: tmp.gun}); // TODO: Ugly, clean up? Simplify all these if conditions (without ruining the whole chaining API)? + } + } else + if(obj_has(tmp, 'put')){ + //if(u !== tmp.put){ + tmp.on('in', tmp); + } + } else { if(obj_has(get, _field)){ get = get[_field]; var next = get? (gun.get(get)._) : cat; // TODO: BUG! Handle plural chains by iterating over them. - if(obj_has(next, 'put')){ // potentially incorrect? Maybe? - //if(u !== next.put){ // potentially incorrect? Maybe? + //if(obj_has(next, 'put')){ // potentially incorrect? Maybe? + if(u !== next.put){ // potentially incorrect? Maybe? //next.tag['in'].last.next(next); next.on('in', next); return; @@ -1041,8 +1108,8 @@ if(rel = Gun.val.rel.is(val)){ if(!at.gun._){ return } (at.gun._).on('out', { - get: {'#': rel, '.': get}, - '#': root._.ask(Gun.HAM.synth, at.gun), + get: tmp = {'#': rel, '.': get, gun: at.gun}, + '#': root._.ask(Gun.HAM.synth, tmp), gun: at.gun }); return; @@ -1060,12 +1127,12 @@ obj_map(cat.map, function(proxy){ proxy.at.on('in', proxy.at); }); - } + }; if(cat.soul){ if(!at.gun._){ return } (at.gun._).on('out', { - get: {'#': cat.soul, '.': get}, - '#': root._.ask(Gun.HAM.synth, at.gun), + get: tmp = {'#': cat.soul, '.': get, gun: at.gun}, + '#': root._.ask(Gun.HAM.synth, tmp), gun: at.gun }); return; @@ -1091,14 +1158,15 @@ } if(cat.ack){ if(!obj_has(cat, 'put')){ // u !== cat.put instead? + //if(u !== cat.put){ return; } } cat.ack = -1; if(cat.soul){ cat.on('out', { - get: {'#': cat.soul}, - '#': root._.ask(Gun.HAM.synth, cat.gun), + get: tmp = {'#': cat.soul, gun: cat.gun}, + '#': root._.ask(Gun.HAM.synth, tmp), gun: cat.gun }); return; @@ -1119,7 +1187,7 @@ function input(at){ at = at._ || at; var ev = this, cat = this.as, gun = at.gun, coat = gun._, change = at.put, back = cat.back._ || empty, rel, tmp; - if(0 > cat.ack && !Gun.val.rel.is(change)){ // for better behavior? + if(0 > cat.ack && !at.ack && !Gun.val.rel.is(change)){ // for better behavior? cat.ack = 1; } if(cat.get && at.get !== cat.get){ @@ -1195,9 +1263,8 @@ not(cat, at); } tmp = (cat.map || (cat.map = {}))[coat.id] = cat.map[coat.id] || {at: coat}; - if(rel !== tmp.rel){ - ask(cat, tmp.rel = rel); - } + if(rel === tmp.rel){ return } + ask(cat, tmp.rel = rel); } function echo(cat, at, ev){ if(!cat.echo){ return } // || node_ === at.get ???? @@ -1260,17 +1327,15 @@ if(cat.ack){ tmp.ack = tmp.ack || -1; tmp.on('out', { - get: {'#': soul}, - '#': cat.root._.ask(Gun.HAM.synth, tmp.gun), - gun: tmp.gun + get: tmp = {'#': soul, gun: tmp.gun}, + '#': cat.root._.ask(Gun.HAM.synth, tmp) }); return; } obj_map(cat.next, function(gun, key){ (gun._).on('out', { - get: {'#': soul, '.': key}, - '#': cat.root._.ask(Gun.HAM.synth, tmp.gun), - gun: gun + get: gun = {'#': soul, '.': key, gun: gun}, + '#': cat.root._.ask(Gun.HAM.synth, gun) }); }); } @@ -1433,7 +1498,9 @@ ref = ref.get(path[i]); } if(as.not || Gun.node.soul(at.obj)){ - at.soul(Gun.node.soul(at.obj) || ((as.opt||{}).uuid || as.gun.back('opt.uuid') || Gun.text.random)()); + var id = Gun.node.soul(at.obj) || ((as.opt||{}).uuid || as.gun.back('opt.uuid') || Gun.text.random)(); + ref.back(-1).get(id); + at.soul(id); return; } (as.stun = as.stun || {})[path] = true; @@ -1446,7 +1513,9 @@ if(!at.gun || !at.gun._.back){ return } // TODO: Handle ev.off(); at = (at.gun._.back._); - cat.soul(Gun.node.soul(cat.obj) || Gun.node.soul(at.put) || Gun.val.rel.is(at.put) || ((as.opt||{}).uuid || as.gun.back('opt.uuid') || Gun.text.random)()); // TODO: BUG!? Do we really want the soul of the object given to us? Could that be dangerous? + var id = Gun.node.soul(cat.obj) || Gun.node.soul(at.put) || Gun.val.rel.is(at.put) || ((as.opt||{}).uuid || as.gun.back('opt.uuid') || Gun.text.random)(); // TODO: BUG!? Do we really want the soul of the object given to us? Could that be dangerous? + at.gun.back(-1).get(id); + cat.soul(id); as.stun[cat.path] = false; as.batch(); } @@ -1599,7 +1668,21 @@ state_ify(delta, field, is); } } - Gun.HAM.synth = function(at, ev, as){ var gun = this.as || as; + Gun.HAM.synth = function(at, ev){ + var as = this.as, cat = as.gun._; + if(!at.put || (as['.'] && !obj_has(at.put[as['#']], cat.get))){ + if(cat.put !== u){ return } + cat.on('in', { + get: cat.get, + put: cat.put = u, + gun: cat.gun, + }) + return; + } + at.gun = cat.root; + Gun.on('put', at); + } + Gun.HAM.synth_ = function(at, ev, as){ var gun = this.as || as; var cat = gun._, root = cat.root._, put = {}, tmp; if(!at.put){ //if(obj_has(cat, 'put')){ return } @@ -1660,178 +1743,12 @@ module.exports = Gun; })(require, './core'); - ;require(function(module){ - var Gun = require('./core'); - var obj = Gun.obj, obj_is = obj.is, obj_put = obj.put, obj_map = obj.map, obj_empty = obj.empty; - var num = Gun.num, num_is = num.is; - var _soul = Gun.val.rel._, _field = '.'; - - - ;(function(){ - Gun.chain.key = function(index, cb, opt){ - if(!index){ - if(cb){ - cb.call(this, {err: Gun.log('No key!')}); - } - return this; - } - var gun = this; - if(typeof opt === 'string'){ - console.log("Please report this as an issue! key.opt.string"); - return gun; - } - if(gun === gun._.root){if(cb){cb({err: Gun.log("Can't do that on root instance.")})};return gun} - opt = opt || {}; - opt.key = index; - opt.any = cb || function(){}; - opt.ref = gun.back(-1).get(opt.key); - opt.gun = opt.gun || gun; - gun.on(key, {as: opt}); - if(!opt.data){ - opt.res = Gun.on.stun(opt.ref); - } - return gun; - } - function key(at, ev){ var opt = this; - ev.off(); - opt.soul = Gun.node.soul(at.put); - if(!opt.soul || opt.key === opt.soul){ return opt.data = {} } - opt.data = obj_put({}, keyed._, Gun.node.ify(obj_put({}, opt.soul, Gun.val.rel.ify(opt.soul)), '#'+opt.key+'#')); - (opt.res||iffe)(function(){ - opt.ref.put(opt.data, opt.any, {soul: opt.key, key: opt.key}); - },opt); - if(opt.res){ - opt.res(); - } - } - function iffe(fn,as){fn.call(as||{})} - function keyed(f){ - if(!f || !('#' === f[0] && '#' === f[f.length-1])){ return } - var s = f.slice(1,-1); - if(!s){ return } - return s; - } - keyed._ = '##'; - Gun.on('next', function(at){ - var gun = at.gun; - if(gun.back(-1) !== at.back){ return } - gun.on('in', pseudo, gun._); - gun.on('out', normalize, gun._); - }); - function normalize(at){ var cat = this; - if(!at.put){ - if(at.get){ - search.call(at.gun? at.gun._ : cat, at); - } - return; - } - if(at.opt && at.opt.key){ return } - var put = at.put, graph = cat.gun.back(-1)._.graph; - Gun.graph.is(put, function(node, soul){ - if(!Gun.node.is(graph['#'+soul+'#'], function each(rel,id){ - if(id !== Gun.val.rel.is(rel)){ return } - if(rel = graph['#'+id+'#']){ - Gun.node.is(rel, each); // correct params? - return; - } - Gun.node.soul.ify(rel = put[id] = Gun.obj.copy(node), id); - })){ return } - Gun.obj.del(put, soul); - }); - } - function search(at){ var cat = this; - var tmp; - if(!Gun.obj.is(tmp = at.get)){ return } - if(!Gun.obj.has(tmp, '#')){ return } - if((tmp = at.get) && (null === tmp['.'])){ - tmp['.'] = '##'; - return; - } - if((tmp = at.get) && Gun.obj.has(tmp, '.')){ - if(tmp['#']){ - cat = cat.root.gun.get(tmp['#'])._; - } - tmp = at['#']; - at['#'] = Gun.on.ask(proxy); - } - var tried = {}; - function proxy(ack, ev){ - var put = ack.put, lex = at.get; - if(!cat.pseudo || ack.via){ // TODO: BUG! MEMORY PERF! What about unsubscribing? - //ev.off(); - //ack.via = ack.via || {}; - return Gun.on.ack(tmp, ack); - } - if(ack.put){ - if(!lex['.']){ - ev.off(); - return Gun.on.ack(tmp, ack); - } - if(obj_has(ack.put[lex['#']], lex['.'])){ - ev.off(); - return Gun.on.ack(tmp, ack); - } - } - Gun.obj.map(cat.seen, function(ref,id){ // TODO: BUG! In-memory versus future? - if(tried[id]){ - return Gun.on.ack(tmp, ack); - } - tried[id] = true; - ref.on('out', { - gun: ref, - get: id = {'#': id, '.': at.get['.']}, - '#': Gun.on.ask(proxy) - }); - }); - } - } - function pseudo(at, ev){ var cat = this; - // TODO: BUG! Pseudo can't handle plurals!? - if(cat.pseudo){ - //ev.stun();return; - if(cat.pseudo === at.put){ return } - ev.stun(); - cat.change = cat.changed || cat.pseudo; - cat.on('in', Gun.obj.to(at, {put: cat.put = cat.pseudo})); - return; - } - if(!at.put){ return } - var rel = Gun.val.rel.is(at.put[keyed._]); - if(!rel){ return } - var soul = Gun.node.soul(at.put), resume = ev.stun(resume), root = cat.gun.back(-1), seen = cat.seen = {}; - cat.pseudo = cat.put = Gun.state.ify(Gun.node.ify({}, soul)); - root.get(rel).on(each, {change: true}); - function each(change){ - Gun.node.is(change, map); - } - function map(rel, soul){ - if(soul !== Gun.val.rel.is(rel)){ return } - if(seen[soul]){ return } - seen[soul] = root.get(soul).on(on, true); - } - function on(put){ - if(!put){ return } - cat.pseudo = Gun.HAM.union(cat.pseudo, put) || cat.pseudo; - cat.change = cat.changed = put; - cat.put = cat.pseudo; - resume({ - gun: cat.gun, - put: cat.pseudo, - get: soul - //via: this.at - }); - } - } - var obj = Gun.obj, obj_has = obj.has; - }()); - - })(require, './key'); - ;require(function(module){ var Gun = require('./core'); Gun.chain.path = function(field, cb, opt){ var back = this, gun = back, tmp; opt = opt || {}; opt.path = true; + Gun.log.once("pathing", "Warning: `.path` to be removed from core (but available as an extension), use `.get` chains instead. If you are opposed to this, please voice your opinion in https://gitter.im/amark/gun and ask others."); if(gun === gun._.root){if(cb){cb({err: Gun.log("Can't do that on root instance.")})}return gun} if(typeof field === 'string'){ tmp = field.split(opt.split || '.'); @@ -2002,6 +1919,7 @@ ;require(function(module){ var Gun = require('./core'), u; Gun.chain.not = function(cb, opt, t){ + Gun.log.once("nottobe", "Warning: `.not` to be removed from core (but available as an extension), use `.val` instead, which now supports (v0.7.x+) 'not found data' as `undefined` data in callbacks. If you are opposed to this, please voice your opinion in https://gitter.im/amark/gun and ask others."); return this.get(ought, {not: cb}); } function ought(at, ev){ ev.off(); @@ -2084,9 +2002,8 @@ this.to.next(at); (opt = {}).prefix = (at.opt || opt).prefix || at.gun.back('opt.prefix') || 'gun/'; var graph = root._.graph; - Gun.obj.map(at.put, function(node, soul){ - async[soul] = graph[soul] || node; + async[soul] = async[soul] || graph[soul] || node; }); count += 1; check[at['#']] = root; @@ -2101,7 +2018,7 @@ Gun.obj.map(all, function(node, soul){ // Since localStorage only has 5MB, it is better that we keep only // the data that the user is currently interested in. - node = graph[soul] || all[soul]; + node = graph[soul] || all[soul] || node; try{store.setItem(opt.prefix + soul, JSON.stringify(node)); }catch(e){ err = e || "localStorage failure" } }); @@ -2129,10 +2046,9 @@ if(!lex || !(soul = lex[Gun._.soul])){ return } //if(0 >= at.cap){ return } var field = lex['.']; - data = Gun.obj.ify(store.getItem(opt.prefix + soul) || null) || async[soul] || u; if(data && field){ - data = Gun.state.ify(u, field, Gun.state.is(data, field), data[field], soul); + data = Gun.state.to(data, field); } if(!data && !Gun.obj.empty(gun.back('opt.peers'))){ // if data not found, don't ack if there are peers. return; // Hmm, what if we have peers but we are disconnected? @@ -2249,4 +2165,4 @@ } })(require, './polyfill/request'); -}()); +}()); \ No newline at end of file diff --git a/gun.min.js b/gun.min.js index 3559579b8..e020f5900 100644 --- a/gun.min.js +++ b/gun.min.js @@ -1 +1 @@ -!function(){function t(n){function o(t){return t.split("/").slice(-1).toString().replace(".js","")}return n.slice?t[o(n)]:function(e,i){n(e={exports:{}}),t[o(i)]=e.exports}}var n;"undefined"!=typeof window&&(n=window),"undefined"!=typeof global&&(n=global),n=n||{};var o=n.console||{log:function(){}};if("undefined"!=typeof module)var e=module;t(function(t){var n={};n.fns=n.fn={is:function(t){return!!t&&"function"==typeof t}},n.bi={is:function(t){return t instanceof Boolean||"boolean"==typeof t}},n.num={is:function(t){return!e(t)&&(t-parseFloat(t)+1>=0||1/0===t||-(1/0)===t)}},n.text={is:function(t){return"string"==typeof t}},n.text.ify=function(t){return n.text.is(t)?t:"undefined"!=typeof JSON?JSON.stringify(t):t&&t.toString?t.toString():t},n.text.random=function(t,n){var o="";for(t=t||24,n=n||"0123456789ABCDEFGHIJKLMNOPQRSTUVWXZabcdefghijklmnopqrstuvwxyz";t>0;)o+=n.charAt(Math.floor(Math.random()*n.length)),t--;return o},n.text.match=function(t,o){function e(t,n){for(var o,e=-1,i=0;o=n[i++];)if(!~(e=t.indexOf(o,e+1)))return!1;return!0}var i=!1;if(t=t||"",o=n.text.is(o)?{"=":o}:o||{},n.obj.has(o,"~")&&(t=t.toLowerCase(),o["="]=(o["="]||o["~"]).toLowerCase()),n.obj.has(o,"="))return t===o["="];if(n.obj.has(o,"*")){if(t.slice(0,o["*"].length)!==o["*"])return!1;i=!0,t=t.slice(o["*"].length)}if(n.obj.has(o,"!")){if(t.slice(-o["!"].length)!==o["!"])return!1;i=!0}if(n.obj.has(o,"+")&&n.list.map(n.list.is(o["+"])?o["+"]:[o["+"]],function(n){return t.indexOf(n)>=0?void(i=!0):!0}))return!1;if(n.obj.has(o,"-")&&n.list.map(n.list.is(o["-"])?o["-"]:[o["-"]],function(n){return t.indexOf(n)<0?void(i=!0):!0}))return!1;if(n.obj.has(o,">")){if(!(t>o[">"]))return!1;i=!0}if(n.obj.has(o,"<")){if(!(tn?-1:n>o?1:0):0}},n.list.map=function(t,n,o){return a(t,n,o)},n.list.index=1,n.obj={is:function(t){return t?t instanceof Object&&t.constructor===Object||"Object"===Object.prototype.toString.call(t).match(/^\[object (\w+)\]$/)[1]:!1}},n.obj.put=function(t,n,o){return(t||{})[n]=o,t},n.obj.has=function(t,n){return t&&Object.prototype.hasOwnProperty.call(t,n)},n.obj.del=function(t,n){return t?(t[n]=null,delete t[n],t):void 0},n.obj.as=function(t,n,o,e){return t[n]=t[n]||(e===o?{}:o)},n.obj.ify=function(t){if(r(t))return t;try{t=JSON.parse(t)}catch(n){t={}}return t},function(){function t(t,n){u(this,n)&&o!==this[n]||(this[n]=t)}var o;n.obj.to=function(n,o){return o=o||{},a(n,t,o),o}}(),n.obj.copy=function(t){return t?JSON.parse(JSON.stringify(t)):t},function(){function t(t,n){var o=this.n;if(!o||!(n===o||r(o)&&u(o,n)))return n?!0:void 0}n.obj.empty=function(n,o){return n&&a(n,t,{n:o})?!1:!0}}(),function(){function t(n,o){return 2===arguments.length?(t.r=t.r||{},void(t.r[n]=o)):(t.r=t.r||[],void t.r.push(n))}var i=Object.keys;n.obj.map=function(a,s,f){var c,l,p,d,g,h=0,v=o(s);if(t.r=null,i&&r(a)&&(d=Object.keys(a),g=!0),e(a)||d)for(l=(d||a).length;l>h;h++){var b=h+n.list.index;if(v){if(p=g?s.call(f||this,a[d[h]],d[h],t):s.call(f||this,a[h],b,t),p!==c)return p}else if(s===a[g?d[h]:h])return d?d[h]:b}else for(h in a)if(v){if(u(a,h)&&(p=f?s.call(f,a[h],h,t):s(a[h],h,t),p!==c))return p}else if(s===a[h])return h;return v?t.r:n.list.index?0:-1}}(),n.time={},n.time.is=function(t){return t?t instanceof Date:+(new Date).getTime()};var o=n.fn.is,e=n.list.is,i=n.obj,r=i.is,u=i.has,a=i.map;t.exports=n})(t,"./type"),t(function(t){t.exports=function n(t,o,e){if(!t)return{to:n};var t=(this.tag||(this.tag={}))[t]||(this.tag[t]={tag:t,to:n._={next:function(){}}});if(o instanceof Function){var i={off:n.off||(n.off=function(){return this.next===n._.next?!0:(this===this.the.last&&(this.the.last=this.back),this.to.back=this.back,this.next=n._.next,void(this.back.to=this.to))}),to:n._,next:o,the:t,on:this,as:e};return(i.back=t.last||t).to=i,t.last=i}return(t=t.to).next(o),t}})(t,"./onto"),t(function(n){function o(t,n){n=n||{},n.id=n.id||"#",n.rid=n.rid||"@",n.uuid=n.uuid||function(){return+new Date+Math.random()};var o=e;return o.stun=function(t){var n=function(t){return n.off&&n===this.stun?(this.stun=null,!1):o.stun.skip?!1:(t&&(t.cb=t.fn,t.off(),e.queue.push(t)),!0)},e=n.res=function(t,r){if(!n.off){if(t instanceof Function)return o.stun.skip=!0,t.call(r),void(o.stun.skip=!1);n.off=!0;var u,a=0,s=e.queue,f=s.length;for(e.queue=[],n===i.stun&&(i.stun=null),a;f>a;a++)u=s[a],u.fn=u.cb,u.cb=null,o.stun.skip=!0,u.ctx.on(u.tag,u.fn,u),o.stun.skip=!1}},i=t._;return e.back=i.stun||(i.back||{_:{}})._.stun,e.back&&(e.back.next=n),e.queue=[],i.stun=n,e},o}var e=t("./onto");n.exports=o})(t,"./onify"),t(function(n){function o(t,n,e){o.time=e||Gun.time.is,o.waiting.push({when:t,event:n||function(){}}),o.soonest=t?0:t-n,clearTimeout(o.id),o.id=setTimeout(o.check,t)}},o.each=function(t,n,o){var e=this;t&&(t.when<=e.now?t.event instanceof Function&&setTimeout(function(){t.event()},0):(e.soonest=e.soonestt)return{defer:!0};if(e>n)return{historical:!0};if(n>e)return{converge:!0,incoming:!0};if(n===e){if(o(i)===o(r))return{state:!0};if(o(i)u?(a=0,u=t+o.drift):u=t+(a+=1)/s+o.drift}var e=t("./type"),i=t("./node"),r=e.time.is,u=-(1/0),a=0,s=1e3,f="undefined"!=typeof performance?performance.timing&&performance:!1,c=f&&f.timing&&f.timing.navigationStart||(f=!1);o._=">",o.drift=0,o.ify=function(t,n,e,r,u){if(!t||!t[k]){if(!u)return;t=i.soul.ify(t,u)}var a=d(t[k],o._);return l!==n&&n!==k&&(_(e)&&(a[n]=e),l!==r&&(t[n]=r)),t},o.is=function(t,n,e){var i=n&&t&&t[k]&&t[k][o._]||e;if(i)return _(i[n])?i[n]:-(1/0)},function(){function t(t,n){k!==n&&o.ify(this.o,n,this.s)}o.map=function(n,e,i){var r,u=h(u=n||e)?u:null;return n=y(n=n||e)?n:null,u&&!n?(e=_(e)?e:o(),u[k]=u[k]||{},v(u,t,{o:u,s:e}),u):(i=i||h(e)?e:r,e=_(e)?e:o(),function(o,u,a,s){return n?(n.call(i||this||{},o,u,a,s),void(g(a,u)&&r===a[u]||t.call({o:a,s:e},o,u))):(t.call({o:a,s:e},o,u),o)})}}();var l,p=e.obj,d=p.as,g=p.has,h=p.is,v=p.map,b=e.num,_=b.is,m=e.fn,y=m.is,k=i._;n.exports=o})(t,"./state"),t(function(n){var o=t("./type"),e=t("./val"),i=t("./node"),r={};!function(){function t(t,o){return t&&o===i.soul(t)&&i.is(t,this.fn)?void(this.cb&&(n.n=t,n.as=this.as,this.cb.call(n.as,t,o,n))):!0}function n(t){t&&i.is(n.n,t,n.as)}r.is=function(n,o,e,i){return n&&s(n)&&!l(n)?!d(n,t,{cb:o,fn:e,as:i}):!1}}(),function(){function t(t,r){var u;return(u=l(t,r))?u:(r.env=t,r.soul=o,i.ify(r.obj,n,r)&&(t.graph[e.rel.is(r.rel)]=r.node),r)}function n(n,o,r){var s,l,p=this,d=p.env;if(i._===o&&c(n,e.rel._))return r._;if(s=a(n,o,r,p,d)){if(o||(p.node=p.node||r||{},c(n,i._)&&(p.node._=g(n._)),p.node=i.soul.ify(p.node,e.rel.is(p.rel)),p.rel=p.rel||e.rel.ify(i.soul(p.node))),(l=d.map)&&(l.call(d.as||{},n,o,r,p),c(r,o))){if(n=r[o],u===n)return void f(r,o);if(!(s=a(n,o,r,p,d)))return}if(!o)return p.node;if(!0===s)return n;if(l=t(d,{obj:n,path:p.path.concat(o)}),l.node)return l.rel}}function o(t){var n=this,o=e.rel.is(n.rel),r=n.env.graph;n.rel=n.rel||e.rel.ify(t),n.rel[e.rel._]=t,n.node&&n.node[i._]&&(n.node[i._][e.rel._]=t),c(r,o)&&(r[t]=r[o],f(r,o))}function a(t,n,o,i,r){var u;return e.is(t)?!0:s(t)?1:(u=r.invalid)?(t=u.call(r.as||{},t,n,o),a(t,n,o,i,r)):void(r.err="Invalid value at '"+i.path.concat(n).join(".")+"'!")}function l(t,n){for(var o,e=t.seen,i=e.length;i--;)if(o=e[i],n.obj===o.obj)return o;e.push(n)}r.ify=function(n,o,i){var r={path:[],obj:n};return o?"string"==typeof o?o={soul:o}:o instanceof Function&&(o.map=o):o={},o.soul&&(r.rel=e.rel.ify(o.soul)),o.graph=o.graph||{},o.seen=o.seen||[],o.as=o.as||i,t(o,r),o.root=r.node,o.graph}}(),r.node=function(t){var n=i.soul(t);if(n)return p({},n,t)},function(){function t(t,n){var o,u;if(i._===n){if(l(t,e.rel._))return;return void(this.obj[n]=g(t))}return(o=e.rel.is(t))?(u=this.opt.seen[o])?void(this.obj[n]=u):void(this.obj[n]=this.opt.seen[o]=r.to(this.graph,o,this.opt)):void(this.obj[n]=t)}r.to=function(n,o,e){if(n){var i={};return e=e||{seen:{}},d(n[o],t,{obj:i,graph:n,opt:e}),i}}}();var u,a=(o.fn.is,o.obj),s=a.is,f=a.del,c=a.has,l=a.empty,p=a.put,d=a.map,g=a.copy;n.exports=r})(t,"./graph"),t(function(n){function o(){this.cache={}}var e=t("./type");o.prototype.track=function(t){return this.cache[t]=e.time.is(),this.to||this.gc(),t},o.prototype.check=function(t){return e.obj.has(this.cache,t)?this.track(t):!1},o.prototype.gc=function(){var t=this,n=e.time.is(),o=n,i=3e5;e.obj.map(t.cache,function(r,u){o=Math.min(n,r),i>n-r||e.obj.del(t.cache,u)});var r=e.obj.empty(t.cache);if(r)return void(t.to=null);var u=n-o,a=i-u;t.to=setTimeout(function(){t.gc()},a)},n.exports=o})(t,"./dup"),t(function(n){function i(t){return t instanceof i?(this._={gun:this}).gun:this instanceof i?i.create(this._={gun:this,opt:t}):new i(t)}i.is=function(t){return t instanceof i},i.version=.7,i.chain=i.prototype,i.chain.toJSON=function(){};var r=t("./type");r.obj.to(r,i),i.HAM=t("./HAM"),i.val=t("./val"),i.node=t("./node"),i.state=t("./state"),i.graph=t("./graph"),i.dup=t("./dup"),i.on=t("./onify")(),i._={node:i.node._,soul:i.val.rel._,state:i.state._,field:".",value:"="},function(){function t(t){var o,e=this,r=e.as;if(t.gun||(t.gun=r.gun),!t["#"]&&t["@"]){if(t["#"]=i.text.random(),r.ack(t["@"],t))return;return r.dup.track(t["#"]),void i.on("out",l(t,{gun:r.gun}))}t["#"]&&r.dup.check(t["#"])||(r.dup.track(t["#"]),r.ack(t["@"],t)||(o=l(t,{gun:r.gun}),t.get&&(n(t,r)||i.on("get",o)),t.put&&(i.HAM.synth(t,e,r.gun),i.on("put",o)),i.on("out",o)))}function n(t,n){var o,e=t.get[d],r=n.graph[e],u=t.get[g],a=n.next||(n.next={}),s=(a[e]||(a[e]=n.gun.get(e)))._;if(r){if(u){if(!c(r,u))return;o=i.obj.put(i.node.soul.ify({},e),u,r[u]),r=i.state.ify(o,u,i.state.is(r,u))}return r=i.graph.node(r),o=s.ack,n.on("in",{"@":t["#"],how:"mem",put:r,gun:s.gun}),o>0?!0:void 0}}i.create=function(n){n.on=n.on||i.on,n.root=n.root||n.gun,n.graph=n.graph||{},n.dup=n.dup||new i.dup,n.ask=i.on.ask,n.ack=i.on.ack;var o=n.gun.opt(n.opt);return n.once||(n.on("in",t,n),n.on("out",t,n)),n.once=1,o}}(),function(){i.on.ask=function(t,n){if(this.on){var o=i.text.random();return t&&this.on(o,t,n),o}},i.on.ack=function(t,n){if(t&&n&&this.on){var o=t["#"]||t;if(this.tag&&this.tag[o])return this.on(o,n),!0}}}(),function(){i.chain.opt=function(t){t=t||{};var n=this,o=n._,e=t.peers||t;return f(t)||(t={}),f(o.opt)||(o.opt=t),u(e)&&(e=[e]),a(e)&&(e=p(e,function(t,n,o){o(t,{url:t})}),f(o.opt.peers)||(o.opt.peers={}),o.opt.peers=l(e,o.opt.peers)),o.opt.wsc=o.opt.wsc||{protocols:null},o.opt.peers=o.opt.peers||{},l(t,o.opt),i.on("opt",o),n}}();var u=i.text.is,a=i.list.is,s=i.obj,f=s.is,c=s.has,l=s.to,p=s.map,d=i._.soul,g=i._.field;o.debug=function(t,n){return o.debug.i&&t===o.debug.i&&o.debug.i++&&(o.log.apply(o,arguments)||n)},i.log=function(){return!i.log.off&&o.log.apply(o,arguments),[].slice.call(arguments).join(" ")},i.log.once=function(t,n,o){return(o=i.log.once)[t]=o[t]||0,o[t]++||i.log(n)},i.log.once("welcome","Hello wonderful person! :) Thanks for using GUN, feel free to ask for help on https://gitter.im/amark/gun and ask StackOverflow questions tagged with 'gun'!"),"undefined"!=typeof window&&(window.Gun=i),"undefined"!=typeof e&&(e.exports=i),n.exports=i})(t,"./root"),t(function(){var n=t("./root");n.chain.back=function(t,n){var i;if(-1===t||1/0===t)return this._.root;if(1===t)return this._.back||this;var r=this,u=r._;if("string"==typeof t&&(t=t.split(".")),t instanceof Array){var a=0,s=t.length,i=u;for(a;s>a;a++)i=(i||e)[t[a]];if(o!==i)return n?r:i;if(i=u.back)return i.back(t,n)}else if(t instanceof Function){for(var f,i={back:r};(i=i.back)&&(i=i._)&&!(f=t(i,n)););return f}};var o,e={}})(t,"./back"),t(function(){function o(t){var n,o=this.as,e=o.gun,i=e.back(-1);if(t.gun||(t.gun=e),(n=t.get)&&!n[m])if(g(n,y)){n=n[y];var r=n?e.get(n)._:o;if(g(r,"put"))return void r.on("in",r);if(g(o,"put")){var u,a=o.put;if((u=c.node.soul(a))&&(a=c.val.rel.ify(u)),u=c.val.rel.is(a)){if(!t.gun._)return;return void t.gun._.on("out",{get:{"#":u,".":n},"#":i._.ask(c.HAM.synth,t.gun),gun:t.gun})}if(l===a||c.val.is(a)){if(!t.gun._)return;return void t.gun._.on("in",{get:n,gun:t.gun})}}else o.map&&_(o.map,function(t){t.at.on("in",t.at)});if(o.soul){if(!t.gun._)return;return void t.gun._.on("out",{get:{"#":o.soul,".":n},"#":i._.ask(c.HAM.synth,t.gun),gun:t.gun})}if(o.get){if(!o.back._)return;return void o.back._.on("out",{get:h({},y,o.get),gun:e})}t=b(t,{get:{}})}else{if(g(o,"put")?o.on("in",o):o.map&&_(o.map,function(t){t.at.on("in",t.at)}),o.ack&&!g(o,"put"))return;if(o.ack=-1,o.soul)return void o.on("out",{get:{"#":o.soul},"#":i._.ask(c.HAM.synth,o.gun),gun:o.gun});if(o.get){if(!o.back._)return;return void o.back._.on("out",{get:h({},y,o.get),gun:o.gun})}}o.back._.on("out",t)}function e(t){t=t._||t;{var n,o=this,e=this.as,u=t.gun,f=u._,d=t.put;e.back._||p}if(0>e.ack&&!c.val.rel.is(d)&&(e.ack=1),e.get&&t.get!==e.get&&(t=b(t,{get:e.get})),e.field&&f!==e&&(t=b(t,{gun:e.gun}),f.ack&&(e.ack=e.ack||f.ack)),l===d){if(o.to.next(t),e.soul)return;return r(e,t,o),e.field&&s(e,t),v(f.echo,e.id),void v(e.map,f.id)}return e.soul?(e.root._.now&&(t=b(t,{put:d=f.put})),o.to.next(t),r(e,t,o),void _(d,a,{at:t,cat:e})):(n=c.val.rel.is(d))?(i(e,t,f,n),o.to.next(t),void r(e,t,o)):c.val.is(d)?(e.field||e.soul?s(e,t):(f.field||f.soul)&&((f.echo||(f.echo={}))[e.id]=e,(e.map||(e.map={}))[f.id]=e.map[f.id]||{at:f}),o.to.next(t),void r(e,t,o)):(e.field&&f!==e&&g(f,"put")&&(e.put=f.put),(n=c.node.soul(d))&&f.field&&(f.put=e.root.get(n)._.put),o.to.next(t),r(e,t,o),i(e,t,f,n),void _(d,a,{at:t,cat:e}))}function i(t,n,o,e){if(e&&k!==t.get){var r=t.root.get(e)._;t.field?o=r:o.field&&i(o,n,o,e),o!==t&&((o.echo||(o.echo={}))[t.id]=t,t.field&&!(t.map||p)[o.id]&&s(t,n),r=(t.map||(t.map={}))[o.id]=t.map[o.id]||{at:o},e!==r.rel&&f(t,r.rel=e))}}function r(t,n,o){t.echo&&(t.field&&(n=b(n,{event:o})),_(t.echo,u,n))}function u(t){t.on("in",this)}function a(t,n){var o,e,i,r=this.cat,u=r.next||p,a=this.at;(k!==n||u[n])&&(o=u[n])&&(i=o._,i.field?(t&&t[m]&&c.val.rel.is(t)===c.node.soul(i.put)||(i.put=t),e=o):e=a.gun.get(n),i.on("in",{put:t,get:n,gun:e,via:a}))}function s(t){if(t.field||t.soul){var n=t.map;t.map=null,null!==n&&(l!==n||t.put===l)&&(_(n,function(n){(n=n.at)&&v(n.echo,t.id)}),_(t.next,function(t,n){var o=t._;o.put=l,o.ack&&(o.ack=-1),o.on("in",{get:n,gun:t,put:l})}))}}function f(t,n){var o=t.root.get(n)._;return t.ack?(o.ack=o.ack||-1,void o.on("out",{get:{"#":n},"#":t.root._.ask(c.HAM.synth,o.gun),gun:o.gun})):void _(t.next,function(e,i){e._.on("out",{get:{"#":n,".":i},"#":t.root._.ask(c.HAM.synth,o.gun),gun:e})})}var c=t("./root");c.chain.chain=function(){var t=this._,i=new this.constructor(this),r=i._;return r.root=n=t.root,r.id=++n._.once,r.back=this,r.on=c.on,c.on("chain",r),r.on("in",e,r),r.on("out",o,r),i},c.chain.chain.input=e;var l,p={},d=c.obj,g=d.has,h=d.put,v=d.del,b=d.to,_=d.map,m=c._.soul,y=c._.field,k=c.node._})(t,"./chain"),t(function(){function n(t,n){var o=n._,e=o.next,i=n.chain(),r=i._;return e||(e=o.next={}),e[r.get=t]=i,o.root===n?r.soul=t:(o.soul||o.field)&&(r.field=t),i}function o(t){var n,o=this,e=o.as,r=t.gun,a=r._,f=t.put;i===f&&(f=a.put),(n=f)&&n[s._]&&(n=s.is(n))&&(n=a.root.get(n)._,i!==n.put&&(t=u(t,{put:n.put}))),e.use(t,t.event||o),o.to.next(t)}var e=t("./root");e.chain.get=function(t,i,r){if("string"!=typeof t){if(t instanceof Function){var u=this,s=u._;return r=i||{},r.use=t,r.out=r.out||{cap:1},r.out.get=r.out.get||{},"_"!=s.get&&(s.root._.now=!0),s.on("in",o,r),s.on("out",r.out),s.root._.now=!1,u}return a(t)?this.get(""+t,i,r):((r=this.chain())._.err={err:e.log("Invalid get request!",t)},i&&i.call(r,r._.err),r)}var u,c,l=this,p=l._,d=p.next||f;return(u=d[t])||(u=n(t,l)),(c=p.stun)&&(u._.stun=u._.stun||c),i&&i instanceof Function&&u.get(i,r),u};var i,r=e.obj,u=(r.has,e.obj.to),a=e.num.is,s=e.val.rel,f=(e.node._,{})})(t,"./get"),t(function(){function n(t){t.batch=e;var n=t.opt||{},o=t.env=s.state.map(r,n.state);return o.soul=t.soul,t.graph=s.graph.ify(t.data,o,t),o.err?((t.ack||h).call(t,t.out={err:s.log(o.err)}),void(t.res&&t.res())):void t.batch()}function e(){var t=this;t.graph&&!d(t.stun,i)&&((t.res||v)(function(){t.ref._.on("out",{cap:3,gun:t.ref,put:t.out=t.env.graph,opt:t.opt,"#":t.gun.back(-1)._.ask(function(n){this.off(),t.ack&&t.ack(n,this)},t.opt)})},t),t.res&&t.res())}function i(t){return t?!0:void 0}function r(t,n,o,e){var i=this;!n&&e.path.length&&(i.res||v)(function(){var t=e.path,n=i.ref,o=(i.opt,0),r=t.length;for(o;r>o;o++)n=n.get(t[o]);return i.not||s.node.soul(e.obj)?void e.soul(s.node.soul(e.obj)||((i.opt||{}).uuid||i.gun.back("opt.uuid")||s.text.random)()):((i.stun=i.stun||{})[t]=!0,void n.get("_").get(u,{as:{at:e,as:i}}))},{as:i,at:e})}function u(t,n){var o=this.as,e=o.at;o=o.as,t.gun&&t.gun._.back&&(n.off(),t=t.gun._.back._,e.soul(s.node.soul(e.obj)||s.node.soul(t.put)||s.val.rel.is(t.put)||((o.opt||{}).uuid||o.gun.back("opt.uuid")||s.text.random)()),o.stun[e.path]=!1,o.batch())}function a(t,n){var e=this.as;if(t.gun&&t.gun._){if(t.err)return void o.log("Please report this as an issue! Put.any.err");var i,r=t.gun._.back._,u=r.put,a=e.opt||{};if(n.off(),e.ref!==e.gun){if(i=e.gun._.get||r.get,!i)return void o.log("Please report this as an issue! Put.no.get");e.data=p({},i,e.data),i=null}if(f===u){if(!r.get)return;r.soul||(i=r.gun.back(function(t){return t.soul?t.soul:void(e.data=p({},t.get,e.data))})),i=i||r.get,r=r.root.get(i)._,e.not=e.soul=i,u=e.data}e.not||(e.soul=s.node.soul(u))||(e.soul=e.path&&l(e.data)?(a.uuid||r.root._.opt.uuid||s.text.random)():t.soul||r.soul||(a.uuid||r.root._.opt.uuid||s.text.random)()),e.ref.put(e.data,e.soul,e)}}var s=t("./root");s.chain.put=function(t,o,e){var i,r=this,u=r._,f=u.root;return e=e||{},e.data=t,e.gun=e.gun||r,"string"==typeof o?e.soul=o:e.ack=o,u.soul&&(e.soul=u.soul),e.soul||f===r?l(e.data)?(e.gun=r=f.get(e.soul=e.soul||(e.not=s.node.soul(e.data)||(f._.opt.uuid||s.text.random)())),e.ref=e.gun,n(e),r):((e.ack||h).call(e,e.out={err:s.log("Data saved to the root level of the graph must be a node (an object), not a",typeof e.data,'of "'+e.data+'"!')}),e.res&&e.res(),r):s.is(t)?(t.get(function(t,n){n.off();var i=s.node.soul(t.put);return i?void r.put(s.val.rel.ify(i),o,e):void s.log("The reference you are saving is a",typeof t.put,'"'+e.put+'", not a node (object)!')}),r):(e.ref=e.ref||f===(i=u.back)?r:i,e.ref._.soul&&s.val.is(e.data)&&u.get?(e.data=p({},u.get,e.data),e.ref.put(e.data,e.soul,e),r):(e.ref.get("_").get(a,{as:e}),e.out||(e.res=e.res||s.on.stun(e.ref),e.gun._.stun=e.ref._.stun),r))};var f,c=s.obj,l=c.is,p=c.put,d=c.map,g={},h=function(){},v=function(t,n){t.call(n||g)}})(t,"./put"),t(function(n){var e=t("./root");n.exports=e,function(){function t(t,n){if(e._.node!==n){var r=this.node,u=this.vertex,a=this.union,s=this.machine,f=g(r,n),c=g(u,n);if(i===f||i===c)return!0;var l=t,p=u[n];if(!b(l)&&i!==l)return!0;if(!b(p)&&i!==p)return!0;var d=e.HAM(s,f,c,l,p);if(d.err)return void o.log(".!HYPOTHETICAL AMNESIA MACHINE ERR!.",n,d.err);if(!(d.state||d.historical||d.current))return d.incoming?(a[n]=t,void h(a,n,f)):d.defer?(a[n]=t,void h(a,n,f)):void 0}}function n(t,n){var o=this;if(e._.node!==n&&b(t)){var i=o.node,r=o.vertex,u=g(i,n,!0),a=g(r,n,!0),s=o.delta,f=e.HAM(o.machine,u,a,t,r[n]);f.incoming&&(s[n]=t,h(s,n,u))}}e.HAM.union=function(n,o,i){return o&&o._&&(n=n||e.node.soul.ify({_:{">":{}}},e.node.soul(o)),n&&n._&&(i=a(i)?{machine:i}:{machine:e.state()},i.union=n||e.obj.copy(n),i.vertex=n,i.node=o,!l(o,t,i)))?i.union:void 0},e.HAM.delta=function(t,o,i){return i=a(i)?{machine:i}:{machine:e.state()},t?(i.soul=e.node.soul(i.vertex=t),i.soul?(i.delta=e.node.soul.ify({},i.soul),l(i.node=o,n,i),i.delta):void 0):e.obj.copy(o)},e.HAM.synth=function(t,n,o){var r=this.as||o,u=r._,a=u.root._,s={};if(!t.put){if(u.put!==i)return;return void u.on("in",{get:u.get,put:u.put=i,gun:r,via:t})}l(t.put,function(t,n){var o=this.graph;s[n]=e.HAM.delta(o[n],t,{graph:o}),o[n]=e.HAM.union(o[n],t)||o[n]},a),t.gun!==a.gun&&(s=t.put),l(s,function(o,r){var a=this,s=a.next||(a.next={}),l=s[r]||(s[r]=a.gun.get(r)),p=l._;return p.put=a.graph[r],u.field&&!f(o,u.field)?((t=c(t,{})).put=i,void e.HAM.synth(t,n,u.gun)):void p.on("in",{put:o,get:r,gun:l,via:t})},a)}}();{var i,r=e,u=r.num,a=u.is,s=r.obj,f=s.has,c=(s.put,s.to),l=s.map,p=e.node,d=(p.soul,p.is,p.ify,e.state),g=d.is,h=d.ify,v=e.val,b=v.is;v.rel.is}})(t,"./index"),t(function(n){var o=t("./root");t("./index"),t("./opt"),t("./chain"),t("./back"),t("./put"),t("./get"),n.exports=o})(t,"./core"),t(function(){{var n=t("./core"),e=n.obj,i=(e.is,e.put),r=(e.map,e.empty,n.num);r.is,n.val.rel._}!function(){function t(t,o){var u=this;return o.off(),u.soul=n.node.soul(t.put),u.soul&&u.key!==u.soul?(u.data=i({},r._,n.node.ify(i({},u.soul,n.val.rel.ify(u.soul)),"#"+u.key+"#")),(u.res||e)(function(){u.ref.put(u.data,u.any,{soul:u.key,key:u.key})},u),void(u.res&&u.res())):u.data={}}function e(t,n){t.call(n||{})}function r(t){if(t&&"#"===t[0]&&"#"===t[t.length-1]){var n=t.slice(1,-1);if(n)return n}}function u(t){var o=this;if(!t.put)return void(t.get&&a.call(t.gun?t.gun._:o,t));if(!t.opt||!t.opt.key){var e=t.put,i=o.gun.back(-1)._.graph;n.graph.is(e,function(t,o){n.node.is(i["#"+o+"#"],function r(o,u){return u===n.val.rel.is(o)?(o=i["#"+u+"#"])?void n.node.is(o,r):void n.node.soul.ify(o=e[u]=n.obj.copy(t),u):void 0})&&n.obj.del(e,o)})}}function a(t){function o(u,a){var s=(u.put,t.get);if(!i.pseudo||u.via)return n.on.ack(e,u);if(u.put){if(!s["."])return a.off(),n.on.ack(e,u);if(c(u.put[s["#"]],s["."]))return a.off(),n.on.ack(e,u)}n.obj.map(i.seen,function(i,a){return r[a]?n.on.ack(e,u):(r[a]=!0,void i.on("out",{gun:i,get:a={"#":a,".":t.get["."]},"#":n.on.ask(o)}))})}var e,i=this;if(n.obj.is(e=t.get)&&n.obj.has(e,"#")){if((e=t.get)&&null===e["."])return void(e["."]="##");(e=t.get)&&n.obj.has(e,".")&&(e["#"]&&(i=i.root.gun.get(e["#"])._),e=t["#"],t["#"]=n.on.ask(o));var r={}}}function s(t,o){function e(t){n.node.is(t,i)}function i(t,o){o===n.val.rel.is(t)&&(p[o]||(p[o]=l.get(o).on(u,!0)))}function u(t){t&&(a.pseudo=n.HAM.union(a.pseudo,t)||a.pseudo,a.change=a.changed=t,a.put=a.pseudo,c({gun:a.gun,put:a.pseudo,get:f}))}var a=this;if(a.pseudo){if(a.pseudo===t.put)return;return o.stun(),a.change=a.changed||a.pseudo,void a.on("in",n.obj.to(t,{put:a.put=a.pseudo}))}if(t.put){var s=n.val.rel.is(t.put[r._]);if(s){var f=n.node.soul(t.put),c=o.stun(c),l=a.gun.back(-1),p=a.seen={};a.pseudo=a.put=n.state.ify(n.node.ify({},f)),l.get(s).on(e,{change:!0})}}}n.chain.key=function(e,i,r){if(!e)return i&&i.call(this,{err:n.log("No key!")}),this;var u=this;return"string"==typeof r?(o.log("Please report this as an issue! key.opt.string"),u):u===u._.root?(i&&i({err:n.log("Can't do that on root instance.")}),u):(r=r||{},r.key=e,r.any=i||function(){},r.ref=u.back(-1).get(r.key),r.gun=r.gun||u,u.on(t,{as:r}),r.data||(r.res=n.on.stun(r.ref)),u)},r._="##",n.on("next",function(t){var n=t.gun;n.back(-1)===t.back&&(n.on("in",s,n._),n.on("out",u,n._))});var f=n.obj,c=f.has}()})(t,"./key"),t(function(){var n=t("./core");n.chain.path=function(t,o,e){var i,r=this,u=r;if(e=e||{},e.path=!0,u===u._.root)return o&&o({err:n.log("Can't do that on root instance.")}),u;if("string"==typeof t){if(i=t.split(e.split||"."),1===i.length)return u=r.get(t,o,e),u._.opt=e,u;t=i}if(t instanceof Array){if(t.length>1){u=r;var a=0,s=t.length;for(a;s>a;a++)u=u.get(t[a],a+1===s?o:null,e)}else u=r.get(t[0],o,e);return u._.opt=e,u}return t||0==t?(u=r.get(""+t,o,e),u._.opt=e,u):r}})(t,"./path"),t(function(){function n(t,n){var o,r=this,u=t.gun,s=u._,f=s.put||t.put,o=r.last,c=s.id+t.get;if(i!==f){if(f&&f[a._]&&(o=a.is(f))){if(o=s.root.get(o)._,i===o.put)return;f=o.put}r.change&&(f=t.put),(o.put!==f||o.get!==c||e.node.soul(f))&&(o.put=f,o.get=c,s.last=f,r.as?r.ok.call(r.as,t,n):r.ok.call(u,f,t.get,t,n))}}function o(t,n){var e,r=this.as,u=r.cat,s=t.gun,f=s._,c=f.put||t.put;if(c&&c[a._]&&(e=a.is(c))){if(e=u.root.get(e)._,i===e.put)return;c=e.put}if(n.wait&&clearTimeout(n.wait),!r.async)return void(n.wait=setTimeout(function(){o.call({as:r},t,n,n.wait||1)},r.wait||99));if(u.field||u.soul){if(n.off())return}else{if((r.seen=r.seen||{})[f.id])return;r.seen[f.id]=!0}r.ok.call(t.gun||r.gun,c,t.get)}var e=t("./core");e.chain.on=function(t,o,e,i){var r,u,a=this,f=a._;if("string"==typeof t)return o?(r=f.on(t,o,e||f,i),e&&e.gun&&(e.subs||(e.subs=[])).push(r),u=function(){r&&r.off&&r.off(),u.off()},u.off=a.off.bind(a)||s,a.off=u,a):f.on(t);var c=o;return c=!0===c?{change:!0}:c||{},c.ok=t,c.last={},a.get(n,c),a},e.chain.val=function(t,n){var r=this,u=r._,a=u.put;if(0=a?n():void(o||(clearTimeout(o),o=setTimeout(n,1e3)))}),Gun.on("get",function(t){this.to.next(t);var n,o,i,u,a=t.gun,s=t.get;if((i=t.opt||{}).prefix=i.prefix||t.gun.back("opt.prefix")||"gun/",s&&(n=s[Gun._.soul])){var f=s["."];o=Gun.obj.ify(e.getItem(i.prefix+n)||null)||r[n]||u,o&&f&&(o=Gun.state.ify(u,f,Gun.state.is(o,f),o[f],n)),(o||Gun.obj.empty(a.back("opt.peers")))&&a.on("in",{"@":t["#"],put:Gun.graph.node(o),how:"lS"})}})}})(t,"./adapters/localStorage"),t(function(){function n(t){var n=a,o=this,i=t.wire||e(t,o);return o.wsp&&o.wsp.count++,i?i.readyState===i.OPEN?void i.send(n):void(t.queue=t.queue||[]).push(n):void 0}function o(t,n,e){if(e&&t){try{t=JSON.parse(t.data||t)}catch(i){}if(t instanceof Array)for(var r,u=0;r=t[u++];)o(r,n,e);else e.wsp&&1===e.wsp.count&&((t.body||t).wsp=f),e.gun.on("in",t.body||t)}}function e(t,e){if(t&&t.url){var s=t.url.replace("http","ws"),f=t.wire=new u(s,e.opt.wsc.protocols,e.opt.wsc);return f.onclose=function(){i(t,e)},f.onerror=function(n){i(t,e),n&&"ECONNREFUSED"===n.code},f.onopen=function(){var o=t.queue;t.queue=[],r.obj.map(o,function(o){a=o,n.call(e,t)})},f.onmessage=function(n){o(n,t,e)},f}}function i(t,n){clearTimeout(t.defer),t.defer=setTimeout(function(){e(t,n)},2e3)}var r=t("./core");if("undefined"==typeof JSON)throw new Error("Gun depends on JSON. Please load it first:\najax.cdnjs.com/ajax/libs/json2/20110223/json2.js");var u;if("undefined"!=typeof window){u=window.WebSocket||window.webkitWebSocket||window.mozWebSocket;var a,s,f=function(){};r.on("out",function(t){this.to.next(t);var o=t.gun._.root._,e=o.wsp||(o.wsp={});if(!t.wsp||1!==e.count){if(a=JSON.stringify(t),o.udrain)return void o.udrain.push(a);o.udrain=[],clearTimeout(s),s=setTimeout(function(){if(o.udrain){var t=o.udrain;o.udrain=null,t.length&&(a=JSON.stringify(t),r.obj.map(o.opt.peers,n,o))}},1),e.count=0,r.obj.map(o.opt.peers,n,o)}})}})(t,"./polyfill/request")}(); \ No newline at end of file +!function(){function t(n){function o(t){return t.split("/").slice(-1).toString().replace(".js","")}return n.slice?t[o(n)]:function(e,i){n(e={exports:{}}),t[o(i)]=e.exports}}var n;"undefined"!=typeof window&&(n=window),"undefined"!=typeof global&&(n=global),n=n||{};var o=n.console||{log:function(){}};if("undefined"!=typeof module)var e=module;t(function(t){var n={};n.fns=n.fn={is:function(t){return!!t&&"function"==typeof t}},n.bi={is:function(t){return t instanceof Boolean||"boolean"==typeof t}},n.num={is:function(t){return!e(t)&&(t-parseFloat(t)+1>=0||1/0===t||-(1/0)===t)}},n.text={is:function(t){return"string"==typeof t}},n.text.ify=function(t){return n.text.is(t)?t:"undefined"!=typeof JSON?JSON.stringify(t):t&&t.toString?t.toString():t},n.text.random=function(t,n){var o="";for(t=t||24,n=n||"0123456789ABCDEFGHIJKLMNOPQRSTUVWXZabcdefghijklmnopqrstuvwxyz";t>0;)o+=n.charAt(Math.floor(Math.random()*n.length)),t--;return o},n.text.match=function(t,o){function e(t,n){for(var o,e=-1,i=0;o=n[i++];)if(!~(e=t.indexOf(o,e+1)))return!1;return!0}var i=!1;if(t=t||"",o=n.text.is(o)?{"=":o}:o||{},n.obj.has(o,"~")&&(t=t.toLowerCase(),o["="]=(o["="]||o["~"]).toLowerCase()),n.obj.has(o,"="))return t===o["="];if(n.obj.has(o,"*")){if(t.slice(0,o["*"].length)!==o["*"])return!1;i=!0,t=t.slice(o["*"].length)}if(n.obj.has(o,"!")){if(t.slice(-o["!"].length)!==o["!"])return!1;i=!0}if(n.obj.has(o,"+")&&n.list.map(n.list.is(o["+"])?o["+"]:[o["+"]],function(n){return t.indexOf(n)>=0?void(i=!0):!0}))return!1;if(n.obj.has(o,"-")&&n.list.map(n.list.is(o["-"])?o["-"]:[o["-"]],function(n){return t.indexOf(n)<0?void(i=!0):!0}))return!1;if(n.obj.has(o,">")){if(!(t>o[">"]))return!1;i=!0}if(n.obj.has(o,"<")){if(!(tn?-1:n>o?1:0):0}},n.list.map=function(t,n,o){return a(t,n,o)},n.list.index=1,n.obj={is:function(t){return t?t instanceof Object&&t.constructor===Object||"Object"===Object.prototype.toString.call(t).match(/^\[object (\w+)\]$/)[1]:!1}},n.obj.put=function(t,n,o){return(t||{})[n]=o,t},n.obj.has=function(t,n){return t&&Object.prototype.hasOwnProperty.call(t,n)},n.obj.del=function(t,n){return t?(t[n]=null,delete t[n],t):void 0},n.obj.as=function(t,n,o,e){return t[n]=t[n]||(e===o?{}:o)},n.obj.ify=function(t){if(r(t))return t;try{t=JSON.parse(t)}catch(n){t={}}return t},function(){function t(t,n){u(this,n)&&o!==this[n]||(this[n]=t)}var o;n.obj.to=function(n,o){return o=o||{},a(n,t,o),o}}(),n.obj.copy=function(t){return t?JSON.parse(JSON.stringify(t)):t},function(){function t(t,n){var o=this.n;if(!o||!(n===o||r(o)&&u(o,n)))return n?!0:void 0}n.obj.empty=function(n,o){return n&&a(n,t,{n:o})?!1:!0}}(),function(){function t(n,o){return 2===arguments.length?(t.r=t.r||{},void(t.r[n]=o)):(t.r=t.r||[],void t.r.push(n))}var i=Object.keys;n.obj.map=function(a,s,f){var c,l,p,g,d,h=0,v=o(s);if(t.r=null,i&&r(a)&&(g=Object.keys(a),d=!0),e(a)||g)for(l=(g||a).length;l>h;h++){var _=h+n.list.index;if(v){if(p=d?s.call(f||this,a[g[h]],g[h],t):s.call(f||this,a[h],_,t),p!==c)return p}else if(s===a[d?g[h]:h])return g?g[h]:_}else for(h in a)if(v){if(u(a,h)&&(p=f?s.call(f,a[h],h,t):s(a[h],h,t),p!==c))return p}else if(s===a[h])return h;return v?t.r:n.list.index?0:-1}}(),n.time={},n.time.is=function(t){return t?t instanceof Date:+(new Date).getTime()};var o=n.fn.is,e=n.list.is,i=n.obj,r=i.is,u=i.has,a=i.map;t.exports=n})(t,"./type"),t(function(t){t.exports=function n(t,o,e){if(!t)return{to:n};var t=(this.tag||(this.tag={}))[t]||(this.tag[t]={tag:t,to:n._={next:function(){}}});if(o instanceof Function){var i={off:n.off||(n.off=function(){return this.next===n._.next?!0:(this===this.the.last&&(this.the.last=this.back),this.to.back=this.back,this.next=n._.next,void(this.back.to=this.to))}),to:n._,next:o,the:t,on:this,as:e};return(i.back=t.last||t).to=i,t.last=i}return(t=t.to).next(o),t}})(t,"./onto"),t(function(n){function o(t,n){n=n||{},n.id=n.id||"#",n.rid=n.rid||"@",n.uuid=n.uuid||function(){return+new Date+Math.random()};var o=e;return o.stun=function(t){var n=function(t){return n.off&&n===this.stun?(this.stun=null,!1):o.stun.skip?!1:(t&&(t.cb=t.fn,t.off(),e.queue.push(t)),!0)},e=n.res=function(t,r){if(!n.off){if(t instanceof Function)return o.stun.skip=!0,t.call(r),void(o.stun.skip=!1);n.off=!0;var u,a=0,s=e.queue,f=s.length;for(e.queue=[],n===i.stun&&(i.stun=null),a;f>a;a++)u=s[a],u.fn=u.cb,u.cb=null,o.stun.skip=!0,u.ctx.on(u.tag,u.fn,u),o.stun.skip=!1}},i=t._;return e.back=i.stun||(i.back||{_:{}})._.stun,e.back&&(e.back.next=n),e.queue=[],i.stun=n,e},o}var e=t("./onto");n.exports=o})(t,"./onify"),t(function(n){function o(t,n,e){o.time=e||Gun.time.is,o.waiting.push({when:t,event:n||function(){}}),o.soonest=t?0:t-n,clearTimeout(o.id),o.id=setTimeout(o.check,t)}},o.each=function(t,n,o){var e=this;t&&(t.when<=e.now?t.event instanceof Function&&setTimeout(function(){t.event()},0):(e.soonest=e.soonestt)return{defer:!0};if(e>n)return{historical:!0};if(n>e)return{converge:!0,incoming:!0};if(n===e){if(i=o(i)||"",r=o(r)||"",i===r)return{state:!0};if(r>i)return{converge:!0,current:!0};if(i>r)return{converge:!0,incoming:!0}}return{err:"Invalid CRDT Data: "+i+" to "+r+" at "+n+" to "+e+"!"}}if("undefined"==typeof JSON)throw new Error("JSON is not included in this browser. Please load it first: ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js");var o=JSON.stringify;t.exports=n})(t,"./HAM"),t(function(n){var o=t("./type"),e={};e.is=function(t){return t===i?!1:null===t?!0:t===1/0?!1:s(t)||u(t)||a(t)?!0:e.rel.is(t)||!1},e.rel={_:"#"},function(){function t(t,n){var o=this;return o.id?o.id=!1:n==r&&s(t)?void(o.id=t):o.id=!1}e.rel.is=function(n){if(n&&n[r]&&!n._&&c(n)){var o={};if(p(n,t,o),o.id)return o.id}return!1}}(),e.rel.ify=function(t){return l({},r,t)};var i,r=e.rel._,u=o.bi.is,a=o.num.is,s=o.text.is,f=o.obj,c=f.is,l=f.put,p=f.map;n.exports=e})(t,"./val"),t(function(n){var o=t("./type"),e=t("./val"),i={_:"_"};i.soul=function(t,n){return t&&t._&&t._[n||p]},i.soul.ify=function(t,n){return n="string"==typeof n?{soul:n}:n||{},t=t||{},t._=t._||{},t._[p]=n.soul||t._[p]||l(),t},i.soul._=e.rel._,function(){function t(t,n){return n!==i._?e.is(t)?void(this.cb&&this.cb.call(this.as,t,n,this.n,this.s)):!0:void 0}i.is=function(n,o,e){var r;return a(n)&&(r=i.soul(n))?!f(n,t,{as:e,cb:o,s:r,n:n}):!1}}(),function(){function t(t,n){var o,i,r=this.o;return r.map?(o=r.map.call(this.as,t,""+n,r.node),void(i===o?s(r.node,n):r.node&&(r.node[n]=o))):void(e.is(t)&&(r.node[n]=t))}i.ify=function(n,o,e){return o?"string"==typeof o?o={soul:o}:o instanceof Function&&(o={map:o}):o={},o.map&&(o.node=o.map.call(e,n,r,o.node||{})),(o.node=i.soul.ify(o.node||{},o))&&f(n,t,{o:o,as:e}),o.node}}();var r,u=o.obj,a=u.is,s=u.del,f=u.map,c=o.text,l=c.random,p=i.soul._;n.exports=i})(t,"./node"),t(function(n){function o(){var t;return t=f?c+f.now():r(),t>u?(a=0,u=t+o.drift):u=t+(a+=1)/s+o.drift}var e=t("./type"),i=t("./node"),r=e.time.is,u=-(1/0),a=0,s=1e3,f="undefined"!=typeof performance?performance.timing&&performance:!1,c=f&&f.timing&&f.timing.navigationStart||(f=!1);o._=">",o.drift=0,o.is=function(t,n,e){var i=n&&t&&t[x]&&t[x][o._]||e;if(i)return m(i=i[n])?i:-(1/0)},o.ify=function(t,n,e,r,u){if(!t||!t[x]){if(!u)return;t=i.soul.ify(t,u)}var a=g(t[x],o._);return l!==n&&n!==x&&(m(e)&&(a[n]=e),l!==r&&(t[n]=r)),t},o.to=function(t,n,e){var r=t[n];return h(r)&&(r=_(r)),o.ify(e,n,o.is(t,n),r,i.soul(t))},function(){function t(t,n){x!==n&&o.ify(this.o,n,this.s)}o.map=function(n,e,i){var r,u=h(u=n||e)?u:null;return n=k(n=n||e)?n:null,u&&!n?(e=m(e)?e:o(),u[x]=u[x]||{},v(u,t,{o:u,s:e}),u):(i=i||h(e)?e:r,e=m(e)?e:o(),function(o,u,a,s){return n?(n.call(i||this||{},o,u,a,s),void(d(a,u)&&r===a[u]||t.call({o:a,s:e},o,u))):(t.call({o:a,s:e},o,u),o)})}}();var l,p=e.obj,g=p.as,d=p.has,h=p.is,v=p.map,_=p.copy,b=e.num,m=b.is,y=e.fn,k=y.is,x=i._;n.exports=o})(t,"./state"),t(function(n){var o=t("./type"),e=t("./val"),i=t("./node"),r={};!function(){function t(t,o){return t&&o===i.soul(t)&&i.is(t,this.fn,this.as)?void(this.cb&&(n.n=t,n.as=this.as,this.cb.call(n.as,t,o,n))):!0}function n(t){t&&i.is(n.n,t,n.as)}r.is=function(n,o,e,i){return n&&s(n)&&!l(n)?!g(n,t,{cb:o,fn:e,as:i}):!1}}(),function(){function t(t,r){var u;return(u=l(t,r))?u:(r.env=t,r.soul=o,i.ify(r.obj,n,r)&&(t.graph[e.rel.is(r.rel)]=r.node),r)}function n(n,o,r){var s,l,p=this,g=p.env;if(i._===o&&c(n,e.rel._))return r._;if(s=a(n,o,r,p,g)){if(o||(p.node=p.node||r||{},c(n,i._)&&(p.node._=d(n._)),p.node=i.soul.ify(p.node,e.rel.is(p.rel)),p.rel=p.rel||e.rel.ify(i.soul(p.node))),(l=g.map)&&(l.call(g.as||{},n,o,r,p),c(r,o))){if(n=r[o],u===n)return void f(r,o);if(!(s=a(n,o,r,p,g)))return}if(!o)return p.node;if(!0===s)return n;if(l=t(g,{obj:n,path:p.path.concat(o)}),l.node)return l.rel}}function o(t){var n=this,o=e.rel.is(n.rel),r=n.env.graph;n.rel=n.rel||e.rel.ify(t),n.rel[e.rel._]=t,n.node&&n.node[i._]&&(n.node[i._][e.rel._]=t),c(r,o)&&(r[t]=r[o],f(r,o))}function a(t,n,o,i,r){var u;return e.is(t)?!0:s(t)?1:(u=r.invalid)?(t=u.call(r.as||{},t,n,o),a(t,n,o,i,r)):void(r.err="Invalid value at '"+i.path.concat(n).join(".")+"'!")}function l(t,n){for(var o,e=t.seen,i=e.length;i--;)if(o=e[i],n.obj===o.obj)return o;e.push(n)}r.ify=function(n,o,i){var r={path:[],obj:n};return o?"string"==typeof o?o={soul:o}:o instanceof Function&&(o.map=o):o={},o.soul&&(r.rel=e.rel.ify(o.soul)),o.graph=o.graph||{},o.seen=o.seen||[],o.as=o.as||i,t(o,r),o.root=r.node,o.graph}}(),r.node=function(t){var n=i.soul(t);if(n)return p({},n,t)},function(){function t(t,n){var o,u;if(i._===n){if(l(t,e.rel._))return;return void(this.obj[n]=d(t))}return(o=e.rel.is(t))?(u=this.opt.seen[o])?void(this.obj[n]=u):void(this.obj[n]=this.opt.seen[o]=r.to(this.graph,o,this.opt)):void(this.obj[n]=t)}r.to=function(n,o,e){if(n){var i={};return e=e||{seen:{}},g(n[o],t,{obj:i,graph:n,opt:e}),i}}}();var u,a=(o.fn.is,o.obj),s=a.is,f=a.del,c=a.has,l=a.empty,p=a.put,g=a.map,d=a.copy;n.exports=r})(t,"./graph"),t(function(n){function o(){this.cache={}}var e=t("./type");o.prototype.track=function(t){return this.cache[t]=e.time.is(),this.to||this.gc(),t},o.prototype.check=function(t){return e.obj.has(this.cache,t)?this.track(t):!1},o.prototype.gc=function(){var t=this,n=e.time.is(),o=n,i=3e5;e.obj.map(t.cache,function(r,u){o=Math.min(n,r),i>n-r||e.obj.del(t.cache,u)});var r=e.obj.empty(t.cache);if(r)return void(t.to=null);var u=n-o,a=i-u;t.to=setTimeout(function(){t.gc()},a)},n.exports=o})(t,"./dup"),t(function(n){function i(t){return t instanceof i?(this._={gun:this}).gun:this instanceof i?i.create(this._={gun:this,opt:t}):new i(t)}i.is=function(t){return t instanceof i},i.version=.7,i.chain=i.prototype,i.chain.toJSON=function(){};var r=t("./type");r.obj.to(r,i),i.HAM=t("./HAM"),i.val=t("./val"),i.node=t("./node"),i.state=t("./state"),i.graph=t("./graph"),i.dup=t("./dup"),i.on=t("./onify")(),i._={node:i.node._,soul:i.val.rel._,state:i.state._,field:".",value:"="},function(){function t(t){var n,o=this,e=o.as;if(t.gun||(t.gun=e.gun),t["#"]||(t["#"]=i.text.random()),!e.dup.check(t["#"])){if(t["@"]){if(e.ack(t["@"],t))return;return e.dup.track(t["#"]),void i.on("out",l(t,{gun:e.gun}))}e.dup.track(t["#"]),n=l(t,{gun:e.gun}),t.get&&i.on("get",n),t.put&&i.on("put",n),i.on("out",n)}}i.create=function(n){n.on=n.on||i.on,n.root=n.root||n.gun,n.graph=n.graph||{},n.dup=n.dup||new i.dup,n.ask=i.on.ask,n.ack=i.on.ack;var o=n.gun.opt(n.opt);return n.once||(n.on("in",t,n),n.on("out",t,n)),n.once=1,o}}(),function(){function t(t,n,o,e){var r=this,u=i.state.is(o,n);if(!u)return r.err="Error: No state on '"+n+"' in node '"+e+"'!";var a=r.graph[e]||h,s=i.state.is(a,n,!0),f=a[n],c=i.HAM(r.machine,u,s,t,f);c.incoming&&(r.put[e]=i.state.to(o,n,r.put[e]),(r.diff||(r.diff={}))[e]=i.state.to(o,n,r.diff[e]))}function n(t,n){var e=(this.gun._.next||h)[n];if(e){var r=this.at[n]={put:this.node=t,get:this.soul=n,gun:this.ref=e};p(t,o,this),i.on("node",r)}}function o(t,n){var o=this.graph,e=this.soul,r=this.ref._;o[e]=i.state.to(this.node,n,o[e]),(r.put||(r.put={}))[n]=t}function e(t){t.gun&&t.gun._.on("in",t)}i.on("put",function(o){if(!o["#"])return this.to.next(o);var r=this,u={gun:o.gun,graph:o.gun._.graph,put:{},at:{},machine:i.state()};return i.graph.is(o.put,null,t,u)||(u.err="Error: Invalid graph!"),u.err?u.gun.on("in",{"@":o["#"],err:i.log(u.err)}):(p(u.put,n,u),p(u.at,e,u),void(u.diff&&r.to.next(l(o,{put:u.diff}))))})}();!function(){i.on("get",function(t){var n,o=this,e=t.get[g],r=t.gun._,u=r.graph[e],a=t.get[d],s=r.next||(r.next={}),f=(s[e]||h)._;if(!u||!f)return o.to.next(t);if(a){if(!c(u,a))return o.to.next(t);u=i.state.to(u,a)}else u=i.obj.copy(u);u=i.graph.node(u),n=f.ack,r.on("in",{"@":t["#"],how:"mem",put:u,gun:f.gun}),n>0||o.to.next(t)})}(),function(){i.on.ask=function(t,n){if(this.on){var o=i.text.random();return t&&this.on(o,t,n),o}},i.on.ack=function(t,n){if(t&&n&&this.on){var o=t["#"]||t;if(this.tag&&this.tag[o])return this.on(o,n),!0}}}(),function(){i.chain.opt=function(t){t=t||{};var n=this,o=n._,e=t.peers||t;return f(t)||(t={}),f(o.opt)||(o.opt=t),u(e)&&(e=[e]),a(e)&&(e=p(e,function(t,n,o){o(t,{url:t})}),f(o.opt.peers)||(o.opt.peers={}),o.opt.peers=l(e,o.opt.peers)),o.opt.wsc=o.opt.wsc||{protocols:null},o.opt.peers=o.opt.peers||{},l(t,o.opt),i.on("opt",o),n}}();var u=i.text.is,a=i.list.is,s=i.obj,f=s.is,c=s.has,l=s.to,p=s.map,g=(s.copy,i._.soul),d=i._.field,h=(i.val.rel.is,{});o.debug=function(t,n){return o.debug.i&&t===o.debug.i&&o.debug.i++&&(o.log.apply(o,arguments)||n)},i.log=function(){return!i.log.off&&o.log.apply(o,arguments),[].slice.call(arguments).join(" ")},i.log.once=function(t,n,o){return(o=i.log.once)[t]=o[t]||0,o[t]++||i.log(n)},i.log.once("welcome","Hello wonderful person! :) Thanks for using GUN, feel free to ask for help on https://gitter.im/amark/gun and ask StackOverflow questions tagged with 'gun'!"),"undefined"!=typeof window&&(window.Gun=i),"undefined"!=typeof e&&(e.exports=i),n.exports=i})(t,"./root"),t(function(){var n=t("./root");n.chain.back=function(t,n){var i;if(-1===t||1/0===t)return this._.root;if(1===t)return this._.back||this;var r=this,u=r._;if("string"==typeof t&&(t=t.split(".")),t instanceof Array){var a=0,s=t.length,i=u;for(a;s>a;a++)i=(i||e)[t[a]];if(o!==i)return n?r:i;if(i=u.back)return i.back(t,n)}else if(t instanceof Function){for(var f,i={back:r};(i=i.back)&&(i=i._)&&!(f=t(i,n)););return f}};var o,e={}})(t,"./back"),t(function(){function o(t){var n,o,e,i=this.as,r=i.gun,u=r.back(-1);if(t.gun||(t.gun=r),o=t.get)if(e=o[m])e=u.get(e)._,d(o,y)?d(n=e.put,o=o[y])&&e.on("in",{get:e.get,put:c.state.to(n,o),gun:e.gun}):d(e,"put")&&e.on("in",e);else if(d(o,y)){o=o[y];var a=o?r.get(o)._:i;if(l!==a.put)return void a.on("in",a);if(d(i,"put")){var s,f=i.put;if((s=c.node.soul(f))&&(f=c.val.rel.ify(s)),s=c.val.rel.is(f)){if(!t.gun._)return;return void t.gun._.on("out",{get:e={"#":s,".":o,gun:t.gun},"#":u._.ask(c.HAM.synth,e),gun:t.gun})}if(l===f||c.val.is(f)){if(!t.gun._)return;return void t.gun._.on("in",{get:o,gun:t.gun})}}else i.map&&b(i.map,function(t){t.at.on("in",t.at)});if(i.soul){if(!t.gun._)return;return void t.gun._.on("out",{get:e={"#":i.soul,".":o,gun:t.gun},"#":u._.ask(c.HAM.synth,e),gun:t.gun})}if(i.get){if(!i.back._)return;return void i.back._.on("out",{get:h({},y,i.get),gun:r})}t=_(t,{get:{}})}else{if(d(i,"put")?i.on("in",i):i.map&&b(i.map,function(t){t.at.on("in",t.at)}),i.ack&&!d(i,"put"))return;if(i.ack=-1,i.soul)return void i.on("out",{get:e={"#":i.soul,gun:i.gun},"#":u._.ask(c.HAM.synth,e),gun:i.gun});if(i.get){if(!i.back._)return;return void i.back._.on("out",{get:h({},y,i.get),gun:i.gun})}}i.back._.on("out",t)}function e(t){t=t._||t;{var n,o=this,e=this.as,u=t.gun,f=u._,g=t.put;e.back._||p}if(0>e.ack&&!t.ack&&!c.val.rel.is(g)&&(e.ack=1),e.get&&t.get!==e.get&&(t=_(t,{get:e.get})),e.field&&f!==e&&(t=_(t,{gun:e.gun}),f.ack&&(e.ack=e.ack||f.ack)),l===g){if(o.to.next(t),e.soul)return;return r(e,t,o),e.field&&s(e,t),v(f.echo,e.id),void v(e.map,f.id)}return e.soul?(e.root._.now&&(t=_(t,{put:g=f.put})),o.to.next(t),r(e,t,o),void b(g,a,{at:t,cat:e})):(n=c.val.rel.is(g))?(i(e,t,f,n),o.to.next(t),void r(e,t,o)):c.val.is(g)?(e.field||e.soul?s(e,t):(f.field||f.soul)&&((f.echo||(f.echo={}))[e.id]=e,(e.map||(e.map={}))[f.id]=e.map[f.id]||{at:f}),o.to.next(t),void r(e,t,o)):(e.field&&f!==e&&d(f,"put")&&(e.put=f.put),(n=c.node.soul(g))&&f.field&&(f.put=e.root.get(n)._.put),o.to.next(t),r(e,t,o),i(e,t,f,n),void b(g,a,{at:t,cat:e}))}function i(t,n,o,e){if(e&&k!==t.get){var r=t.root.get(e)._;t.field?o=r:o.field&&i(o,n,o,e),o!==t&&((o.echo||(o.echo={}))[t.id]=t,t.field&&!(t.map||p)[o.id]&&s(t,n),r=(t.map||(t.map={}))[o.id]=t.map[o.id]||{at:o},e!==r.rel&&f(t,r.rel=e))}}function r(t,n,o){t.echo&&(t.field&&(n=_(n,{event:o})),b(t.echo,u,n))}function u(t){t.on("in",this)}function a(t,n){var o,e,i,r=this.cat,u=r.next||p,a=this.at;(k!==n||u[n])&&(o=u[n])&&(i=o._,i.field?(t&&t[m]&&c.val.rel.is(t)===c.node.soul(i.put)||(i.put=t),e=o):e=a.gun.get(n),i.on("in",{put:t,get:n,gun:e,via:a}))}function s(t){if(t.field||t.soul){var n=t.map;t.map=null,null!==n&&(l!==n||t.put===l)&&(b(n,function(n){(n=n.at)&&v(n.echo,t.id)}),b(t.next,function(t,n){var o=t._;o.put=l,o.ack&&(o.ack=-1),o.on("in",{get:n,gun:t,put:l})}))}}function f(t,n){var o=t.root.get(n)._;return t.ack?(o.ack=o.ack||-1,void o.on("out",{get:o={"#":n,gun:o.gun},"#":t.root._.ask(c.HAM.synth,o)})):void b(t.next,function(o,e){o._.on("out",{get:o={"#":n,".":e,gun:o},"#":t.root._.ask(c.HAM.synth,o)})})}var c=t("./root");c.chain.chain=function(){var t=this._,i=new this.constructor(this),r=i._;return r.root=n=t.root,r.id=++n._.once,r.back=this,r.on=c.on,c.on("chain",r),r.on("in",e,r),r.on("out",o,r),i},c.chain.chain.input=e;var l,p={},g=c.obj,d=g.has,h=g.put,v=g.del,_=g.to,b=g.map,m=c._.soul,y=c._.field,k=c.node._})(t,"./chain"),t(function(){function n(t,n){var o=n._,e=o.next,i=n.chain(),r=i._;return e||(e=o.next={}),e[r.get=t]=i,o.root===n?r.soul=t:(o.soul||o.field)&&(r.field=t),i}function o(t){var n,o=this,e=o.as,r=t.gun,a=r._,f=t.put;i===f&&(f=a.put),(n=f)&&n[s._]&&(n=s.is(n))&&(n=a.root.get(n)._,i!==n.put&&(t=u(t,{put:n.put}))),e.use(t,t.event||o),o.to.next(t)}var e=t("./root");e.chain.get=function(t,i,r){if("string"!=typeof t){if(t instanceof Function){var u=this,s=u._;return r=i||{},r.use=t,r.out=r.out||{cap:1},r.out.get=r.out.get||{},"_"!=s.get&&(s.root._.now=!0),s.on("in",o,r),s.on("out",r.out),s.root._.now=!1,u}return a(t)?this.get(""+t,i,r):((r=this.chain())._.err={err:e.log("Invalid get request!",t)},i&&i.call(r,r._.err),r)}var u,c,l=this,p=l._,g=p.next||f;return(u=g[t])||(u=n(t,l)),(c=p.stun)&&(u._.stun=u._.stun||c),i&&i instanceof Function&&u.get(i,r),u};var i,r=e.obj,u=(r.has,e.obj.to),a=e.num.is,s=e.val.rel,f=(e.node._,{})})(t,"./get"),t(function(){function n(t){t.batch=e;var n=t.opt||{},o=t.env=s.state.map(r,n.state);return o.soul=t.soul,t.graph=s.graph.ify(t.data,o,t),o.err?((t.ack||h).call(t,t.out={err:s.log(o.err)}),void(t.res&&t.res())):void t.batch()}function e(){var t=this;t.graph&&!g(t.stun,i)&&((t.res||v)(function(){t.ref._.on("out",{cap:3,gun:t.ref,put:t.out=t.env.graph,opt:t.opt,"#":t.gun.back(-1)._.ask(function(n){this.off(),t.ack&&t.ack(n,this)},t.opt)})},t),t.res&&t.res())}function i(t){return t?!0:void 0}function r(t,n,o,e){var i=this;!n&&e.path.length&&(i.res||v)(function(){var t=e.path,n=i.ref,o=(i.opt,0),r=t.length;for(o;r>o;o++)n=n.get(t[o]);if(i.not||s.node.soul(e.obj)){var a=s.node.soul(e.obj)||((i.opt||{}).uuid||i.gun.back("opt.uuid")||s.text.random)();return n.back(-1).get(a),void e.soul(a)}(i.stun=i.stun||{})[t]=!0,n.get("_").get(u,{as:{at:e,as:i}})},{as:i,at:e})}function u(t,n){var o=this.as,e=o.at;if(o=o.as,t.gun&&t.gun._.back){n.off(),t=t.gun._.back._;var i=s.node.soul(e.obj)||s.node.soul(t.put)||s.val.rel.is(t.put)||((o.opt||{}).uuid||o.gun.back("opt.uuid")||s.text.random)();t.gun.back(-1).get(i),e.soul(i),o.stun[e.path]=!1,o.batch()}}function a(t,n){var e=this.as;if(t.gun&&t.gun._){if(t.err)return void o.log("Please report this as an issue! Put.any.err");var i,r=t.gun._.back._,u=r.put,a=e.opt||{};if(n.off(),e.ref!==e.gun){if(i=e.gun._.get||r.get,!i)return void o.log("Please report this as an issue! Put.no.get");e.data=p({},i,e.data),i=null}if(f===u){if(!r.get)return;r.soul||(i=r.gun.back(function(t){return t.soul?t.soul:void(e.data=p({},t.get,e.data))})),i=i||r.get,r=r.root.get(i)._,e.not=e.soul=i,u=e.data}e.not||(e.soul=s.node.soul(u))||(e.soul=e.path&&l(e.data)?(a.uuid||r.root._.opt.uuid||s.text.random)():t.soul||r.soul||(a.uuid||r.root._.opt.uuid||s.text.random)()),e.ref.put(e.data,e.soul,e)}}var s=t("./root");s.chain.put=function(t,o,e){var i,r=this,u=r._,f=u.root;return e=e||{},e.data=t,e.gun=e.gun||r,"string"==typeof o?e.soul=o:e.ack=o,u.soul&&(e.soul=u.soul),e.soul||f===r?l(e.data)?(e.gun=r=f.get(e.soul=e.soul||(e.not=s.node.soul(e.data)||(f._.opt.uuid||s.text.random)())),e.ref=e.gun,n(e),r):((e.ack||h).call(e,e.out={err:s.log("Data saved to the root level of the graph must be a node (an object), not a",typeof e.data,'of "'+e.data+'"!')}),e.res&&e.res(),r):s.is(t)?(t.get(function(t,n){n.off();var i=s.node.soul(t.put);return i?void r.put(s.val.rel.ify(i),o,e):void s.log("The reference you are saving is a",typeof t.put,'"'+e.put+'", not a node (object)!')}),r):(e.ref=e.ref||f===(i=u.back)?r:i,e.ref._.soul&&s.val.is(e.data)&&u.get?(e.data=p({},u.get,e.data),e.ref.put(e.data,e.soul,e),r):(e.ref.get("_").get(a,{as:e}),e.out||(e.res=e.res||s.on.stun(e.ref),e.gun._.stun=e.ref._.stun),r))};var f,c=s.obj,l=c.is,p=c.put,g=c.map,d={},h=function(){},v=function(t,n){t.call(n||d)}})(t,"./put"),t(function(n){var e=t("./root");n.exports=e,function(){function t(t,n){if(e._.node!==n){var r=this.node,u=this.vertex,a=this.union,s=this.machine,f=d(r,n),c=d(u,n);if(i===f||i===c)return!0;var l=t,p=u[n];if(!_(l)&&i!==l)return!0;if(!_(p)&&i!==p)return!0;var g=e.HAM(s,f,c,l,p);if(g.err)return void o.log(".!HYPOTHETICAL AMNESIA MACHINE ERR!.",n,g.err);if(!(g.state||g.historical||g.current))return g.incoming?(a[n]=t,void h(a,n,f)):g.defer?(a[n]=t,void h(a,n,f)):void 0}}function n(t,n){var o=this;if(e._.node!==n&&_(t)){var i=o.node,r=o.vertex,u=d(i,n,!0),a=d(r,n,!0),s=o.delta,f=e.HAM(o.machine,u,a,t,r[n]);f.incoming&&(s[n]=t,h(s,n,u))}}e.HAM.union=function(n,o,i){return o&&o._&&(n=n||e.node.soul.ify({_:{">":{}}},e.node.soul(o)),n&&n._&&(i=a(i)?{machine:i}:{machine:e.state()},i.union=n||e.obj.copy(n),i.vertex=n,i.node=o,!l(o,t,i)))?i.union:void 0},e.HAM.delta=function(t,o,i){return i=a(i)?{machine:i}:{machine:e.state()},t?(i.soul=e.node.soul(i.vertex=t),i.soul?(i.delta=e.node.soul.ify({},i.soul),l(i.node=o,n,i),i.delta):void 0):e.obj.copy(o)},e.HAM.synth=function(t){var n=this.as,o=n.gun._;if(!t.put||n["."]&&!f(t.put[n["#"]],o.get)){if(o.put!==i)return;return void o.on("in",{get:o.get,put:o.put=i,gun:o.gun})}t.gun=o.root,e.on("put",t)},e.HAM.synth_=function(t,n,o){var r=this.as||o,u=r._,a=u.root._,s={};if(!t.put){if(u.put!==i)return;return void u.on("in",{get:u.get,put:u.put=i,gun:r,via:t})}l(t.put,function(t,n){var o=this.graph;s[n]=e.HAM.delta(o[n],t,{graph:o}),o[n]=e.HAM.union(o[n],t)||o[n]},a),t.gun!==a.gun&&(s=t.put),l(s,function(o,r){var a=this,s=a.next||(a.next={}),l=s[r]||(s[r]=a.gun.get(r)),p=l._;return p.put=a.graph[r],u.field&&!f(o,u.field)?((t=c(t,{})).put=i,void e.HAM.synth(t,n,u.gun)):void p.on("in",{put:o,get:r,gun:l,via:t})},a)}}();{var i,r=e,u=r.num,a=u.is,s=r.obj,f=s.has,c=(s.put,s.to),l=s.map,p=e.node,g=(p.soul,p.is,p.ify,e.state),d=g.is,h=g.ify,v=e.val,_=v.is;v.rel.is}})(t,"./index"),t(function(n){var o=t("./root");t("./index"),t("./opt"),t("./chain"),t("./back"),t("./put"),t("./get"),n.exports=o})(t,"./core"),t(function(){var n=t("./core");n.chain.path=function(t,o,e){var i,r=this,u=r;if(e=e||{},e.path=!0,n.log.once("pathing","Warning: `.path` to be removed from core (but available as an extension), use `.get` chains instead. If you are opposed to this, please voice your opinion in https://gitter.im/amark/gun and ask others."),u===u._.root)return o&&o({err:n.log("Can't do that on root instance.")}),u;if("string"==typeof t){if(i=t.split(e.split||"."),1===i.length)return u=r.get(t,o,e),u._.opt=e,u;t=i}if(t instanceof Array){if(t.length>1){u=r;var a=0,s=t.length;for(a;s>a;a++)u=u.get(t[a],a+1===s?o:null,e)}else u=r.get(t[0],o,e);return u._.opt=e,u}return t||0==t?(u=r.get(""+t,o,e),u._.opt=e,u):r}})(t,"./path"),t(function(){function n(t,n){var o,r=this,u=t.gun,s=u._,f=s.put||t.put,o=r.last,c=s.id+t.get;if(i!==f){if(f&&f[a._]&&(o=a.is(f))){if(o=s.root.get(o)._,i===o.put)return;f=o.put}r.change&&(f=t.put),(o.put!==f||o.get!==c||e.node.soul(f))&&(o.put=f,o.get=c,s.last=f,r.as?r.ok.call(r.as,t,n):r.ok.call(u,f,t.get,t,n))}}function o(t,n){var e,r=this.as,u=r.cat,s=t.gun,f=s._,c=f.put||t.put;if(c&&c[a._]&&(e=a.is(c))){if(e=u.root.get(e)._,i===e.put)return;c=e.put}if(n.wait&&clearTimeout(n.wait),!r.async)return void(n.wait=setTimeout(function(){o.call({as:r},t,n,n.wait||1)},r.wait||99));if(u.field||u.soul){if(n.off())return}else{if((r.seen=r.seen||{})[f.id])return;r.seen[f.id]=!0}r.ok.call(t.gun||r.gun,c,t.get)}var e=t("./core");e.chain.on=function(t,o,e,i){var r,u,a=this,f=a._;if("string"==typeof t)return o?(r=f.on(t,o,e||f,i),e&&e.gun&&(e.subs||(e.subs=[])).push(r),u=function(){r&&r.off&&r.off(),u.off()},u.off=a.off.bind(a)||s,a.off=u,a):f.on(t);var c=o;return c=!0===c?{change:!0}:c||{},c.ok=t,c.last={},a.get(n,c),a},e.chain.val=function(t,n){var r=this,u=r._,a=u.put;if(0=a?n():void(o||(clearTimeout(o),o=setTimeout(n,1e3)))}),Gun.on("get",function(t){this.to.next(t);var n,o,i,u,a=t.gun,s=t.get;if((i=t.opt||{}).prefix=i.prefix||t.gun.back("opt.prefix")||"gun/",s&&(n=s[Gun._.soul])){var f=s["."];o=Gun.obj.ify(e.getItem(i.prefix+n)||null)||r[n]||u,o&&f&&(o=Gun.state.to(o,f)),(o||Gun.obj.empty(a.back("opt.peers")))&&a.on("in",{"@":t["#"],put:Gun.graph.node(o),how:"lS"})}})}})(t,"./adapters/localStorage"),t(function(){function n(t){var n=a,o=this,i=t.wire||e(t,o);return o.wsp&&o.wsp.count++,i?i.readyState===i.OPEN?void i.send(n):void(t.queue=t.queue||[]).push(n):void 0}function o(t,n,e){if(e&&t){try{t=JSON.parse(t.data||t)}catch(i){}if(t instanceof Array)for(var r,u=0;r=t[u++];)o(r,n,e);else e.wsp&&1===e.wsp.count&&((t.body||t).wsp=f),e.gun.on("in",t.body||t)}}function e(t,e){if(t&&t.url){var s=t.url.replace("http","ws"),f=t.wire=new u(s,e.opt.wsc.protocols,e.opt.wsc);return f.onclose=function(){i(t,e)},f.onerror=function(n){i(t,e),n&&"ECONNREFUSED"===n.code},f.onopen=function(){var o=t.queue;t.queue=[],r.obj.map(o,function(o){a=o,n.call(e,t)})},f.onmessage=function(n){o(n,t,e)},f}}function i(t,n){clearTimeout(t.defer),t.defer=setTimeout(function(){e(t,n)},2e3)}var r=t("./core");if("undefined"==typeof JSON)throw new Error("Gun depends on JSON. Please load it first:\najax.cdnjs.com/ajax/libs/json2/20110223/json2.js");var u;if("undefined"!=typeof window){u=window.WebSocket||window.webkitWebSocket||window.mozWebSocket;var a,s,f=function(){};r.on("out",function(t){this.to.next(t);var o=t.gun._.root._,e=o.wsp||(o.wsp={});if(!t.wsp||1!==e.count){if(a=JSON.stringify(t),o.udrain)return void o.udrain.push(a);o.udrain=[],clearTimeout(s),s=setTimeout(function(){if(o.udrain){var t=o.udrain;o.udrain=null,t.length&&(a=JSON.stringify(t),r.obj.map(o.opt.peers,n,o))}},1),e.count=0,r.obj.map(o.opt.peers,n,o)}})}})(t,"./polyfill/request")}(); \ No newline at end of file diff --git a/lib/file.js b/lib/file.js index 24a0a459f..69fc57b3a 100644 --- a/lib/file.js +++ b/lib/file.js @@ -15,9 +15,10 @@ Gun.on('put', function(at){ var f = at.gun.back('opt._file') if(!f.use){ return } var graph = at.put, opt = at.opt || {}; - var Graph = f.gun._.graph - Gun.obj.map(graph, function(node, soul){ - f.disk.graph[soul] = Graph[soul] || graph[soul]; + var Graph = f.gun._.graph; + var dg = f.disk.graph; + Gun.graph.is(graph, null, function(val, key, node, soul){ + dg[soul] = Gun.state.to(node, key, dg[soul]); }); f.count = (f.count || 0) + 1; if(!at['@']){ // don't ack other acks! diff --git a/package.json b/package.json index eac649f97..3ed967dc3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gun", - "version": "0.7.2", + "version": "0.7.3", "description": "Graph engine", "main": "index.js", "browser": "gun.min.js", diff --git a/src/HAM.js b/src/HAM.js index 90aa82c9a..d143981ba 100644 --- a/src/HAM.js +++ b/src/HAM.js @@ -13,7 +13,9 @@ function HAM(machineState, incomingState, currentState, incomingValue, currentVa } if(incomingState === currentState){ - if(Lexical(incomingValue) === Lexical(currentValue)){ // Note: while these are practically the same, the deltas could be technically different + incomingValue = Lexical(incomingValue) || ""; + currentValue = Lexical(currentValue) || ""; + if(incomingValue === currentValue){ // Note: while these are practically the same, the deltas could be technically different return {state: true}; } /* @@ -24,10 +26,10 @@ function HAM(machineState, incomingState, currentState, incomingValue, currentVa because convergence (data integrity) is generally more important. Any difference in this algorithm must be given a new and different name. */ - if(Lexical(incomingValue) < Lexical(currentValue)){ // Lexical only works on simple value types! + if(incomingValue < currentValue){ // Lexical only works on simple value types! return {converge: true, current: true}; } - if(Lexical(currentValue) < Lexical(incomingValue)){ // Lexical only works on simple value types! + if(currentValue < incomingValue){ // Lexical only works on simple value types! return {converge: true, incoming: true}; } } diff --git a/src/adapters/localStorage.js b/src/adapters/localStorage.js index ad3e0b749..3a2723f8d 100644 --- a/src/adapters/localStorage.js +++ b/src/adapters/localStorage.js @@ -11,9 +11,8 @@ Gun.on('put', function(at){ var err, id, opt, root = at.gun._.root; this.to.next(at); (opt = {}).prefix = (at.opt || opt).prefix || at.gun.back('opt.prefix') || 'gun/'; var graph = root._.graph; - Gun.obj.map(at.put, function(node, soul){ - async[soul] = graph[soul] || node; + async[soul] = async[soul] || graph[soul] || node; }); count += 1; check[at['#']] = root; @@ -28,7 +27,7 @@ Gun.on('put', function(at){ var err, id, opt, root = at.gun._.root; Gun.obj.map(all, function(node, soul){ // Since localStorage only has 5MB, it is better that we keep only // the data that the user is currently interested in. - node = graph[soul] || all[soul]; + node = graph[soul] || all[soul] || node; try{store.setItem(opt.prefix + soul, JSON.stringify(node)); }catch(e){ err = e || "localStorage failure" } }); @@ -56,10 +55,9 @@ Gun.on('get', function(at){ if(!lex || !(soul = lex[Gun._.soul])){ return } //if(0 >= at.cap){ return } var field = lex['.']; - data = Gun.obj.ify(store.getItem(opt.prefix + soul) || null) || async[soul] || u; if(data && field){ - data = Gun.state.ify(u, field, Gun.state.is(data, field), data[field], soul); + data = Gun.state.to(data, field); } if(!data && !Gun.obj.empty(gun.back('opt.peers'))){ // if data not found, don't ack if there are peers. return; // Hmm, what if we have peers but we are disconnected? diff --git a/src/chain.js b/src/chain.js index 46a28ba27..d385db4dd 100644 --- a/src/chain.js +++ b/src/chain.js @@ -17,13 +17,24 @@ function output(at){ at.gun = gun; } if(get = at.get){ - if(!get[_soul]){ + if(tmp = get[_soul]){ + tmp = (root.get(tmp)._); + if(obj_has(get, _field)){ + if(obj_has(put = tmp.put, get = get[_field])){ + tmp.on('in', {get: tmp.get, put: Gun.state.to(put, get), gun: tmp.gun}); // TODO: Ugly, clean up? Simplify all these if conditions (without ruining the whole chaining API)? + } + } else + if(obj_has(tmp, 'put')){ + //if(u !== tmp.put){ + tmp.on('in', tmp); + } + } else { if(obj_has(get, _field)){ get = get[_field]; var next = get? (gun.get(get)._) : cat; // TODO: BUG! Handle plural chains by iterating over them. - if(obj_has(next, 'put')){ // potentially incorrect? Maybe? - //if(u !== next.put){ // potentially incorrect? Maybe? + //if(obj_has(next, 'put')){ // potentially incorrect? Maybe? + if(u !== next.put){ // potentially incorrect? Maybe? //next.tag['in'].last.next(next); next.on('in', next); return; @@ -37,8 +48,8 @@ function output(at){ if(rel = Gun.val.rel.is(val)){ if(!at.gun._){ return } (at.gun._).on('out', { - get: {'#': rel, '.': get}, - '#': root._.ask(Gun.HAM.synth, at.gun), + get: tmp = {'#': rel, '.': get, gun: at.gun}, + '#': root._.ask(Gun.HAM.synth, tmp), gun: at.gun }); return; @@ -56,12 +67,12 @@ function output(at){ obj_map(cat.map, function(proxy){ proxy.at.on('in', proxy.at); }); - } + }; if(cat.soul){ if(!at.gun._){ return } (at.gun._).on('out', { - get: {'#': cat.soul, '.': get}, - '#': root._.ask(Gun.HAM.synth, at.gun), + get: tmp = {'#': cat.soul, '.': get, gun: at.gun}, + '#': root._.ask(Gun.HAM.synth, tmp), gun: at.gun }); return; @@ -87,14 +98,15 @@ function output(at){ } if(cat.ack){ if(!obj_has(cat, 'put')){ // u !== cat.put instead? + //if(u !== cat.put){ return; } } cat.ack = -1; if(cat.soul){ cat.on('out', { - get: {'#': cat.soul}, - '#': root._.ask(Gun.HAM.synth, cat.gun), + get: tmp = {'#': cat.soul, gun: cat.gun}, + '#': root._.ask(Gun.HAM.synth, tmp), gun: cat.gun }); return; @@ -115,7 +127,7 @@ function output(at){ function input(at){ at = at._ || at; var ev = this, cat = this.as, gun = at.gun, coat = gun._, change = at.put, back = cat.back._ || empty, rel, tmp; - if(0 > cat.ack && !Gun.val.rel.is(change)){ // for better behavior? + if(0 > cat.ack && !at.ack && !Gun.val.rel.is(change)){ // for better behavior? cat.ack = 1; } if(cat.get && at.get !== cat.get){ @@ -191,9 +203,8 @@ function relate(cat, at, coat, rel){ not(cat, at); } tmp = (cat.map || (cat.map = {}))[coat.id] = cat.map[coat.id] || {at: coat}; - if(rel !== tmp.rel){ - ask(cat, tmp.rel = rel); - } + if(rel === tmp.rel){ return } + ask(cat, tmp.rel = rel); } function echo(cat, at, ev){ if(!cat.echo){ return } // || node_ === at.get ???? @@ -256,17 +267,15 @@ function ask(cat, soul){ if(cat.ack){ tmp.ack = tmp.ack || -1; tmp.on('out', { - get: {'#': soul}, - '#': cat.root._.ask(Gun.HAM.synth, tmp.gun), - gun: tmp.gun + get: tmp = {'#': soul, gun: tmp.gun}, + '#': cat.root._.ask(Gun.HAM.synth, tmp) }); return; } obj_map(cat.next, function(gun, key){ (gun._).on('out', { - get: {'#': soul, '.': key}, - '#': cat.root._.ask(Gun.HAM.synth, tmp.gun), - gun: gun + get: gun = {'#': soul, '.': key, gun: gun}, + '#': cat.root._.ask(Gun.HAM.synth, gun) }); }); } diff --git a/src/graph.js b/src/graph.js index a78c991da..94e8db0ce 100644 --- a/src/graph.js +++ b/src/graph.js @@ -8,8 +8,8 @@ var Graph = {}; if(!g || !obj_is(g) || obj_empty(g)){ return false } // must be an object. return !obj_map(g, map, {cb:cb,fn:fn,as:as}); // makes sure it wasn't an empty object. } - function map(n, s){ // we invert this because the way we check for this is via a negation. - if(!n || s !== Node.soul(n) || !Node.is(n, this.fn)){ return true } // it is true that this is an invalid graph. + function map(n, s){ // we invert this because the way'? we check for this is via a negation. + if(!n || s !== Node.soul(n) || !Node.is(n, this.fn, this.as)){ return true } // it is true that this is an invalid graph. if(!this.cb){ return } nf.n = n; nf.as = this.as; // sequential race conditions aren't races. this.cb.call(nf.as, n, s, nf); diff --git a/src/index.js b/src/index.js index bac204294..87e1fef17 100644 --- a/src/index.js +++ b/src/index.js @@ -101,7 +101,21 @@ module.exports = Gun; state_ify(delta, field, is); } } - Gun.HAM.synth = function(at, ev, as){ var gun = this.as || as; + Gun.HAM.synth = function(at, ev){ + var as = this.as, cat = as.gun._; + if(!at.put || (as['.'] && !obj_has(at.put[as['#']], cat.get))){ + if(cat.put !== u){ return } + cat.on('in', { + get: cat.get, + put: cat.put = u, + gun: cat.gun, + }) + return; + } + at.gun = cat.root; + Gun.on('put', at); + } + Gun.HAM.synth_ = function(at, ev, as){ var gun = this.as || as; var cat = gun._, root = cat.root._, put = {}, tmp; if(!at.put){ //if(obj_has(cat, 'put')){ return } diff --git a/src/key.js b/src/key.js deleted file mode 100644 index 6f3662d24..000000000 --- a/src/key.js +++ /dev/null @@ -1,166 +0,0 @@ - -var Gun = require('./core'); -var obj = Gun.obj, obj_is = obj.is, obj_put = obj.put, obj_map = obj.map, obj_empty = obj.empty; -var num = Gun.num, num_is = num.is; -var _soul = Gun.val.rel._, _field = '.'; - - -;(function(){ - Gun.chain.key = function(index, cb, opt){ - if(!index){ - if(cb){ - cb.call(this, {err: Gun.log('No key!')}); - } - return this; - } - var gun = this; - if(typeof opt === 'string'){ - console.log("Please report this as an issue! key.opt.string"); - return gun; - } - if(gun === gun._.root){if(cb){cb({err: Gun.log("Can't do that on root instance.")})};return gun} - opt = opt || {}; - opt.key = index; - opt.any = cb || function(){}; - opt.ref = gun.back(-1).get(opt.key); - opt.gun = opt.gun || gun; - gun.on(key, {as: opt}); - if(!opt.data){ - opt.res = Gun.on.stun(opt.ref); - } - return gun; - } - function key(at, ev){ var opt = this; - ev.off(); - opt.soul = Gun.node.soul(at.put); - if(!opt.soul || opt.key === opt.soul){ return opt.data = {} } - opt.data = obj_put({}, keyed._, Gun.node.ify(obj_put({}, opt.soul, Gun.val.rel.ify(opt.soul)), '#'+opt.key+'#')); - (opt.res||iffe)(function(){ - opt.ref.put(opt.data, opt.any, {soul: opt.key, key: opt.key}); - },opt); - if(opt.res){ - opt.res(); - } - } - function iffe(fn,as){fn.call(as||{})} - function keyed(f){ - if(!f || !('#' === f[0] && '#' === f[f.length-1])){ return } - var s = f.slice(1,-1); - if(!s){ return } - return s; - } - keyed._ = '##'; - Gun.on('next', function(at){ - var gun = at.gun; - if(gun.back(-1) !== at.back){ return } - gun.on('in', pseudo, gun._); - gun.on('out', normalize, gun._); - }); - function normalize(at){ var cat = this; - if(!at.put){ - if(at.get){ - search.call(at.gun? at.gun._ : cat, at); - } - return; - } - if(at.opt && at.opt.key){ return } - var put = at.put, graph = cat.gun.back(-1)._.graph; - Gun.graph.is(put, function(node, soul){ - if(!Gun.node.is(graph['#'+soul+'#'], function each(rel,id){ - if(id !== Gun.val.rel.is(rel)){ return } - if(rel = graph['#'+id+'#']){ - Gun.node.is(rel, each); // correct params? - return; - } - Gun.node.soul.ify(rel = put[id] = Gun.obj.copy(node), id); - })){ return } - Gun.obj.del(put, soul); - }); - } - function search(at){ var cat = this; - var tmp; - if(!Gun.obj.is(tmp = at.get)){ return } - if(!Gun.obj.has(tmp, '#')){ return } - if((tmp = at.get) && (null === tmp['.'])){ - tmp['.'] = '##'; - return; - } - if((tmp = at.get) && Gun.obj.has(tmp, '.')){ - if(tmp['#']){ - cat = cat.root.gun.get(tmp['#'])._; - } - tmp = at['#']; - at['#'] = Gun.on.ask(proxy); - } - var tried = {}; - function proxy(ack, ev){ - var put = ack.put, lex = at.get; - if(!cat.pseudo || ack.via){ // TODO: BUG! MEMORY PERF! What about unsubscribing? - //ev.off(); - //ack.via = ack.via || {}; - return Gun.on.ack(tmp, ack); - } - if(ack.put){ - if(!lex['.']){ - ev.off(); - return Gun.on.ack(tmp, ack); - } - if(obj_has(ack.put[lex['#']], lex['.'])){ - ev.off(); - return Gun.on.ack(tmp, ack); - } - } - Gun.obj.map(cat.seen, function(ref,id){ // TODO: BUG! In-memory versus future? - if(tried[id]){ - return Gun.on.ack(tmp, ack); - } - tried[id] = true; - ref.on('out', { - gun: ref, - get: id = {'#': id, '.': at.get['.']}, - '#': Gun.on.ask(proxy) - }); - }); - } - } - function pseudo(at, ev){ var cat = this; - // TODO: BUG! Pseudo can't handle plurals!? - if(cat.pseudo){ - //ev.stun();return; - if(cat.pseudo === at.put){ return } - ev.stun(); - cat.change = cat.changed || cat.pseudo; - cat.on('in', Gun.obj.to(at, {put: cat.put = cat.pseudo})); - return; - } - if(!at.put){ return } - var rel = Gun.val.rel.is(at.put[keyed._]); - if(!rel){ return } - var soul = Gun.node.soul(at.put), resume = ev.stun(resume), root = cat.gun.back(-1), seen = cat.seen = {}; - cat.pseudo = cat.put = Gun.state.ify(Gun.node.ify({}, soul)); - root.get(rel).on(each, {change: true}); - function each(change){ - Gun.node.is(change, map); - } - function map(rel, soul){ - if(soul !== Gun.val.rel.is(rel)){ return } - if(seen[soul]){ return } - seen[soul] = root.get(soul).on(on, true); - } - function on(put){ - if(!put){ return } - cat.pseudo = Gun.HAM.union(cat.pseudo, put) || cat.pseudo; - cat.change = cat.changed = put; - cat.put = cat.pseudo; - resume({ - gun: cat.gun, - put: cat.pseudo, - get: soul - //via: this.at - }); - } - } - var obj = Gun.obj, obj_has = obj.has; -}()); - - \ No newline at end of file diff --git a/src/node.js b/src/node.js index 3168d1254..36febdfe4 100644 --- a/src/node.js +++ b/src/node.js @@ -10,6 +10,7 @@ Node.soul.ify = function(n, o){ // put a soul on an object. n._[soul_] = o.soul || n._[soul_] || text_random(); // put the soul on it. return n; } +Node.soul._ = Val.rel._; ;(function(){ Node.is = function(n, cb, as){ var s; // checks to see if an object is a valid node. if(!obj_is(n)){ return false } // must be an object. @@ -51,7 +52,7 @@ Node.soul.ify = function(n, o){ // put a soul on an object. }()); var obj = Type.obj, obj_is = obj.is, obj_del = obj.del, obj_map = obj.map; var text = Type.text, text_random = text.random; -var soul_ = Val.rel._; +var soul_ = Node.soul._; var u; module.exports = Node; \ No newline at end of file diff --git a/src/not.js b/src/not.js index 416e1f8d2..3a488dc10 100644 --- a/src/not.js +++ b/src/not.js @@ -1,6 +1,7 @@ var Gun = require('./core'), u; Gun.chain.not = function(cb, opt, t){ + Gun.log.once("nottobe", "Warning: `.not` to be removed from core (but available as an extension), use `.val` instead, which now supports (v0.7.x+) 'not found data' as `undefined` data in callbacks. If you are opposed to this, please voice your opinion in https://gitter.im/amark/gun and ask others."); return this.get(ought, {not: cb}); } function ought(at, ev){ ev.off(); diff --git a/src/path.js b/src/path.js index ae2b1c5ee..ea45d95a7 100644 --- a/src/path.js +++ b/src/path.js @@ -3,6 +3,7 @@ var Gun = require('./core'); Gun.chain.path = function(field, cb, opt){ var back = this, gun = back, tmp; opt = opt || {}; opt.path = true; + Gun.log.once("pathing", "Warning: `.path` to be removed from core (but available as an extension), use `.get` chains instead. If you are opposed to this, please voice your opinion in https://gitter.im/amark/gun and ask others."); if(gun === gun._.root){if(cb){cb({err: Gun.log("Can't do that on root instance.")})}return gun} if(typeof field === 'string'){ tmp = field.split(opt.split || '.'); diff --git a/src/put.js b/src/put.js index 4187105c4..7e1be7413 100644 --- a/src/put.js +++ b/src/put.js @@ -87,7 +87,9 @@ function map(v,f,n, at){ var as = this; ref = ref.get(path[i]); } if(as.not || Gun.node.soul(at.obj)){ - at.soul(Gun.node.soul(at.obj) || ((as.opt||{}).uuid || as.gun.back('opt.uuid') || Gun.text.random)()); + var id = Gun.node.soul(at.obj) || ((as.opt||{}).uuid || as.gun.back('opt.uuid') || Gun.text.random)(); + ref.back(-1).get(id); + at.soul(id); return; } (as.stun = as.stun || {})[path] = true; @@ -100,7 +102,9 @@ function soul(at, ev){ var as = this.as, cat = as.at; as = as.as; if(!at.gun || !at.gun._.back){ return } // TODO: Handle ev.off(); at = (at.gun._.back._); - cat.soul(Gun.node.soul(cat.obj) || Gun.node.soul(at.put) || Gun.val.rel.is(at.put) || ((as.opt||{}).uuid || as.gun.back('opt.uuid') || Gun.text.random)()); // TODO: BUG!? Do we really want the soul of the object given to us? Could that be dangerous? + var id = Gun.node.soul(cat.obj) || Gun.node.soul(at.put) || Gun.val.rel.is(at.put) || ((as.opt||{}).uuid || as.gun.back('opt.uuid') || Gun.text.random)(); // TODO: BUG!? Do we really want the soul of the object given to us? Could that be dangerous? + at.gun.back(-1).get(id); + cat.soul(id); as.stun[cat.path] = false; as.batch(); } diff --git a/src/root.js b/src/root.js index a1cad3848..9ba2c38fd 100644 --- a/src/root.js +++ b/src/root.js @@ -51,39 +51,84 @@ Gun._ = { // some reserved key words, these are not the only ones. //console.log("add to.next(at)"); // TODO: BUG!!! var ev = this, cat = ev.as, coat; if(!at.gun){ at.gun = cat.gun } - if(!at['#'] && at['@']){ - at['#'] = Gun.text.random(); // TODO: Use what is used other places instead. - // TODO: BUG! For multi-instances, the "ack" system is globally shared, but it shouldn't be. + if(!at['#']){ at['#'] = Gun.text.random() } // TODO: Use what is used other places instead. + if(cat.dup.check(at['#'])){ return } + if(at['@']){ + // TODO: BUG! For multi-instances, the "ack" system is globally shared, but it shouldn't be. if(cat.ack(at['@'], at)){ return } // TODO: Consider not returning here, maybe, where this would let the "handshake" on sync occur for Holy Grail? cat.dup.track(at['#']); Gun.on('out', obj_to(at, {gun: cat.gun})); return; } - if(at['#'] && cat.dup.check(at['#'])){ return } cat.dup.track(at['#']); - if(cat.ack(at['@'], at)){ return } + //if(cat.ack(at['@'], at)){ return } //cat.ack(at['@'], at); coat = obj_to(at, {gun: cat.gun}); if(at.get){ - if(!get(at, cat)){ - Gun.on('get', coat); - } + //Gun.on.GET(coat); + Gun.on('get', coat); } if(at.put){ - Gun.HAM.synth(at, ev, cat.gun); // TODO: Clean up, just make it part of on('put')! + //Gun.on.PUT(coat); Gun.on('put', coat); } Gun.on('out', coat); } - 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 } +}()); + +;(function(){ + Gun.on('put', function(at){ + //Gun.on.PUT = function(at){ + if(!at['#']){ return this.to.next(at) } // for tests. + var ev = this, ctx = {gun: at.gun, graph: at.gun._.graph, put: {}, at: {}, machine: Gun.state()}; + if(!Gun.graph.is(at.put, null, verify, ctx)){ ctx.err = "Error: Invalid graph!" } + if(ctx.err){ return ctx.gun.on('in', {'@': at['#'], err: Gun.log(ctx.err) }) } + obj_map(ctx.put, merge, ctx); + obj_map(ctx.at, map, ctx); + if(!ctx.diff){ return } + ev.to.next(obj_to(at, {put: ctx.diff})); + }); + function verify(val, key, node, soul){ var ctx = this; + var state = Gun.state.is(node, key), tmp; + if(!state){ return ctx.err = "Error: No state on '"+key+"' in node '"+soul+"'!" } + var vertex = ctx.graph[soul] || empty, was = Gun.state.is(vertex, key, true), known = vertex[key]; + var HAM = Gun.HAM(ctx.machine, state, was, val, known); + if(!HAM.incoming){ return } + ctx.put[soul] = Gun.state.to(node, key, ctx.put[soul]); + (ctx.diff || (ctx.diff = {}))[soul] = Gun.state.to(node, key, ctx.diff[soul]); // TODO: Bug? If val is a relation, it is an object and therefore passed by reference. Will this be a problem? + } + function merge(node, soul){ + var ref = ((this.gun._).next || empty)[soul]; + if(!ref){ return } + var at = this.at[soul] = { + put: this.node = node, + get: this.soul = soul, + gun: this.ref = ref + }; + obj_map(node, each, this); + Gun.on('node', at); + } + function each(val, key){ + var graph = this.graph, soul = this.soul, cat = (this.ref._), tmp; + graph[soul] = Gun.state.to(this.node, key, graph[soul]); + (cat.put || (cat.put = {}))[key] = val; + } + function map(at, soul){ + if(!at.gun){ return } + (at.gun._).on('in', at); + } +}()); +var tmpev = {to:{next:function(){}}}; // temporary while we have to switch event hooks. +;(function(){ + Gun.on('get', function(at){ + var ev = this, soul = at.get[_soul], cat = at.gun._, node = cat.graph[soul], field = at.get[_field], tmp; + var next = cat.next || (cat.next = {}), as = ((next[soul] || empty)._); + if(!node || !as){ return ev.to.next(at) } if(field){ - if(!obj_has(node, field)){ return } - tmp = Gun.obj.put(Gun.node.soul.ify({}, soul), field, node[field]); - node = Gun.state.ify(tmp, field, Gun.state.is(node, field)); + if(!obj_has(node, field)){ return ev.to.next(at) } + node = Gun.state.to(node, field); + } else { + node = Gun.obj.copy(node); } //if(at.gun === cat.gun){ node = Gun.graph.node(node); // TODO: BUG! Clone node? @@ -98,9 +143,10 @@ Gun._ = { // some reserved key words, these are not the only ones. gun: as.gun }); if(0 < tmp){ - return true; + return; } - } + ev.to.next(at); + }); }()); ;(function(){ @@ -143,9 +189,9 @@ Gun._ = { // some reserved key words, these are not the only ones. var text_is = Gun.text.is; var list_is = Gun.list.is; -var obj = Gun.obj, obj_is = obj.is, obj_has = obj.has, obj_to = obj.to, obj_map = obj.map; -var _soul = Gun._.soul, _field = Gun._.field; -//var u; +var obj = Gun.obj, obj_is = obj.is, obj_has = obj.has, obj_to = obj.to, obj_map = obj.map, obj_copy = obj.copy; +var _soul = Gun._.soul, _field = Gun._.field, rel_is = Gun.val.rel.is; +var empty = {}, u; console.debug = function(i, s){ return (console.debug.i && i === console.debug.i && console.debug.i++) && (console.log.apply(console, arguments) || s) }; diff --git a/src/state.js b/src/state.js index f90ee850f..883e9add5 100644 --- a/src/state.js +++ b/src/state.js @@ -17,6 +17,11 @@ var time = Type.time.is, last = -Infinity, N = 0, D = 1000; // WARNING! In the f var perf = (typeof performance !== 'undefined')? (performance.timing && performance) : false, start = (perf && perf.timing && perf.timing.navigationStart) || (perf = false); State._ = '>'; State.drift = 0; +State.is = function(n, f, o){ // convenience function to get the state on a field on a node and return it. + var tmp = (f && n && n[N_] && n[N_][State._]) || o; + if(!tmp){ return } + return num_is(tmp = tmp[f])? tmp : -Infinity; +} State.ify = function(n, f, s, v, soul){ // put a field's state on a node. if(!n || !n[N_]){ // reject if it is not node-like. if(!soul){ // unless they passed a soul @@ -35,10 +40,12 @@ State.ify = function(n, f, s, v, soul){ // put a field's state on a node. } return n; } -State.is = function(n, f, o){ // convenience function to get the state on a field on a node and return it. - var tmp = (f && n && n[N_] && n[N_][State._]) || o; - if(!tmp){ return } - return num_is(tmp[f])? tmp[f] : -Infinity; +State.to = function(from, f, to){ + var val = from[f]; + if(obj_is(val)){ + val = obj_copy(val); + } + return State.ify(to, f, State.is(from, f), val, Node.soul(from)); } ;(function(){ State.map = function(cb, s, as){ var u; // for use with Node.ify @@ -67,7 +74,7 @@ State.is = function(n, f, o){ // convenience function to get the state on a fiel State.ify(this.o, f, this.s) ; } }()); -var obj = Type.obj, obj_as = obj.as, obj_has = obj.has, obj_is = obj.is, obj_map = obj.map; +var obj = Type.obj, obj_as = obj.as, obj_has = obj.has, obj_is = obj.is, obj_map = obj.map, obj_copy = obj.copy; var num = Type.num, num_is = num.is; var fn = Type.fn, fn_is = fn.is; var N_ = Node._, u; diff --git a/test/common.js b/test/common.js index ba5b0f824..0df08caa3 100644 --- a/test/common.js +++ b/test/common.js @@ -2,6 +2,7 @@ var root; (function(env){ root = env.window? env.window : global; env.window && root.localStorage && root.localStorage.clear(); + try{ require('fs').unlinkSync('data.json') }catch(e){} //root.Gun = root.Gun || require('../gun'); if(root.Gun){ root.Gun = root.Gun; @@ -3008,7 +3009,7 @@ describe('Gun', function(){ var gun = Gun(); gun.get('val/follow').val(function(data){ - //console.log("val"); + //console.log("val", data); }).get(function(at){ if(done.c){ return } done.c = 1; done(); @@ -3022,7 +3023,6 @@ describe('Gun', function(){ var check = {}, count = {}; gun.map().val(function(v,f){ - //console.log("***********", f,v); check[f] = v; count[f] = (count[f] || 0) + 1; if(check['1_1'] && check['2_2']){ @@ -3134,15 +3134,18 @@ describe('Gun', function(){ ); setTimeout(function(){ gun.get(function(at){ + //console.log('*', at.put); done.app = done.app || at.put.alias; }); gun.back(-1).get('pub').get(function(at){ + //console.log("**", at.put); done.pub = done.pub || at.put.auth; }); gun.path('alias').get(function(at){ + //console.log("***", at.put); done.alias = done.alias || at.put.mark; }).path('mark').get(function(at){ - //console.log("************", at.put); + //console.log("************", at.put);return; setTimeout(function(){ done.mark = done.mark || at.put.pub; expect(Gun.val.rel.is(done.mark)).to.be('pub'); @@ -3469,7 +3472,6 @@ describe('Gun', function(){ try{ require('fs').unlinkSync('bdata') }catch(e){} try{ require('fs').unlinkSync('ddata') }catch(e){} Gun.on('out', function(msg){ - //console.log("oye", msg); this.to.next(msg); var onGun = msg.gun.back(-1); if(onGun === b) { @@ -3492,7 +3494,6 @@ describe('Gun', function(){ d = Gun({file: "ddata"}); var db = d.get("key"); db.map().on(function(val,field){ - //console.log("d key got val:", field, val) expect(val).to.be('hello'); if(done.c){ return } done.c = 1; setTimeout(function(){ @@ -3526,6 +3527,22 @@ describe('Gun', function(){ } }); }); + + it('Callbacks should have database safe data copies', function(done){ + var gun = Gun(); + + gun.get('ds/safe').put({a: 1}); + + gun.get('ds/safe').on(function(data){ + data.b = 2; + }); + + gun.get('ds/safe').val(function(data){ + expect(gun._.root._.graph['ds/safe'].b).to.not.be.ok(); + if(done.c){ return } done.c = 1; + done(); + }); + }); return; it.only('Custom extensions are chainable', function(done){ Gun.chain.filter = function(filter){