diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d4acd93..32474079 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # CHANGELOG +## 0.5.9 + +GUN 0.3 -> 0.4 -> 0.5 Migration Guide: +`gun.back` -> `gun.back()`; +`gun.get(key, cb)` -> cb(err, data) -> cb(at) at.err, at.put; +`gun.map(cb)` -> `gun.map().on(cb)`; +`gun.init` -> deprecated; +`gun.put(data, cb)` -> cb(err, ok) -> cb(ack) ack.err, ack.ok; +`gun.get(key)` global/absolute -> `gun.back(-1).get(key)`; +`gun.key(key)` -> temporarily broken; + ## 0.3.7 - Catch localStorage errors. diff --git a/gun.js b/gun.js index 6936b930..c7c6fc44 100644 --- a/gun.js +++ b/gun.js @@ -82,7 +82,7 @@ delete o[k]; return o; } - Type.obj.as = function(o, f, v){ return o[f] = o[f] || (arguments.length >= 3? v : {}) } + Type.obj.as = function(o, f, v, u){ return o[f] = o[f] || (u === v? {} : v) } Type.obj.ify = function(o){ if(obj_is(o)){ return o } try{o = JSON.parse(o); @@ -182,6 +182,7 @@ if(this === this.the.last){ this.the.last = this.back; } + this.to.back = this.back; this.next = onto._.next; this.back.to = this.to; }), @@ -191,8 +192,7 @@ on: this, as: as, }; - (be.back = tag.last || - (tag.to = be) && tag).to = be; + (be.back = tag.last || tag).to = be; return tag.last = be; } (tag = tag.to).next(arg); @@ -441,13 +441,12 @@ var Type = require('./type'); var Val = {}; Val.is = function(v){ // Valid values are a subset of JSON: null, binary, number (!Infinity), text, or a soul relation. Arrays need special algorithms to handle concurrency, so they are not supported directly. Use an extension that supports them if needed but research their problems first. - var u; if(v === u){ return false } if(v === null){ return true } // "deletes", nulling out fields. if(v === Infinity){ return false } // we want this to be, but JSON does not support it, sad face. - if(bi_is(v) // by "binary" we mean boolean. - || num_is(v) - || text_is(v)){ // by "text" we mean strings. + if(text_is(v) // by "text" we mean strings. + || bi_is(v) // by "binary" we mean boolean. + || num_is(v)){ // by "number" we mean integers or decimals. return true; // simple values are valid. } return Val.rel.is(v) || false; // is the value a soul relation? Then it is valid and return it. If not, everything else remaining is an invalid data type. Custom extensions can be built on top of these primitives to support other types. @@ -455,7 +454,7 @@ Val.rel = {_: '#'}; ;(function(){ Val.rel.is = function(v){ // this defines whether an object is a soul relation or not, they look like this: {'#': 'UUID'} - if(v && !v._ && obj_is(v)){ // must be an object. + if(v && v[rel_] && !v._ && obj_is(v)){ // must be an object. var o = {}; obj_map(v, map, o); if(o.id){ // a valid id was found. @@ -466,15 +465,15 @@ } function map(s, f){ var o = this; // map over the object... if(o.id){ return o.id = false } // if ID is already defined AND we're still looping through the object, it is considered invalid. - if(f == _rel && text_is(s)){ // the field should be '#' and have a text value. + if(f == rel_ && text_is(s)){ // the field should be '#' and have a text value. o.id = s; // we found the soul! } else { return o.id = false; // if there exists anything else on the object that isn't the soul, then it is considered invalid. } } }()); - Val.rel.ify = function(t){ return obj_put({}, _rel, t) } // convert a soul into a relation and return it. - var _rel = Val.rel._; + Val.rel.ify = function(t){ return obj_put({}, rel_, t) } // convert a soul into a relation and return it. + var rel_ = Val.rel._, u; var bi_is = Type.bi.is; var num_is = Type.num.is; var text_is = Type.text.is; @@ -486,26 +485,26 @@ var Type = require('./type'); var Val = require('./val'); var Node = {_: '_'}; - Node.soul = function(n, o){ return (n && n._ && n._[o || _soul]) } // convenience function to check to see if there is a soul on a node and return it. + Node.soul = function(n, o){ return (n && n._ && n._[o || soul_]) } // convenience function to check to see if there is a soul on a node and return it. Node.soul.ify = function(n, o){ // put a soul on an object. o = (typeof o === 'string')? {soul: o} : o || {}; n = n || {}; // make sure it exists. n._ = n._ || {}; // make sure meta exists. - n._[_soul] = o.soul || n._[_soul] || text_random(); // put the soul on it. + n._[soul_] = o.soul || n._[soul_] || text_random(); // put the soul on it. return n; } ;(function(){ - Node.is = function(n, cb, o){ var s; // checks to see if an object is a valid node. + 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. if(s = Node.soul(n)){ // must have a soul on it. - return !obj_map(n, map, {o:o,cb:cb,s:s,n:n}); + return !obj_map(n, map, {as:as,cb:cb,s:s,n:n}); } return false; // nope! This was not a valid node. } function map(v, f){ // we invert this because the way we check for this is via a negation. if(f === Node._){ return } // skip over the metadata. if(!Val.is(v)){ return true } // it is true that this is an invalid node. - if(this.cb){ this.cb.call(this.o, v, f, this.s, this.n) } // optionally callback each field/value. + if(this.cb){ this.cb.call(this.as, v, f, this.n, this.s) } // optionally callback each field/value. } }()); ;(function(){ @@ -515,11 +514,11 @@ else if(o instanceof Function){ o = {map: o} } if(o.map){ o.node = o.map.call(as, obj, u, o.node || {}) } if(o.node = Node.soul.ify(o.node || {}, o)){ - obj_map(obj, map, {opt:o,as:as}); + obj_map(obj, map, {o:o,as:as}); } return o.node; // This will only be a valid node if the object wasn't already deep! } - function map(v, f){ var o = this.opt, tmp, u; // iterate over each field/value. + function map(v, f){ var o = this.o, tmp, u; // iterate over each field/value. if(o.map){ tmp = o.map.call(this.as, v, ''+f, o.node); if(u === tmp){ @@ -535,7 +534,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_ = Val.rel._; var u; module.exports = Node; })(require, './node'); @@ -546,17 +545,28 @@ function State(){ var t = time(); if(last < t){ - n = 0; - return last = t; + return N = 0, last = t; } return last = t + ((N += 1) / D); } var time = Type.time.is, last = -Infinity, N = 0, D = 1000; // WARNING! In the future, on machines that are D times faster than 2016AD machines, you will want to increase D by another several orders of magnitude so the processing speed never out paces the decimal resolution (increasing an integer effects the state accuracy). State._ = '>'; - State.ify = function(n, f, s){ // put a field's state on a node. - if(!n || !n[N_]){ return } // reject if it is not node-like. + 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 + return; + } + n = Node.soul.ify(n, soul); // then make it so! + } var tmp = obj_as(n[N_], State._); // grab the states data. - if(u !== f && num_is(s)){ tmp[f] = s } // add the valid state. + if(u !== f && f !== N_){ + if(num_is(s)){ + tmp[f] = s; // add the valid state. + } + if(u !== v){ // Note: Not its job to check for valid values! + n[f] = v; + } + } return n; } State.is = function(n, f, o){ // convenience function to get the state on a field on a node and return it. @@ -606,17 +616,17 @@ ;(function(){ Graph.is = function(g, cb, fn, as){ // checks to see if an object is a valid graph. if(!g || !obj_is(g) || obj_empty(g)){ return false } // must be an object. - return !obj_map(g, map, {fn:fn,cb:cb,as:as}); // makes sure it wasn't an empty object. - } - function nf(fn){ // optional callback for each node. - if(fn){ Node.is(nf.n, fn, nf.as) } // where we then have an optional callback for each field/value. + 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. - if(!fn_is(this.cb)){ return } - nf.n = n; nf.as = this.as; + 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); } + function nf(fn){ // optional callback for each node. + if(fn){ Node.is(nf.n, fn, nf.as) } // where we then have an optional callback for each field/value. + } }()); ;(function(){ Graph.ify = function(obj, env, as){ @@ -750,7 +760,6 @@ module.exports = Graph; })(require, './graph'); - ;require(function(module){ var Type = require('./type'); function Dup(){ @@ -937,7 +946,7 @@ Gun.log = function(){ return (!Gun.log.off && console.log.apply(console, arguments)), [].slice.call(arguments).join(' ') } Gun.log.once = function(w,s,o){ return (o = Gun.log.once)[w] = o[w] || 0, o[w]++ || Gun.log(s) } - Gun.log.once("migrate", "GUN 0.3 -> 0.4 -> 0.5 Migration Guide:\n`gun.back` -> `gun.back()`;\n`gun.get(key, cb)` -> cb(err, data) -> cb(at) at.err, at.put;\n`gun.map(cb)` -> `gun.map().on(cb)`;\n`gun.init` -> deprecated;\n`gun.put(data, cb)` -> cb(err, ok) -> cb(ack) ack.err, ack.ok;\n`gun.get(key)` global/absolute -> `gun.back(-1).get(key)`;\n`gun.key(key)` -> temporarily broken;\nand don't chain off of `gun.val()`;\nCheers, jump on https://gitter.im/amark/gun for help and StackOverflow 'gun' tag for questions!") + Gun.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'!"); if(typeof window !== "undefined"){ window.Gun = Gun } if(typeof common !== "undefined"){ common.exports = Gun } module.exports = Gun; @@ -1061,8 +1070,7 @@ if(obj_has(cat, 'put')){ //if(u !== cat.put){ cat.on('in', cat); - //cat.on('in').last.emit(cat); - } else// TODO: BUG! Handle plural chains by iterating over them. + } else if(cat.map){ obj_map(cat.map, function(proxy){ proxy.at.on('in', proxy.at); @@ -1699,7 +1707,7 @@ 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); + Gun.node.is(rel, each); // correct params? return; } Gun.node.soul.ify(rel = put[id] = Gun.obj.copy(node), id); @@ -1898,6 +1906,13 @@ opt.cat = at; gun.get(val, {as: opt}); opt.async = at.stun? 1 : true; + } else { + Gun.log.once("valonce", "Chainable val is experimental, its behavior and API may change moving forward. Please play with it and report bugs and ideas on how to improve it."); + var chain = gun.chain(); + chain._.val = gun.val(function(){ + chain._.on('in', gun._); + }); + return chain; } return gun; } @@ -1974,18 +1989,30 @@ ;require(function(module){ var Gun = require('./core'); Gun.chain.map = function(cb, opt, t){ - var gun = this, cat = gun._, chain = cat.fields; - //cb = cb || function(){ return this } // TODO: API BREAKING CHANGE! 0.5 Will behave more like other people's usage of `map` where the passed callback is a transform function. By default though, if no callback is specified then it will use a transform function that returns the same thing it received. - if(chain){ return chain } - chain = cat.fields = gun.chain(); - gun.on('in', map, chain._); - if(cb){ - chain.on(cb); + var gun = this, cat = gun._, chain; + if(!cb){ + if(chain = cat.fields){ return chain } + chain = cat.fields = gun.chain(); + chain._.val = gun.back('val'); + gun.on('in', map, chain._); + return chain; } + Gun.log.once("mapfn", "Map functions are experimental, their behavior and API may change moving forward. Please play with it and report bugs and ideas on how to improve it."); + chain = gun.chain(); + gun.map().on(function(data, key, at, ev){ + var next = (cb||noop).call(this, data, key, at, ev); + if(u === next){ return } + if(Gun.is(next)){ + chain._.on('in', next._); + return; + } + chain._.on('in', {get: key, put: next, gun: chain}); + }); return chain; } function map(at){ if(!at.put || Gun.val.is(at.put)){ return } + if(this.as.val){ this.off() } obj_map(at.put, each, {cat: this.as, gun: at.gun}); this.to.next(at); } @@ -1994,7 +2021,7 @@ var cat = this.cat, gun = this.gun.get(f), at = (gun._); (at.echo || (at.echo = {}))[cat.id] = cat; } - var obj_map = Gun.obj.map, noop = function(){}, event = {stun: noop, off: noop}, n_ = Gun.node._; + var obj_map = Gun.obj.map, noop = function(){}, event = {stun: noop, off: noop}, n_ = Gun.node._, u; })(require, './map'); ;require(function(module){ @@ -2026,44 +2053,49 @@ ;require(function(module){ if(typeof Gun === 'undefined'){ return } // TODO: localStorage is Browser only. But it would be nice if it could somehow plugin into NodeJS compatible localStorage APIs? - var root, noop = function(){}; + var root, noop = function(){}, u; if(typeof window !== 'undefined'){ root = window } var store = root.localStorage || {setItem: noop, removeItem: noop, getItem: noop}; - function put(at){ var err, id, opt, root = at.gun._.root; + 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/'; - Gun.graph.is(at.put, function(node, soul){ - //try{store.setItem(opt.prefix + soul, Gun.text.ify(node)); - // TODO: BUG! PERF! Biggest slowdown is because of localStorage stringifying larger and larger nodes! - try{store.setItem(opt.prefix + soul, Gun.text.ify(root._.graph[soul]||node)); + Gun.graph.is(at.put, function(node, soul, map){ + var keys = Gun.obj.ify(store.getItem(opt.prefix + soul+'_')||{}); + map(function(val, key){ + keys[key] = 1; + var state = Gun.state.is(node, key); + // #soul.field=val>state + try{store.setItem(opt.prefix + soul+key, JSON.stringify([val,state])); + }catch(e){ err = e || "localStorage failure" } + }); + try{store.setItem(opt.prefix + soul+'_', JSON.stringify(keys)); }catch(e){ err = e || "localStorage failure" } }); - //console.log('@@@@@@@@@@local put!'); if(Gun.obj.empty(at.gun.back('opt.peers'))){ Gun.on.ack(at, {err: err, ok: 0}); // only ack if there are no peers. } - } - function get(at){ + }); + Gun.on('get', function(at){ this.to.next(at); var gun = at.gun, lex = at.get, soul, data, opt, u; //setTimeout(function(){ (opt = at.opt || {}).prefix = opt.prefix || at.gun.back('opt.prefix') || 'gun/'; if(!lex || !(soul = lex[Gun._.soul])){ return } - data = Gun.obj.ify(store.getItem(opt.prefix + soul) || null); - if(!data){ // localStorage isn't trustworthy to say "not found". - if(Gun.obj.empty(gun.back('opt.peers'))){ - gun.back(-1).on('in', {'@': at['#']}); + var field = lex['.']; + if(field){ + if(data = Gun.obj.ify(store.getItem(opt.prefix + soul+field)||null)||u){ + data = Gun.state.ify(u, field, data[1], data[0], soul); } - return; + } else { + Gun.obj.map(Gun.obj.ify(store.getItem(opt.prefix + soul+'_')), function(v,field){ + v = Gun.obj.ify(store.getItem(opt.prefix + soul+field)||{}); + data = Gun.state.ify(data, field, v[1], v[0], soul); + }); } - if(Gun.obj.has(lex, '.')){var tmp = data[lex['.']];data = {_: data._};if(u !== tmp){data[lex['.']] = tmp}} - //console.log('@@@@@@@@@@@@local get', data, at); gun.back(-1).on('in', {'@': at['#'], put: Gun.graph.node(data)}); //},11); - } - Gun.on('put', put); - Gun.on('get', get); + }); })(require, './adapters/localStorage'); ;require(function(module){ diff --git a/gun.min.js b/gun.min.js index 6c75ddf6..246ed606 100644 --- a/gun.min.js +++ b/gun.min.js @@ -1,3 +1,2 @@ -!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 o;"undefined"!=typeof window&&(o=window),"undefined"!=typeof global&&(o=global),o=o||{};var e=o.console||{log:function(){}};if("undefined"!=typeof module)var i=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){return t[n]=t[n]||(arguments.length>=3?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,h,g=0,v=o(s);if(t.r=null,i&&r(a)&&(d=Object.keys(a),h=!0),e(a)||d)for(l=(d||a).length;l>g;g++){var b=g+n.list.index;if(v){if(p=h?s.call(f||this,a[d[g]],d[g],t):s.call(f||this,a[g],b,t),p!==c)return p}else if(s===a[h?d[g]:g])return d?d[g]:b}else for(g in a)if(v){if(u(a,g)&&(p=f?s.call(f,a[g],g,t):s(a[g],g,t),p!==c))return p}else if(s===a[g])return g;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.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).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)a?(n=0,a=t):a=t+(s+=1)/f}var i=t("./type"),r=t("./node"),u=i.time.is,a=-(1/0),s=0,f=1e3;e._=">",e.ify=function(t,n,o){if(t&&t[m]){var i=p(t[m],e._);return c!==n&&b(o)&&(i[n]=o),t}},e.is=function(t,n,o){var i=n&&t&&t[m]&&t[m][e._]||o;if(i)return b(i[n])?i[n]:-(1/0)},function(){function t(t,n){m!==n&&e.ify(this.o,n,this.s)}e.map=function(n,o,i){var r,u=h(u=n||o)?u:null;return n=k(n=n||o)?n:null,u&&!n?(o=b(o)?o:e(),u[m]=u[m]||{},g(u,t,{o:u,s:o}),u):(i=i||h(o)?o:r,o=b(o)?o:e(),function(e,u,a,s){return n?(n.call(i||this||{},e,u,a,s),void(d(a,u)&&r===a[u]||t.call({o:a,s:o},e,u))):(t.call({o:a,s:o},e,u),e)})}}();var c,l=i.obj,p=l.as,d=l.has,h=l.is,g=l.map,v=i.num,b=v.is,y=i.fn,k=y.is,m=r._;o.exports=e})(t,"./state"),t(function(n){var o=t("./type"),e=t("./val"),i=t("./node"),r={};!function(){function t(n){n&&i.is(t.n,n,t.as)}function n(n,o){return n&&o===i.soul(n)&&i.is(n,this.fn)?void(a(this.cb)&&(t.n=n,t.as=this.as,this.cb.call(t.as,n,o,t))):!0}r.is=function(t,o,e,i){return t&&f(t)&&!p(t)?!h(t,n,{fn:e,cb:o,as:i}):!1}}(),function(){function t(t,r){var u;return(u=s(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,f,p=this,d=p.env;if(i._===o&&l(n,e.rel._))return r._;if(s=a(n,o,r,p,d)){if(o||(p.node=p.node||r||{},l(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))),(f=d.map)&&(f.call(d.as||{},n,o,r,p),l(r,o))){if(n=r[o],u===n)return void c(r,o);if(!(s=a(n,o,r,p,d)))return}if(!o)return p.node;if(!0===s)return n;if(f=t(d,{obj:n,path:p.path.concat(o)}),f.node)return f.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),l(r,o)&&(r[t]=r[o],c(r,o))}function a(t,n,o,i,r){var u;return e.is(t)?!0:f(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 s(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 d({},n,t)},function(){function t(t,n){var o,u;if(i._===n){if(p(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:{}},h(n[o],t,{obj:i,graph:n,opt:e}),i}}}();var u,a=o.fn.is,s=o.obj,f=s.is,c=s.del,l=s.has,p=s.empty,d=s.put,h=s.map,g=s.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 o(t){return t instanceof o?(this._={gun:this}).gun:this instanceof o?o.create(this._={gun:this,opt:t}):new o(t)}o.is=function(t){return t instanceof o},o.version=.5,o.chain=o.prototype,o.chain.toJSON=function(){};var r=t("./type");r.obj.to(r,o),o.HAM=t("./HAM"),o.val=t("./val"),o.node=t("./node"),o.state=t("./state"),o.graph=t("./graph"),o.dup=t("./dup"),o.on=t("./onify")(),o._={node:o.node._,soul:o.val.rel._,state:o.state._,field:".",value:"="},function(){function t(t){var e=this.as,i=e.gun;t.get&&n(t,e)||(e.on("in",l(t,{gun:e.gun})),t["#"]&&e.dup.track(t["#"]),t.gun||(t=l(t,{gun:i})),o.on("out",t))}function n(t,n){var e,i=t.get[d],r=n.graph[i],u=t.get[h],a=n.next||(n.next={}),s=(a[i]||(a[i]=n.gun.get(i)))._;if(r){if(u){if(!c(r,u))return;e=o.obj.put(o.node.soul.ify({},i),u,r[u]),r=o.state.ify(e,u,o.state.is(r,u))}return s.on("in",{put:r,get:s.soul,gun:s.gun}),0 0.4 -> 0.5 Migration Guide:\n`gun.back` -> `gun.back()`;\n`gun.get(key, cb)` -> cb(err, data) -> cb(at) at.err, at.put;\n`gun.map(cb)` -> `gun.map().on(cb)`;\n`gun.init` -> deprecated;\n`gun.put(data, cb)` -> cb(err, ok) -> cb(ack) ack.err, ack.ok;\n`gun.get(key)` global/absolute -> `gun.back(-1).get(key)`;\n`gun.key(key)` -> temporarily broken;\nand don't chain off of `gun.val()`;\nCheers, jump on https://gitter.im/amark/gun for help and StackOverflow 'gun' tag for questions!"),"undefined"!=typeof window&&(window.Gun=o),"undefined"!=typeof i&&(i.exports=o),n.exports=o})(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 n(t){{var n,o=this.as,e=o.gun;e.back(-1)}if(t.gun||(t.gun=e),(n=t.get)&&!n[k])if(h(n,m)){n=n[m];var i=n?e.get(n)._:o;if(h(i,"put"))return void i.on("in",i);if(h(o,"put")){var r,u=o.put;if((r=c.node.soul(u))&&(u=c.val.rel.ify(r)),r=c.val.rel.is(u)){if(!t.gun._)return;return void t.gun._.on("out",{get:{"#":r,".":n},"#":c.on.ask(c.HAM.synth,t.gun),gun:t.gun})}if(l===u||c.val.is(u)){if(!t.gun._)return;return void t.gun._.on("in",{get:n,gun:t.gun})}}else o.map&&y(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},"#":c.on.ask(c.HAM.synth,t.gun),gun:t.gun})}if(o.get){if(!o.back._)return;return void o.back._.on("out",{get:g({},m,o.get),gun:e})}t=b(t,{get:{}})}else{if(h(o,"put")?o.on("in",o):o.map&&y(o.map,function(t){t.at.on("in",t.at)}),o.ack&&!h(o,"put"))return;if(o.ack=-1,o.soul)return void o.on("out",{get:{"#":o.soul},"#":c.on.ask(c.HAM.synth,o.gun)});if(o.get){if(!o.back._)return;return void o.back._.on("out",{get:g({},m,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&&t.via&&!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?(o.to.next(t),r(e,t,o),void y(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&&h(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 y(d,a,{at:t,cat:e}))}function i(t,n,o,e){if(e&&_!==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})),y(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;(_!==n||u[n])&&(o=u[n])&&(i=o._,i.field?(t&&t[k]&&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)&&(y(n,function(n){(n=n.at)&&v(n.echo,t.id)}),y(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},"#":c.on.ask(c.HAM.synth,o.gun),gun:o.gun})):void y(t.next,function(t,e){t._.on("out",{get:{"#":n,".":e},"#":c.on.ask(c.HAM.synth,o.gun),gun:t})})}var c=t("./root");c.chain.chain=function(){var t=this._,i=new this.constructor(this),r=i._;return r.root=o=t.root,r.id=++o._.once,r.back=this,r.on=c.on,c.on("chain",r),r.on("in",e,r),r.on("out",n,r),i},c.chain.chain.input=e;var l,p={},d=c.obj,h=d.has,g=d.put,v=d.del,b=d.to,y=d.map,k=c._.soul,m=c._.field,_=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||{},r.out.get=r.out.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=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=o;var n=t.opt||{},e=t.env=s.state.map(r,n.state);return e.soul=t.soul,t.graph=s.graph.ify(t.data,e,t),e.err?((t.ack||g).call(n.as||t.gun,t.out={err:s.log(e.err)}),void(t.res&&t.res())):void t.batch()}function o(){var t=this;t.graph&&!d(t.stun,i)&&((t.res||v)(function(){t.ref._.on("out",{gun:t.ref,put:t.out=t.env.graph,opt:t.opt,"#":s.on.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 o=this.as;if(t.gun&&t.gun._){if(t.err)return void e.log("Please report this as an issue! Put.any.err");var i,r=t.gun._.back._,u=r.put,a=o.opt||{};if(n.off(),o.ref!==o.gun){if(i=o.gun._.get,!i)return void e.log("Please report this as an issue! Put.no.get");o.data=p({},i,o.data),i=null}if(f===u){if(!r.get)return;r.soul||(i=r.gun.back(function(t){return t.soul?t.soul:void(o.data=p({},t.get,o.data))})),i=i||r.get,r=r.root.get(i)._,o.not=o.soul=i,u=o.data}o.not||(o.soul=s.node.soul(u))||(o.soul=o.path&&l(o.data)?(a.uuid||o.gun.back("opt.uuid")||s.text.random)():t.soul),o.ref.put(o.data,o.soul,o)}}var s=t("./root");s.chain.put=function(t,o,e){var i,r=this,u=r._.root;return e=e||{},e.data=t,e.gun=e.gun||r,"string"==typeof o?e.soul=o:e.ack=o,e.soul||u===r?l(e.data)?(e.gun=r=u.get(e.soul=e.soul||(e.not=s.node.soul(e.data)||(u._.opt.uuid||s.text.random)())),e.ref=e.gun,n(e),r):((opt.any||g).call(opt.as||r,e.out={err:s.log("No field to put",typeof e.data,'"'+e.data+'" on!')}),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("Can only save a node, not a property.")}),r):(e.ref=e.ref||u===(i=r._.back)?r:i,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,h={},g=function(){},v=function(t,n){t.call(n||h)}})(t,"./put"),t(function(n){var o=t("./root");n.exports=o,function(){function t(t,n){if(o._.node!==n){var r=this.node,u=this.vertex,a=this.union,s=this.machine,f=h(r,n),c=h(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=o.HAM(s,f,c,l,p);if(d.err)return void e.log(".!HYPOTHETICAL AMNESIA MACHINE ERR!.",d.err);if(!(d.state||d.historical||d.current))return d.incoming?(a[n]=t,void g(a,n,f)):d.defer?(a[n]=t,void g(a,n,f)):void 0}}function n(t,n){var e=this;if(o._.node!==n&&b(t)){var i=e.node,r=e.vertex,u=h(i,n,!0),a=h(r,n,!0),s=e.delta,f=o.HAM(e.machine,u,a,t,r[n]);f.incoming&&(s[n]=t,g(s,n,u))}}o.HAM.union=function(n,e,i){return e&&e._&&(n=n||o.node.soul.ify({_:{">":{}}},o.node.soul(e)),n&&n._&&(i=a(i)?{machine:i}:{machine:o.state()},i.union=n||o.obj.copy(n),i.vertex=n,i.node=e,!l(e,t,i)))?i.union:void 0},o.HAM.delta=function(t,e,i){return i=a(i)?{machine:i}:{machine:o.state()},t?(i.soul=o.node.soul(i.vertex=t),i.soul?(i.delta=o.node.soul.ify({},i.soul),l(i.node=e,n,i),i.delta):void 0):o.obj.copy(e)},o.HAM.synth=function(t,n,e){var r=this.as||e,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 e=this.graph;s[n]=o.HAM.delta(e[n],t,{graph:e}),e[n]=o.HAM.union(e[n],t)||e[n]},a),l(s,function(e,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(e,u.field)?((t=c(t,{})).put=i,void o.HAM.synth(t,n,u.gun)):void p.on("in",{put:e,get:r,gun:l,via:t})},a)}}();{var i,r=o,u=r.num,a=u.is,s=r.obj,f=s.has,c=(s.put,s.to),l=s.map,p=o.node,d=(p.soul,p.is,p.ify,o.state),h=d.is,g=d.ify,v=o.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"),o=n.obj,i=(o.is,o.put),r=(o.map,o.empty,n.num);r.is,n.val.rel._}!function(){function t(t,e){var u=this;return e.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||o)(function(){u.ref.put(u.data,u.any,{soul:u.key,key:u.key})},u),void(u.res&&u.res())):u.data={}}function o(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(o,i,r){if(!o)return i&&i.call(this,{err:n.log("No key!")}),this;var u=this;return"string"==typeof r?(e.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=o,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[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,e){var r,u=this.as,s=u.cat,f=t.gun,c=f._,l=c.put||t.put;if(i!==l){if(l[a._]&&(r=a.is(l))){if(r=s.root.get(r)._,i===r.put)return;l=r.put}if(n.wait&&clearTimeout(n.wait),!(e||0o&&(n=o),t.time=n},scheduleReconnect:function(){var t=this,n=this.backoff.time;this.nextBackoff(),setTimeout(function(){t.connect(),t.ready(function(){t.resetBackoff()})},n)},isClosed:function(){var t=this.socket;if(!t)return!0;var n=t.readyState;return n===t.CLOSING||n===t.CLOSED?!0:!1},ready:function(t){var n=this.socket,o=n.readyState;return o===n.OPEN?void t():void(o===n.CONNECTING&&n.addEventListener("open",t))},send:function(t){if(this.isClosed())return this.queue.push(t),this.connect(),!1;var n=this.socket;return this.ready(function(){n.send(t)}),!0}},"undefined"!=typeof window&&(o.WebSocket=window.WebSocket||window.webkitWebSocket||window.mozWebSocket||null),o.isSupported=!!o.WebSocket,o.isSupported&&(o.formatURL=function(t){return t.replace("http","ws")},o.broadcast=function(t,n){var e=o.pool;n.headers=n.headers||{},i.obj.map(t,function(t,r){var u=o.formatURL(r),a=e[u],s={headers:i.obj.to(n.headers,{"gun-sid":a.sid}),body:n.body},f=i.text.ify(s);a.send(f)})},o.pool={},"undefined"!=typeof window&&window.addEventListener("unload",function(){i.obj.map(o.pool,function(t){t.isClosed()||t.socket.close()})}),i.on("opt",function(t){this.to.next(t);var n=t.gun,e=n.back("opt.peers")||{};i.obj.map(e,function(t,e){var r=o.formatURL(e);if(!o.pool.hasOwnProperty(r)){var u=new o(r,t.backoff,n.back("opt.wsc")||{protocols:null});o.pool[r]=u,u.on("message",function(t){var o;try{o=i.obj.ify(t.data)}catch(e){return}o&&o.body&&n.on("in",o.body)})}})}),i.on("out",function(t){this.to.next(t);var n=t.gun,o=n.back("opt.peers")||{},r=n.back("opt.headers")||{};i.obj.empty(o)||e(o,{body:t,headers:r})}),e.jsonp=function(t,n){e.jsonp.ify(t,function(o){o&&e.jsonp.send(o,function(o,i){n(o,i),e.jsonp.poll(t,i); - -},t.jsonp)})},e.jsonp.send=function(t,n,o){var e=document.createElement("script");return e.src=t,e.onerror=function(){(window[e.id]||function(){})(null,{err:"JSONP failed!"})},window[e.id=o]=function(t,o){n(o,t),n.id=e.id,e.parentNode.removeChild(e),delete window[n.id]},e.async=!0,document.getElementsByTagName("head")[0].appendChild(e),e},e.jsonp.poll=function(t,n){if(t&&t.base&&n&&n.headers&&n.headers.poll){var o=e.jsonp.poll.s=e.jsonp.poll.s||{};o[t.base]=o[t.base]||setTimeout(function(){var n={base:t.base,headers:{pull:1}};e.each(t.headers,function(t,o){n.headers[o]=t}),e.jsonp(n,function(n,i){delete o[t.base];for(var r=i.body||[];r.length&&r.shift;){var u=i.body.shift();u&&u.body&&e.createServer.ing(u,function(){e(t.base,null,null,u)})}})},n.headers.poll)}},e.jsonp.ify=function(t,n){var o=encodeURIComponent,i="?";if(t.url&&t.url.pathname&&(i=t.url.pathname+i),i=t.base+i,e.each((t.url||{}).query,function(t,n){i+=o(n)+"="+o(t)+"&"}),t.headers&&(i+=o("`")+"="+o(JSON.stringify(t.headers))+"&"),e.jsonp.maxc)return n();for(;u;)n(i+a(s,s+=c,f)+u.slice(0,s)),u=u.slice(s)}else n(i)},e.jsonp.max=2e3,e.each=function(t,n,o){if(t&&n)for(var e in t)t.hasOwnProperty(e)&&n.call(o,t[e],e)},n.exports=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,d,h,g=0,v=o(s);if(t.r=null,i&&r(a)&&(d=Object.keys(a),h=!0),e(a)||d)for(l=(d||a).length;l>g;g++){var b=g+n.list.index;if(v){if(p=h?s.call(f||this,a[d[g]],d[g],t):s.call(f||this,a[g],b,t),p!==c)return p}else if(s===a[h?d[g]:g])return d?d[g]:b}else for(g in a)if(v){if(u(a,g)&&(p=f?s.call(f,a[g],g,t):s(a[g],g,t),p!==c))return p}else if(s===a[g])return g;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):u=t+(a+=1)/s}var e=t("./type"),i=t("./node"),r=e.time.is,u=-(1/0),a=0,s=1e3;o._=">",o.ify=function(t,n,e,r,u){if(!t||!t[m]){if(!u)return;t=i.soul.ify(t,u)}var a=l(t[m],o._);return f!==n&&n!==m&&(v(e)&&(a[n]=e),f!==r&&(t[n]=r)),t},o.is=function(t,n,e){var i=n&&t&&t[m]&&t[m][o._]||e;if(i)return v(i[n])?i[n]:-(1/0)},function(){function t(t,n){m!==n&&o.ify(this.o,n,this.s)}o.map=function(n,e,i){var r,u=d(u=n||e)?u:null;return n=y(n=n||e)?n:null,u&&!n?(e=v(e)?e:o(),u[m]=u[m]||{},h(u,t,{o:u,s:e}),u):(i=i||d(e)?e:r,e=v(e)?e:o(),function(o,u,a,s){return n?(n.call(i||this||{},o,u,a,s),void(p(a,u)&&r===a[u]||t.call({o:a,s:e},o,u))):(t.call({o:a,s:e},o,u),o)})}}();var f,c=e.obj,l=c.as,p=c.has,d=c.is,h=c.map,g=e.num,v=g.is,b=e.fn,y=b.is,m=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._=h(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]=h(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,h=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=.5,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=this.as,e=o.gun;t.get&&n(t,o)||(o.on("in",l(t,{gun:o.gun})),t["#"]&&o.dup.track(t["#"]),t.gun||(t=l(t,{gun:e})),i.on("out",t))}function n(t,n){var o,e=t.get[d],r=n.graph[e],u=t.get[h],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 s.on("in",{put:r,get:s.soul,gun:s.gun}),0 0.4 -> 0.5 Migration Guide:\n`gun.back` -> `gun.back()`;\n`gun.get(key, cb)` -> cb(err, data) -> cb(at) at.err, at.put;\n`gun.map(cb)` -> `gun.map().on(cb)`;\n`gun.init` -> deprecated;\n`gun.put(data, cb)` -> cb(err, ok) -> cb(ack) ack.err, ack.ok;\n`gun.get(key)` global/absolute -> `gun.back(-1).get(key)`;\n`gun.key(key)` -> temporarily broken;\nand don't chain off of `gun.val()`;\nCheers, jump on https://gitter.im/amark/gun for help and StackOverflow 'gun' tag for questions!"),"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;e.back(-1)}if(t.gun||(t.gun=e),(n=t.get)&&!n[m])if(h(n,k)){n=n[k];var i=n?e.get(n)._:o;if(h(i,"put"))return void i.on("in",i);if(h(o,"put")){var r,u=o.put;if((r=c.node.soul(u))&&(u=c.val.rel.ify(r)),r=c.val.rel.is(u)){if(!t.gun._)return;return void t.gun._.on("out",{get:{"#":r,".":n},"#":c.on.ask(c.HAM.synth,t.gun),gun:t.gun})}if(l===u||c.val.is(u)){if(!t.gun._)return;return void t.gun._.on("in",{get:n,gun:t.gun})}}else o.map&&y(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},"#":c.on.ask(c.HAM.synth,t.gun),gun:t.gun})}if(o.get){if(!o.back._)return;return void o.back._.on("out",{get:g({},k,o.get),gun:e})}t=b(t,{get:{}})}else{if(h(o,"put")?o.on("in",o):o.map&&y(o.map,function(t){t.at.on("in",t.at)}),o.ack&&!h(o,"put"))return;if(o.ack=-1,o.soul)return void o.on("out",{get:{"#":o.soul},"#":c.on.ask(c.HAM.synth,o.gun)});if(o.get){if(!o.back._)return;return void o.back._.on("out",{get:g({},k,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&&t.via&&!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?(o.to.next(t),r(e,t,o),void y(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&&h(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 y(d,a,{at:t,cat:e}))}function i(t,n,o,e){if(e&&_!==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})),y(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;(_!==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)&&(y(n,function(n){(n=n.at)&&v(n.echo,t.id)}),y(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},"#":c.on.ask(c.HAM.synth,o.gun),gun:o.gun})):void y(t.next,function(t,e){t._.on("out",{get:{"#":n,".":e},"#":c.on.ask(c.HAM.synth,o.gun),gun:t})})}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,h=d.has,g=d.put,v=d.del,b=d.to,y=d.map,m=c._.soul,k=c._.field,_=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||{},r.out.get=r.out.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=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||g).call(n.as||t.gun,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",{gun:t.ref,put:t.out=t.env.graph,opt:t.opt,"#":s.on.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,!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||e.gun.back("opt.uuid")||s.text.random)():t.soul),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._.root;return e=e||{},e.data=t,e.gun=e.gun||r,"string"==typeof o?e.soul=o:e.ack=o,e.soul||u===r?l(e.data)?(e.gun=r=u.get(e.soul=e.soul||(e.not=s.node.soul(e.data)||(u._.opt.uuid||s.text.random)())),e.ref=e.gun,n(e),r):((opt.any||g).call(opt.as||r,e.out={err:s.log("No field to put",typeof e.data,'"'+e.data+'" on!')}),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("Can only save a node, not a property.")}),r):(e.ref=e.ref||u===(i=r._.back)?r:i,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,h={},g=function(){},v=function(t,n){t.call(n||h)}})(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=h(r,n),c=h(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!.",d.err);if(!(d.state||d.historical||d.current))return d.incoming?(a[n]=t,void g(a,n,f)):d.defer?(a[n]=t,void g(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=h(i,n,!0),a=h(r,n,!0),s=o.delta,f=e.HAM(o.machine,u,a,t,r[n]);f.incoming&&(s[n]=t,g(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),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),h=d.is,g=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[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,e){var r,u=this.as,s=u.cat,f=t.gun,c=f._,l=c.put||t.put;if(i!==l){if(l[a._]&&(r=a.is(l))){if(r=s.root.get(r)._,i===r.put)return;l=r.put}if(n.wait&&clearTimeout(n.wait),!(e||0o&&(n=o),t.time=n},scheduleReconnect:function(){var t=this,n=this.backoff.time;this.nextBackoff(),setTimeout(function(){t.connect(),t.ready(function(){t.resetBackoff()})},n)},isClosed:function(){var t=this.socket;if(!t)return!0;var n=t.readyState;return n===t.CLOSING||n===t.CLOSED?!0:!1},ready:function(t){var n=this.socket,o=n.readyState;return o===n.OPEN?void t():void(o===n.CONNECTING&&n.addEventListener("open",t))},send:function(t){if(this.isClosed())return this.queue.push(t),this.connect(),!1;var n=this.socket;return this.ready(function(){n.send(t)}),!0}},"undefined"!=typeof window&&(o.WebSocket=window.WebSocket||window.webkitWebSocket||window.mozWebSocket||null),o.isSupported=!!o.WebSocket,o.isSupported&&(o.formatURL=function(t){return t.replace("http","ws")},o.broadcast=function(t,n){ +var e=o.pool;n.headers=n.headers||{},i.obj.map(t,function(t,r){var u=o.formatURL(r),a=e[u],s={headers:i.obj.to(n.headers,{"gun-sid":a.sid}),body:n.body},f=i.text.ify(s);a.send(f)})},o.pool={},"undefined"!=typeof window&&window.addEventListener("unload",function(){i.obj.map(o.pool,function(t){t.isClosed()||t.socket.close()})}),i.on("opt",function(t){this.to.next(t);var n=t.gun,e=n.back("opt.peers")||{};i.obj.map(e,function(t,e){var r=o.formatURL(e);if(!o.pool.hasOwnProperty(r)){var u=new o(r,t.backoff,n.back("opt.wsc")||{protocols:null});o.pool[r]=u,u.on("message",function(t){var o;try{o=i.obj.ify(t.data)}catch(e){return}o&&o.body&&n.on("in",o.body)})}})}),i.on("out",function(t){this.to.next(t);var n=t.gun,o=n.back("opt.peers")||{},r=n.back("opt.headers")||{};i.obj.empty(o)||e(o,{body:t,headers:r})}),e.jsonp=function(t,n){e.jsonp.ify(t,function(o){o&&e.jsonp.send(o,function(o,i){n(o,i),e.jsonp.poll(t,i)},t.jsonp)})},e.jsonp.send=function(t,n,o){var e=document.createElement("script");return e.src=t,e.onerror=function(){(window[e.id]||function(){})(null,{err:"JSONP failed!"})},window[e.id=o]=function(t,o){n(o,t),n.id=e.id,e.parentNode.removeChild(e),delete window[n.id]},e.async=!0,document.getElementsByTagName("head")[0].appendChild(e),e},e.jsonp.poll=function(t,n){if(t&&t.base&&n&&n.headers&&n.headers.poll){var o=e.jsonp.poll.s=e.jsonp.poll.s||{};o[t.base]=o[t.base]||setTimeout(function(){var n={base:t.base,headers:{pull:1}};e.each(t.headers,function(t,o){n.headers[o]=t}),e.jsonp(n,function(n,i){delete o[t.base];for(var r=i.body||[];r.length&&r.shift;){var u=i.body.shift();u&&u.body&&e.createServer.ing(u,function(){e(t.base,null,null,u)})}})},n.headers.poll)}},e.jsonp.ify=function(t,n){var o=encodeURIComponent,i="?";if(t.url&&t.url.pathname&&(i=t.url.pathname+i),i=t.base+i,e.each((t.url||{}).query,function(t,n){i+=o(n)+"="+o(t)+"&"}),t.headers&&(i+=o("`")+"="+o(JSON.stringify(t.headers))+"&"),e.jsonp.maxc)return n();for(;u;)n(i+a(s,s+=c,f)+u.slice(0,s)),u=u.slice(s)}else n(i)},e.jsonp.max=2e3,e.each=function(t,n,o){if(t&&n)for(var e in t)t.hasOwnProperty(e)&&n.call(o,t[e],e)},n.exports=o)})(t,"./polyfill/request")}(); \ No newline at end of file diff --git a/lib/server.js b/lib/server.js index 7d39bef4..8fbe69b5 100644 --- a/lib/server.js +++ b/lib/server.js @@ -3,11 +3,6 @@ //require('./s3'); require('./wsp/server'); require('./file'); - Gun.log( - 'Hello wonderful person! :)\n' + - 'I\'m mark@gunDB.io, message me for help or with hatemail. ' + - 'I want to hear from you! <3' - ); Gun.log('NOTE: S3 driver not updated to 0.5 yet!'); module.exports = Gun; }()); \ No newline at end of file diff --git a/package.json b/package.json index 701cf90e..08a7b41c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gun", - "version": "0.5.9", + "version": "0.6.0", "description": "Graph engine", "main": "index.js", "browser": "gun.min.js", diff --git a/src/adapters/localStorage.js b/src/adapters/localStorage.js index a00af298..191d2e7f 100644 --- a/src/adapters/localStorage.js +++ b/src/adapters/localStorage.js @@ -1,42 +1,47 @@ if(typeof Gun === 'undefined'){ return } // TODO: localStorage is Browser only. But it would be nice if it could somehow plugin into NodeJS compatible localStorage APIs? -var root, noop = function(){}; +var root, noop = function(){}, u; if(typeof window !== 'undefined'){ root = window } var store = root.localStorage || {setItem: noop, removeItem: noop, getItem: noop}; -function put(at){ var err, id, opt, root = at.gun._.root; +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/'; - Gun.graph.is(at.put, function(node, soul){ - //try{store.setItem(opt.prefix + soul, Gun.text.ify(node)); - // TODO: BUG! PERF! Biggest slowdown is because of localStorage stringifying larger and larger nodes! - try{store.setItem(opt.prefix + soul, Gun.text.ify(root._.graph[soul]||node)); + Gun.graph.is(at.put, function(node, soul, map){ + var keys = Gun.obj.ify(store.getItem(opt.prefix + soul+'_')||{}); + map(function(val, key){ + keys[key] = 1; + var state = Gun.state.is(node, key); + // #soul.field=val>state + try{store.setItem(opt.prefix + soul+key, JSON.stringify([val,state])); + }catch(e){ err = e || "localStorage failure" } + }); + try{store.setItem(opt.prefix + soul+'_', JSON.stringify(keys)); }catch(e){ err = e || "localStorage failure" } }); - //console.log('@@@@@@@@@@local put!'); if(Gun.obj.empty(at.gun.back('opt.peers'))){ Gun.on.ack(at, {err: err, ok: 0}); // only ack if there are no peers. } -} -function get(at){ +}); +Gun.on('get', function(at){ this.to.next(at); var gun = at.gun, lex = at.get, soul, data, opt, u; //setTimeout(function(){ (opt = at.opt || {}).prefix = opt.prefix || at.gun.back('opt.prefix') || 'gun/'; if(!lex || !(soul = lex[Gun._.soul])){ return } - data = Gun.obj.ify(store.getItem(opt.prefix + soul) || null); - if(!data){ // localStorage isn't trustworthy to say "not found". - if(Gun.obj.empty(gun.back('opt.peers'))){ - gun.back(-1).on('in', {'@': at['#']}); + var field = lex['.']; + if(field){ + if(data = Gun.obj.ify(store.getItem(opt.prefix + soul+field)||null)||u){ + data = Gun.state.ify(u, field, data[1], data[0], soul); } - return; + } else { + Gun.obj.map(Gun.obj.ify(store.getItem(opt.prefix + soul+'_')), function(v,field){ + v = Gun.obj.ify(store.getItem(opt.prefix + soul+field)||{}); + data = Gun.state.ify(data, field, v[1], v[0], soul); + }); } - if(Gun.obj.has(lex, '.')){var tmp = data[lex['.']];data = {_: data._};if(u !== tmp){data[lex['.']] = tmp}} - //console.log('@@@@@@@@@@@@local get', data, at); gun.back(-1).on('in', {'@': at['#'], put: Gun.graph.node(data)}); //},11); -} -Gun.on('put', put); -Gun.on('get', get); +}); \ No newline at end of file diff --git a/src/chain.js b/src/chain.js index b3eba6fd..8e640e67 100644 --- a/src/chain.js +++ b/src/chain.js @@ -79,8 +79,7 @@ function output(at){ if(obj_has(cat, 'put')){ //if(u !== cat.put){ cat.on('in', cat); - //cat.on('in').last.emit(cat); - } else// TODO: BUG! Handle plural chains by iterating over them. + } else if(cat.map){ obj_map(cat.map, function(proxy){ proxy.at.on('in', proxy.at); diff --git a/src/graph.js b/src/graph.js index 3b0400e6..a78c991d 100644 --- a/src/graph.js +++ b/src/graph.js @@ -6,17 +6,17 @@ var Graph = {}; ;(function(){ Graph.is = function(g, cb, fn, as){ // checks to see if an object is a valid graph. if(!g || !obj_is(g) || obj_empty(g)){ return false } // must be an object. - return !obj_map(g, map, {fn:fn,cb:cb,as:as}); // makes sure it wasn't an empty object. - } - function nf(fn){ // optional callback for each node. - if(fn){ Node.is(nf.n, fn, nf.as) } // where we then have an optional callback for each field/value. + 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. - if(!fn_is(this.cb)){ return } - nf.n = n; nf.as = this.as; + 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); } + function nf(fn){ // optional callback for each node. + if(fn){ Node.is(nf.n, fn, nf.as) } // where we then have an optional callback for each field/value. + } }()); ;(function(){ Graph.ify = function(obj, env, as){ diff --git a/src/key.js b/src/key.js index bb0300e9..6f3662d2 100644 --- a/src/key.js +++ b/src/key.js @@ -69,7 +69,7 @@ var _soul = Gun.val.rel._, _field = '.'; 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); + Gun.node.is(rel, each); // correct params? return; } Gun.node.soul.ify(rel = put[id] = Gun.obj.copy(node), id); diff --git a/src/map.js b/src/map.js index 01e634ae..85282150 100644 --- a/src/map.js +++ b/src/map.js @@ -1,18 +1,30 @@ var Gun = require('./core'); Gun.chain.map = function(cb, opt, t){ - var gun = this, cat = gun._, chain = cat.fields; - //cb = cb || function(){ return this } // TODO: API BREAKING CHANGE! 0.5 Will behave more like other people's usage of `map` where the passed callback is a transform function. By default though, if no callback is specified then it will use a transform function that returns the same thing it received. - if(chain){ return chain } - chain = cat.fields = gun.chain(); - gun.on('in', map, chain._); - if(cb){ - chain.on(cb); + var gun = this, cat = gun._, chain; + if(!cb){ + if(chain = cat.fields){ return chain } + chain = cat.fields = gun.chain(); + chain._.val = gun.back('val'); + gun.on('in', map, chain._); + return chain; } + Gun.log.once("mapfn", "Map functions are experimental, their behavior and API may change moving forward. Please play with it and report bugs and ideas on how to improve it."); + chain = gun.chain(); + gun.map().on(function(data, key, at, ev){ + var next = (cb||noop).call(this, data, key, at, ev); + if(u === next){ return } + if(Gun.is(next)){ + chain._.on('in', next._); + return; + } + chain._.on('in', {get: key, put: next, gun: chain}); + }); return chain; } function map(at){ if(!at.put || Gun.val.is(at.put)){ return } + if(this.as.val){ this.off() } obj_map(at.put, each, {cat: this.as, gun: at.gun}); this.to.next(at); } @@ -21,5 +33,5 @@ function each(v,f){ var cat = this.cat, gun = this.gun.get(f), at = (gun._); (at.echo || (at.echo = {}))[cat.id] = cat; } -var obj_map = Gun.obj.map, noop = function(){}, event = {stun: noop, off: noop}, n_ = Gun.node._; +var obj_map = Gun.obj.map, noop = function(){}, event = {stun: noop, off: noop}, n_ = Gun.node._, u; \ No newline at end of file diff --git a/src/node.js b/src/node.js index 3dd5cdc7..3168d125 100644 --- a/src/node.js +++ b/src/node.js @@ -2,26 +2,26 @@ var Type = require('./type'); var Val = require('./val'); var Node = {_: '_'}; -Node.soul = function(n, o){ return (n && n._ && n._[o || _soul]) } // convenience function to check to see if there is a soul on a node and return it. +Node.soul = function(n, o){ return (n && n._ && n._[o || soul_]) } // convenience function to check to see if there is a soul on a node and return it. Node.soul.ify = function(n, o){ // put a soul on an object. o = (typeof o === 'string')? {soul: o} : o || {}; n = n || {}; // make sure it exists. n._ = n._ || {}; // make sure meta exists. - n._[_soul] = o.soul || n._[_soul] || text_random(); // put the soul on it. + n._[soul_] = o.soul || n._[soul_] || text_random(); // put the soul on it. return n; } ;(function(){ - Node.is = function(n, cb, o){ var s; // checks to see if an object is a valid node. + 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. if(s = Node.soul(n)){ // must have a soul on it. - return !obj_map(n, map, {o:o,cb:cb,s:s,n:n}); + return !obj_map(n, map, {as:as,cb:cb,s:s,n:n}); } return false; // nope! This was not a valid node. } function map(v, f){ // we invert this because the way we check for this is via a negation. if(f === Node._){ return } // skip over the metadata. if(!Val.is(v)){ return true } // it is true that this is an invalid node. - if(this.cb){ this.cb.call(this.o, v, f, this.s, this.n) } // optionally callback each field/value. + if(this.cb){ this.cb.call(this.as, v, f, this.n, this.s) } // optionally callback each field/value. } }()); ;(function(){ @@ -31,11 +31,11 @@ Node.soul.ify = function(n, o){ // put a soul on an object. else if(o instanceof Function){ o = {map: o} } if(o.map){ o.node = o.map.call(as, obj, u, o.node || {}) } if(o.node = Node.soul.ify(o.node || {}, o)){ - obj_map(obj, map, {opt:o,as:as}); + obj_map(obj, map, {o:o,as:as}); } return o.node; // This will only be a valid node if the object wasn't already deep! } - function map(v, f){ var o = this.opt, tmp, u; // iterate over each field/value. + function map(v, f){ var o = this.o, tmp, u; // iterate over each field/value. if(o.map){ tmp = o.map.call(this.as, v, ''+f, o.node); if(u === tmp){ @@ -51,7 +51,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_ = Val.rel._; var u; module.exports = Node; \ No newline at end of file diff --git a/src/on.js b/src/on.js index f178cf3b..986d8204 100644 --- a/src/on.js +++ b/src/on.js @@ -63,6 +63,13 @@ Gun.chain.val = function(cb, opt){ opt.cat = at; gun.get(val, {as: opt}); opt.async = at.stun? 1 : true; + } else { + Gun.log.once("valonce", "Chainable val is experimental, its behavior and API may change moving forward. Please play with it and report bugs and ideas on how to improve it."); + var chain = gun.chain(); + chain._.val = gun.val(function(){ + chain._.on('in', gun._); + }); + return chain; } return gun; } diff --git a/src/onto.js b/src/onto.js index 2a9777ed..a21faa05 100644 --- a/src/onto.js +++ b/src/onto.js @@ -14,6 +14,7 @@ module.exports = function onto(tag, arg, as){ if(this === this.the.last){ this.the.last = this.back; } + this.to.back = this.back; this.next = onto._.next; this.back.to = this.to; }), @@ -23,8 +24,7 @@ module.exports = function onto(tag, arg, as){ on: this, as: as, }; - (be.back = tag.last || - (tag.to = be) && tag).to = be; + (be.back = tag.last || tag).to = be; return tag.last = be; } (tag = tag.to).next(arg); diff --git a/src/state.js b/src/state.js index 297ce9ed..679a9b59 100644 --- a/src/state.js +++ b/src/state.js @@ -4,17 +4,28 @@ var Node = require('./node'); function State(){ var t = time(); if(last < t){ - n = 0; - return last = t; + return N = 0, last = t; } return last = t + ((N += 1) / D); } var time = Type.time.is, last = -Infinity, N = 0, D = 1000; // WARNING! In the future, on machines that are D times faster than 2016AD machines, you will want to increase D by another several orders of magnitude so the processing speed never out paces the decimal resolution (increasing an integer effects the state accuracy). State._ = '>'; -State.ify = function(n, f, s){ // put a field's state on a node. - if(!n || !n[N_]){ return } // reject if it is not node-like. +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 + return; + } + n = Node.soul.ify(n, soul); // then make it so! + } var tmp = obj_as(n[N_], State._); // grab the states data. - if(u !== f && num_is(s)){ tmp[f] = s } // add the valid state. + if(u !== f && f !== N_){ + if(num_is(s)){ + tmp[f] = s; // add the valid state. + } + if(u !== v){ // Note: Not its job to check for valid values! + n[f] = v; + } + } return n; } State.is = function(n, f, o){ // convenience function to get the state on a field on a node and return it. diff --git a/src/type.js b/src/type.js index f3ecba84..7f351438 100644 --- a/src/type.js +++ b/src/type.js @@ -61,7 +61,7 @@ Type.obj.del = function(o, k){ delete o[k]; return o; } -Type.obj.as = function(o, f, v){ return o[f] = o[f] || (arguments.length >= 3? v : {}) } +Type.obj.as = function(o, f, v, u){ return o[f] = o[f] || (u === v? {} : v) } Type.obj.ify = function(o){ if(obj_is(o)){ return o } try{o = JSON.parse(o); diff --git a/src/val.js b/src/val.js index d7a5d217..a935f8e2 100644 --- a/src/val.js +++ b/src/val.js @@ -2,13 +2,12 @@ var Type = require('./type'); var Val = {}; Val.is = function(v){ // Valid values are a subset of JSON: null, binary, number (!Infinity), text, or a soul relation. Arrays need special algorithms to handle concurrency, so they are not supported directly. Use an extension that supports them if needed but research their problems first. - var u; if(v === u){ return false } if(v === null){ return true } // "deletes", nulling out fields. if(v === Infinity){ return false } // we want this to be, but JSON does not support it, sad face. - if(bi_is(v) // by "binary" we mean boolean. - || num_is(v) - || text_is(v)){ // by "text" we mean strings. + if(text_is(v) // by "text" we mean strings. + || bi_is(v) // by "binary" we mean boolean. + || num_is(v)){ // by "number" we mean integers or decimals. return true; // simple values are valid. } return Val.rel.is(v) || false; // is the value a soul relation? Then it is valid and return it. If not, everything else remaining is an invalid data type. Custom extensions can be built on top of these primitives to support other types. @@ -16,7 +15,7 @@ Val.is = function(v){ // Valid values are a subset of JSON: null, binary, number Val.rel = {_: '#'}; ;(function(){ Val.rel.is = function(v){ // this defines whether an object is a soul relation or not, they look like this: {'#': 'UUID'} - if(v && !v._ && obj_is(v)){ // must be an object. + if(v && v[rel_] && !v._ && obj_is(v)){ // must be an object. var o = {}; obj_map(v, map, o); if(o.id){ // a valid id was found. @@ -27,15 +26,15 @@ Val.rel = {_: '#'}; } function map(s, f){ var o = this; // map over the object... if(o.id){ return o.id = false } // if ID is already defined AND we're still looping through the object, it is considered invalid. - if(f == _rel && text_is(s)){ // the field should be '#' and have a text value. + if(f == rel_ && text_is(s)){ // the field should be '#' and have a text value. o.id = s; // we found the soul! } else { return o.id = false; // if there exists anything else on the object that isn't the soul, then it is considered invalid. } } }()); -Val.rel.ify = function(t){ return obj_put({}, _rel, t) } // convert a soul into a relation and return it. -var _rel = Val.rel._; +Val.rel.ify = function(t){ return obj_put({}, rel_, t) } // convert a soul into a relation and return it. +var rel_ = Val.rel._, u; var bi_is = Type.bi.is; var num_is = Type.num.is; var text_is = Type.text.is; diff --git a/test/common.js b/test/common.js index 45d22ca0..ce217072 100644 --- a/test/common.js +++ b/test/common.js @@ -3383,6 +3383,58 @@ describe('Gun', function(){ },300); }); + it('map with map function', function(done){ + var gun = Gun(), s = 'map/mapfunc', u; + var app = gun.get(s); + var list = app.get('list'); + + var check = {}; + list.map(user => user.age === 27? user.name + "thezombie" : u).on(function(data){ + //console.log('data:', data); + check[data] = true; + if(check.alicethezombie && check.bobthezombie){ + if(done.c){return}done.c=1; + done(); + } + }); + + list.set({name: 'alice', age: 27}); + list.set({name: 'bob', age: 27}); + list.set({name: 'carl', age: 29}); + list.set({name: 'dave', age: 25}); + }); + + it('val and then map', function(done){ + var gun = Gun(), s = 'val/then/map', u; + var list = gun.get(s); + + list.set(gun.get('alice').put({name: 'alice', age: 27})); + list.set(gun.get('bob').put({name: 'bob', age: 27})); + list.set(gun.get('carl').put({name: 'carl', age: 29})); + list.set(gun.get('dave').put({name: 'dave', age: 25})); + + var check = {}; + list.val().map().on(function(data, key){ + check[key] = data; + clearTimeout(done.to); + done.to = setTimeout(function(){ + if(check.alice && check.bob && check.carl && check.dave && done.last){ + expect(check.alice.age).to.be(27); + expect(check.bob.age).to.be(28); + expect(check.carl.age).to.be(29); + expect(check.dave.age).to.be(25); + expect(check.eve).to.not.be.ok(); + if(done.c){return}done.c=1; + done(); + } + },600); + }); + setTimeout(function(){ + list.set(gun.get('eve').put({name: 'eve', age: 30})); + gun.get('bob').path('age').put(28); + done.last = true; + },300); + }); return; it.only('Make sure circular contexts are not copied', function(done){ /* let's define an appropriate deep default database... */ @@ -5331,7 +5383,7 @@ describe('Gun', function(){ Gun.is.node.ify(tmp.node, tmp.soul); tmp.graph['me'] = tmp.keynode = {}; - Gun.obj.as(tmp.rel = {}, Gun._.soul, tmp.soul); + Gun.obj.put(tmp.rel = {}, Gun._.soul, tmp.soul); tmp.keynode[tmp.soul] = tmp.rel; Gun.is.node.ify(tmp.keynode, 'me'); tmp.keynode[Gun._.meta]['key'] = 1;