From 5fe7b84e8c482de32b0510cd905cc96bfdaaf70a Mon Sep 17 00:00:00 2001 From: Mark Nadal Date: Thu, 6 Jul 2017 18:23:25 -0700 Subject: [PATCH] v0.8 src/ baby! --- gun.min.js | 2 +- src/adapters/localStorage.js | 104 +++++++++++----------- src/adapters/websocket.js | 97 ++++++++++++++++++++ src/chain.js | 31 +++++-- src/core.js | 10 --- src/dup.js | 47 ++++------ src/index.js | 167 ++--------------------------------- src/map.js | 2 +- src/not.js | 12 --- src/on.js | 2 +- src/onify.js | 151 ------------------------------- src/path.js | 38 -------- src/polyfill/request.js | 106 ---------------------- src/put.js | 2 +- src/root.js | 73 +++++++-------- src/schedule.js | 39 -------- src/set.js | 6 +- src/type.js | 2 +- 18 files changed, 240 insertions(+), 651 deletions(-) create mode 100644 src/adapters/websocket.js delete mode 100644 src/core.js delete mode 100644 src/not.js delete mode 100644 src/onify.js delete mode 100644 src/path.js delete mode 100644 src/polyfill/request.js delete mode 100644 src/schedule.js diff --git a/gun.min.js b/gun.min.js index c5f26afa..9fc6d7ae 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 _=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],_,t),p!==c)return p}else if(s===a[g?d[h]:h])return d?d[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,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=d(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(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,_=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)?!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.schedule=t("./schedule"),i.on=t("./onify")(),i._={node:i.node._,soul:i.val.rel._,state:i.state._,field:".",value:"="},function(){function t(t){var n,o,e=this,r=e.as;t.gun||(t.gun=r.gun),(o=t["#"])||(o=t["#"]=i.text.random()),r.dup.check(o)||(r.dup.track(o),n=p(t,{gun:r.gun}),r.ack(t["@"],t)||(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]||v,s=i.state.is(a,n,!0),f=a[n],c=i.HAM(r.machine,u,s,t,f);return c.incoming?(r.put[e]=i.state.to(o,n,r.put[e]),void((r.diff||(r.diff={}))[e]=i.state.to(o,n,r.diff[e]))):void(c.defer&&(r.defer=u<(r.defer||1/0)?u:r.defer))}function n(t,n){var e=(this.gun._.next||v)[n];if(e){var r=this.map[n]={put:this.node=t,get:this.soul=n,gun:this.ref=e};d(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,a={gun:o.gun,graph:o.gun._.graph,put:{},map:{},machine:i.state()};return i.graph.is(o.put,null,t,a)||(a.err="Error: Invalid graph!"),a.err?a.gun.on("in",{"@":o["#"],err:i.log(a.err)}):(d(a.put,n,a),d(a.map,e,a),u!==a.defer&&i.schedule(a.defer,function(){i.on("put",o)},i.state),void(a.diff&&r.to.next(p(o,{put:a.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[h],s=r.next||(r.next={}),f=(s[e]||v)._;if(!u||!f)return o.to.next(t);if(a){if(!l(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 c(t)||(t={}),c(o.opt)||(o.opt=t),a(e)&&(e=[e]),s(e)&&(e=d(e,function(t,n,o){o(t,{url:t})}),c(o.opt.peers)||(o.opt.peers={}),o.opt.peers=p(e,o.opt.peers)),o.opt.wsc=o.opt.wsc||{protocols:[]},o.opt.peers=o.opt.peers||{},p(t,o.opt),i.on("opt",o),n}}();var u,a=i.text.is,s=i.list.is,f=i.obj,c=f.is,l=f.has,p=f.to,d=f.map,g=(f.copy,i._.soul),h=i._.field,v=(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)._,g(o,y)?g(n=e.put,o=o[y])&&e.on("in",{get:e.get,put:c.state.to(n,o),gun:e.gun}):g(e,"put")&&e.on("in",e);else if(g(o,y)){o=o[y];var a=o?r.get(o)._:i;if(l!==a.put)return void a.on("in",a);if(g(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(g(i,"put")?i.on("in",i):i.map&&b(i.map,function(t){t.at.on("in",t.at)}),i.ack&&!g(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._,d=t.put;e.back._||p}if(0>e.ack&&!t.ack&&!c.val.rel.is(d)&&(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===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=_(t,{put:d=f.put})),o.to.next(t),r(e,t,o),void b(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 b(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=_(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={},d=c.obj,g=d.has,h=d.put,v=d.del,_=d.to,b=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]);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,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(!_(l)&&i!==l)return!0;if(!_(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&&_(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){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,d=(p.soul,p.is,p.ify,e.state),g=d.is,h=d.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 +!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=i(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(t){function n(t,n,e,i,r){if(n>t)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[j]&&t[j][o._]||e;if(i)return m(i=i[n])?i:-(1/0)},o.ify=function(t,n,e,r,u){if(!t||!t[j]){if(!u)return;t=i.soul.ify(t,u)}var a=g(t[j],o._);return l!==n&&n!==j&&(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){j!==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=m(e)?e:o(),u[j]=u[j]||{},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,k=e.fn,y=k.is,j=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(t){var n={s:{}};return t=t||{max:1e3,age:12e4},n.check=function(t){return n.s[t]?n.track(t):!1},n.track=function(o){return n.s[o]=i(),n.to||(n.to=setTimeout(function(){e.obj.map(n.s,function(o,r){t.age>i()-o||e.obj.del(n.s,r)}),n.to=null},t.age)),o},n}var e=t("./type"),i=e.time.is;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=.8,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("./onto"),i._={node:i.node._,soul:i.val.rel._,state:i.state._,field:".",value:"="},function(){function t(t){var n,o,e=this,r=e.as;t.gun||(t.gun=r.gun),(o=t["#"])||(o=t["#"]=c(9)),r.dup.check(o)||(r.dup.track(o),n=d(t,{gun:r.gun}),r.ack(t["@"],t)||(t.get&&i.on.get(n),t.put&&i.on.put(n)),r.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||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]||m,s=i.state.is(a,n,!0),f=a[n],c=i.HAM(r.machine,u,s,t,f);return c.incoming?(r.put[e]=i.state.to(o,n,r.put[e]),void((r.diff||(r.diff={}))[e]=i.state.to(o,n,r.diff[e]))):void(c.defer&&(r.defer=u<(r.defer||1/0)?u:r.defer))}function n(t,n){var e=this.gun._,i=(e.next||m)[n];if(i){var r=this.map[n]={put:this.node=t,get:this.soul=n,gun:this.ref=i};h(t,o,this),e.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){var r=o.gun._,a={gun:o.gun,graph:o.gun._.graph,put:{},map:{},machine:i.state()};return i.graph.is(o.put,null,t,a)||(a.err="Error: Invalid graph!"),a.err?r.on("in",{"@":o["#"],err:i.log(a.err)}):(h(a.put,n,a),h(a.map,e,a),u!==a.defer&&setTimeout(function(){i.on.put(o)},a.defer-r.machine),void(a.diff&&r.on("put",d(o,{put:a.diff}))))},i.on.get=function(t){var n,o=t.gun._,e=t.get[_],r=o.graph[e],u=t.get[b],a=o.next||(o.next={}),s=(a[e]||m)._;if(!r||!s)return o.on("get",t);if(u){if(!g(r,u))return o.on("get",t);r=i.state.to(r,u)}else r=i.obj.copy(r);r=i.graph.node(r),n=s.ack,o.on("in",{"@":t["#"],how:"mem",put:r,gun:s.gun}),n>0||o.on("get",t)}}(),function(){i.on.ask=function(t,n){if(this.on){var o=c(9);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 p(t)||(t={}),p(o.opt)||(o.opt=t),f(e)&&(e=[e]),a(e)&&(e=h(e,function(t,n,o){o(t,{url:t})}),p(o.opt.peers)||(o.opt.peers={}),o.opt.peers=d(e,o.opt.peers)),o.opt.uuid=o.opt.uuid||function(){return v().toString(36).replace(".","")+c(12)},o.opt.peers=o.opt.peers||{},d(t,o.opt),i.on("opt",o),n}}();var u,a=i.list.is,s=i.text,f=s.is,c=s.random,l=i.obj,p=l.is,g=l.has,d=l.to,h=l.map,v=(l.copy,i.state),_=i._.soul,b=i._.field,m=(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,i.log.once("0.8","0.8 WARNING! Breaking changes, test that your app works before upgrading! The adapter interface has been upgraded (non-default storage and transport layers probably won't work). Also, `.path()` and `.not()` are outside core and now in 'lib/'.")})(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,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,k)?d(n=e.put,o=o[k])&&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,k)){o=o[k];var a=o?r.get(o)._:i;if(l!==a.put)return void a.on("in",a);if(d(i,"put")){var s,p=i.put;if((s=c.node.soul(p))&&(p=c.val.rel.ify(s)),s=c.val.rel.is(p)){if(!t.gun._)return;return void t.gun._.on("out",{get:e={"#":s,".":o,gun:t.gun},"#":u._.ask(f,e),gun:t.gun})}if(l===p||c.val.is(p)){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(f,e),gun:t.gun})}if(i.get){if(!i.back._)return;return void i.back._.on("out",{get:h({},k,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(f,e),gun:i.gun});if(i.get){if(!i.back._)return;return void i.back._.on("out",{get:h({},k,i.get),gun:i.gun})}}i.back._.on("out",t)}function o(t){t=t._||t;{var n,o=this,r=this.as,s=t.gun,f=s._,g=t.put;r.back._||p}if(0>r.ack&&!t.ack&&!c.val.rel.is(g)&&(r.ack=1),r.get&&t.get!==r.get&&(t=_(t,{get:r.get})),r.field&&f!==r&&(t=_(t,{gun:r.gun}),f.ack&&(r.ack=r.ack||f.ack)),l===g){if(o.to.next(t),r.soul)return;return i(r,t,o),r.field&&a(r,t),v(f.echo,r.id),void v(r.map,f.id)}return r.soul?(r.root._.now&&(t=_(t,{put:g=f.put})),o.to.next(t),i(r,t,o),void b(g,u,{at:t,cat:r})):(n=c.val.rel.is(g))?(e(r,t,f,n),o.to.next(t),void i(r,t,o)):c.val.is(g)?(r.field||r.soul?a(r,t):(f.field||f.soul)&&((f.echo||(f.echo={}))[r.id]=r,(r.map||(r.map={}))[f.id]=r.map[f.id]||{at:f}),o.to.next(t),void i(r,t,o)):(r.field&&f!==r&&d(f,"put")&&(r.put=f.put),(n=c.node.soul(g))&&f.field&&(f.put=r.root.get(n)._.put),o.to.next(t),i(r,t,o),e(r,t,f,n),void b(g,u,{at:t,cat:r}))}function e(t,n,o,i){if(i&&y!==t.get){var r=t.root.get(i)._;t.field?o=r:o.field&&e(o,n,o,i),o!==t&&((o.echo||(o.echo={}))[t.id]=t,t.field&&!(t.map||p)[o.id]&&a(t,n),r=(t.map||(t.map={}))[o.id]=t.map[o.id]||{at:o},i!==r.rel&&s(t,r.rel=i))}}function i(t,n,o){t.echo&&(t.field&&(n=_(n,{event:o})),b(t.echo,r,n))}function r(t){t.on("in",this)}function u(t,n){var o,e,i,r=this.cat,u=r.next||p,a=this.at;(y!==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 a(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 s(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(f,o)})):void b(t.next,function(o,e){o._.on("out",{get:o={"#":n,".":e,gun:o},"#":t.root._.ask(f,o)})})}function f(t){var n=this.as,o=n.gun._;if(!t.put||n["."]&&!d(t.put[n["#"]],o.get)){if(o.put!==l)return;return void o.on("in",{get:o.get,put:o.put=l,gun:o.gun})}t.gun=o.root,c.on.put(t)}var c=t("./root");c.chain.chain=function(){var t,e=this._,i=new this.constructor(this),r=i._;return r.root=t=e.root,r.id=++t._.once,r.back=this,r.on=c.on,r.on("in",o,r),r.on("out",n,r),i},c.chain.chain.input=o;var l,p={},g=c.obj,d=g.has,h=g.put,v=g.del,_=g.to,b=g.map,m=c._.soul,k=c._.field,y=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||h,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 o=t("./root");t("./opt"),t("./chain"),t("./back"),t("./put"),t("./get"),n.exports=o})(t,"./index"),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("./index");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=(n.batch||1e3)?s():void(e||(e=setTimeout(s,n.wait||1)))}),t.on("get",function(t){this.to.next(t);var n,o,e,i=t.gun,r=t.get;if(r&&(n=r[Gun._.soul])){var a=r["."];o=u[n]||e,o&&a&&(o=Gun.state.to(o,a)),(o||Gun.obj.empty(i.back("opt.peers")))&&i.on("in",{"@":t["#"],put:Gun.graph.node(o),how:"lS"})}});var a=function(t,n,o,e){u[e]=Gun.state.to(o,n,u[e])},s=function(){var a;r=0,clearTimeout(e),e=!1;var s=i;i={};try{o.setItem(n.file,JSON.stringify(u))}catch(f){a=f||"localStorage failure"}(a||Gun.obj.empty(n.peers))&&Gun.obj.map(s,function(n,o){t.on("in",{"@":o,err:a,ok:0})})}}})}})(t,"./adapters/localStorage"),t(function(){var n,o=t("./index");if("undefined"!=typeof window){n=window.WebSocket||window.webkitWebSocket||window.mozWebSocket,o.on("opt",function(t){function i(t){var n=this,o=c,e=t.wire||u(t,n);return e?e.readyState===e.OPEN?void e.send(o):void(t.queue=t.queue||[]).push(o):void 0}function r(t,n,o){if(o&&t){try{t=JSON.parse(t.data||t)}catch(i){}if(t instanceof Array)for(var u,a=0;u=t[a++];)r(u,n,o);else 1==f.who&&(t.ws=e),o.on("in",t)}}function u(t,e){if(t&&t.url){var u=t.url.replace("http","ws"),s=t.wire=new n(u);return s.onclose=function(){a(t,e)},s.onerror=function(n){a(t,e),n&&"ECONNREFUSED"===n.code},s.onopen=function(){var n=t.queue;t.queue=[],o.obj.map(n,function(n){c=n,i.call(e,t)})},s.onmessage=function(n){r(n,t,e)},s}}function a(t,n){clearTimeout(t.defer),t.defer=setTimeout(function(){u(t,n)},2e3)}this.to.next(t);var s=t.opt;if(!t.once&&!1!==s.WebSocket){var f=s.ws||(s.ws={});if(f.who=0,o.obj.map(s.peers,function(){++f.who}),!t.once){var c;t.on("out",function(n){if(this.to.next(n),!n.ws||1!=f.who){if(c=JSON.stringify(n),f.drain)return void f.drain.push(c);f.drain=[],setTimeout(function(){if(f.drain){var n=f.drain;f.drain=null,n.length&&(c=JSON.stringify(n),o.obj.map(s.peers,i,t))}},s.wait||1),o.obj.map(s.peers,i,t)}})}}});var e=function(){}}})(t,"./adapters/websocket")}(); \ No newline at end of file diff --git a/src/adapters/localStorage.js b/src/adapters/localStorage.js index a9ada676..f4db3b1e 100644 --- a/src/adapters/localStorage.js +++ b/src/adapters/localStorage.js @@ -5,64 +5,66 @@ var root, noop = function(){}, u; if(typeof window !== 'undefined'){ root = window } var store = root.localStorage || {setItem: noop, removeItem: noop, getItem: noop}; -var check = {}, dirty = {}, async = {}, count = 0, max = 10000, wait; - -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] = async[soul] || graph[soul] || node; +Gun.on('opt', function(ctx){ + this.to.next(ctx); + var opt = ctx.opt; + if(ctx.once){ return } + if(false === opt.localStorage){ return } + opt.file = opt.file || opt.prefix || 'gun/'; // support old option name. + var graph = ctx.graph, acks = {}, count = 0, to; + var disk = Gun.obj.ify(store.getItem(opt.file)) || {}; + + ctx.on('put', function(at){ + this.to.next(at); + Gun.graph.is(at.put, null, map); + if(!at['@']){ acks[at['#']] = true; } // only ack non-acks. + count += 1; + if(count >= (opt.batch || 1000)){ + return flush(); + } + if(to){ return } + to = setTimeout(flush, opt.wait || 1); }); - count += 1; - if(!at['@']){ check[at['#']] = root; } // only ack non-acks. - function save(){ - clearTimeout(wait); - var ack = check; - var all = async; + + ctx.on('get', function(at){ + this.to.next(at); + var gun = at.gun, lex = at.get, soul, data, opt, u; + //setTimeout(function(){ + if(!lex || !(soul = lex[Gun._.soul])){ return } + //if(0 >= at.cap){ return } + var field = lex['.']; + data = disk[soul] || u; + if(data && field){ + 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? + } + gun.on('in', {'@': at['#'], put: Gun.graph.node(data), how: 'lS'}); + //},11); + }); + + var map = function(val, key, node, soul){ + disk[soul] = Gun.state.to(node, key, disk[soul]); + } + + var flush = function(){ + var err; count = 0; - wait = false; - check = {}; - async = {}; - 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; - try{store.setItem(opt.prefix + soul, JSON.stringify(node)); - }catch(e){ err = e || "localStorage failure" } - }); - if(!Gun.obj.empty(at.gun.back('opt.peers'))){ return } // only ack if there are no peers. - Gun.obj.map(ack, function(root, id){ - root.on('in', { + clearTimeout(to); + to = false; + var ack = acks; + acks = {}; + try{store.setItem(opt.file, JSON.stringify(disk)); + }catch(e){ err = e || "localStorage failure" } + if(!err && !Gun.obj.empty(opt.peers)){ return } // only ack if there are no peers. + Gun.obj.map(ack, function(yes, id){ + ctx.on('in', { '@': id, err: err, ok: 0 // localStorage isn't reliable, so make its `ok` code be a low number. }); }); } - if(count >= max){ // goal is to do 10K inserts/second. - return save(); - } - if(wait){ return } - clearTimeout(wait); - wait = setTimeout(save, 1000); -}); -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 } - //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.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? - } - gun.on('in', {'@': at['#'], put: Gun.graph.node(data), how: 'lS'}); - //},11); }); \ No newline at end of file diff --git a/src/adapters/websocket.js b/src/adapters/websocket.js new file mode 100644 index 00000000..64c9b4cd --- /dev/null +++ b/src/adapters/websocket.js @@ -0,0 +1,97 @@ + +var Gun = require('./index'); +var WebSocket; +if(typeof window !== 'undefined'){ + WebSocket = window.WebSocket || window.webkitWebSocket || window.mozWebSocket; +} else { + return; +} +Gun.on('opt', function(ctx){ + this.to.next(ctx); + var opt = ctx.opt; + if(ctx.once){ return } + if(false === opt.WebSocket){ return } + var ws = opt.ws || (opt.ws = {}); ws.who = 0; + Gun.obj.map(opt.peers, function(){ ++ws.who }); + if(ctx.once){ return } + var batch; + + ctx.on('out', function(at){ + this.to.next(at); + if(at.ws && 1 == ws.who){ return } // performance hack for reducing echoes. + batch = JSON.stringify(at); + if(ws.drain){ + ws.drain.push(batch); + return; + } + ws.drain = []; + setTimeout(function(){ + if(!ws.drain){ return } + var tmp = ws.drain; + ws.drain = null; + if(!tmp.length){ return } + batch = JSON.stringify(tmp); + Gun.obj.map(opt.peers, send, ctx); + }, opt.wait || 1); + Gun.obj.map(opt.peers, send, ctx); + }); + function send(peer){ + var ctx = this, msg = batch; + var wire = peer.wire || open(peer, ctx); + if(!wire){ return } + if(wire.readyState === wire.OPEN){ + wire.send(msg); + return; + } + (peer.queue = peer.queue || []).push(msg); + } + function receive(msg, peer, ctx){ + if(!ctx || !msg){ return } + try{msg = JSON.parse(msg.data || msg); + }catch(e){} + if(msg instanceof Array){ + var i = 0, m; + while(m = msg[i++]){ + receive(m, peer, ctx); + } + return; + } + if(1 == ws.who){ msg.ws = noop } // If there is only 1 client, just use noop since it doesn't matter. + ctx.on('in', msg); + } + function open(peer, as){ + if(!peer || !peer.url){ return } + var url = peer.url.replace('http', 'ws'); + var wire = peer.wire = new WebSocket(url); + wire.onclose = function(){ + reconnect(peer, as); + }; + wire.onerror = function(error){ + reconnect(peer, as); // placement? + if(!error){ return } + if(error.code === 'ECONNREFUSED'){ + //reconnect(peer, as); + } + }; + wire.onopen = function(){ + var queue = peer.queue; + peer.queue = []; + Gun.obj.map(queue, function(msg){ + batch = msg; + send.call(as, peer); + }); + } + wire.onmessage = function(msg){ + receive(msg, peer, as); // diff: peer not wire! + }; + return wire; + } + function reconnect(peer, as){ + clearTimeout(peer.defer); + peer.defer = setTimeout(function(){ + open(peer, as); + }, 2 * 1000); + } +}); +var noop = function(){}; + \ No newline at end of file diff --git a/src/chain.js b/src/chain.js index d385db4d..066a6dde 100644 --- a/src/chain.js +++ b/src/chain.js @@ -1,12 +1,14 @@ +// WARNING: GUN is very simple, but the JavaScript chaining API around GUN +// is complicated and was extremely hard to build. If you port GUN to another +// language, consider implementing an easier API to build. var Gun = require('./root'); Gun.chain.chain = function(){ - var at = this._, chain = new this.constructor(this), cat = chain._; + var at = this._, chain = new this.constructor(this), cat = chain._, root; cat.root = root = at.root; cat.id = ++root._.once; cat.back = this; cat.on = Gun.on; - Gun.on('chain', cat); cat.on('in', input, cat); // For 'in' if I add my own listeners to each then I MUST do it before in gets called. If I listen globally for all incoming data instead though, regardless of individual listeners, I can transform the data there and then as well. cat.on('out', output, cat); // However for output, there isn't really the global option. I must listen by adding my own listener individually BEFORE this one is ever called. return chain; @@ -49,7 +51,7 @@ function output(at){ if(!at.gun._){ return } (at.gun._).on('out', { get: tmp = {'#': rel, '.': get, gun: at.gun}, - '#': root._.ask(Gun.HAM.synth, tmp), + '#': root._.ask(ack, tmp), gun: at.gun }); return; @@ -72,7 +74,7 @@ function output(at){ if(!at.gun._){ return } (at.gun._).on('out', { get: tmp = {'#': cat.soul, '.': get, gun: at.gun}, - '#': root._.ask(Gun.HAM.synth, tmp), + '#': root._.ask(ack, tmp), gun: at.gun }); return; @@ -106,7 +108,7 @@ function output(at){ if(cat.soul){ cat.on('out', { get: tmp = {'#': cat.soul, gun: cat.gun}, - '#': root._.ask(Gun.HAM.synth, tmp), + '#': root._.ask(ack, tmp), gun: cat.gun }); return; @@ -268,17 +270,32 @@ function ask(cat, soul){ tmp.ack = tmp.ack || -1; tmp.on('out', { get: tmp = {'#': soul, gun: tmp.gun}, - '#': cat.root._.ask(Gun.HAM.synth, tmp) + '#': cat.root._.ask(ack, tmp) }); return; } obj_map(cat.next, function(gun, key){ (gun._).on('out', { get: gun = {'#': soul, '.': key, gun: gun}, - '#': cat.root._.ask(Gun.HAM.synth, gun) + '#': cat.root._.ask(ack, gun) }); }); } +function ack(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.on.put(at); +} var empty = {}, u; var obj = Gun.obj, obj_has = obj.has, obj_put = obj.put, obj_del = obj.del, obj_to = obj.to, obj_map = obj.map; var _soul = Gun._.soul, _field = Gun._.field, node_ = Gun.node._; diff --git a/src/core.js b/src/core.js deleted file mode 100644 index 0d4aaea3..00000000 --- a/src/core.js +++ /dev/null @@ -1,10 +0,0 @@ - -var Gun = require('./root'); -require('./index'); // TODO: CLEAN UP! MERGE INTO ROOT! -require('./opt'); -require('./chain'); -require('./back'); -require('./put'); -require('./get'); -module.exports = Gun; - \ No newline at end of file diff --git a/src/dup.js b/src/dup.js index 5a8e4ffc..1103159d 100644 --- a/src/dup.js +++ b/src/dup.js @@ -1,35 +1,26 @@ var Type = require('./type'); -function Dup(){ - this.cache = {}; -} -Dup.prototype.track = function(id){ - this.cache[id] = Type.time.is(); - if (!this.to) { - this.gc(); // Engage GC. +function Dup(opt){ + var dup = {s:{}}; + opt = opt || {max: 1000, age: 1000 * 60 * 2}; + dup.check = function(id){ + return dup.s[id]? dup.track(id) : false; } - return id; -}; -Dup.prototype.check = function(id){ - // Have we seen this ID recently? - return Type.obj.has(this.cache, id)? this.track(id) : false; // Important, bump the ID's liveliness if it has already been seen before - this is critical to stopping broadcast storms. -} -Dup.prototype.gc = function(){ - var de = this, now = Type.time.is(), oldest = now, maxAge = 5 * 60 * 1000; - // TODO: Gun.scheduler already does this? Reuse that. - Type.obj.map(de.cache, function(time, id){ - oldest = Math.min(now, time); - if ((now - time) < maxAge){ return } - Type.obj.del(de.cache, id); - }); - var done = Type.obj.empty(de.cache); - if(done){ - de.to = null; // Disengage GC. - return; + dup.track = function(id){ + dup.s[id] = time_is(); + if(!dup.to){ + dup.to = setTimeout(function(){ + Type.obj.map(dup.s, function(time, id){ + if(opt.age > (time_is() - time)){ return } + Type.obj.del(dup.s, id); + }); + dup.to = null; + }, opt.age); + } + return id; } - var elapsed = now - oldest; // Just how old? - var nextGC = maxAge - elapsed; // How long before it's too old? - de.to = setTimeout(function(){ de.gc() }, nextGC); // Schedule the next GC event. + return dup; } +var time_is = Type.time.is; module.exports = Dup; \ No newline at end of file diff --git a/src/index.js b/src/index.js index 87e1fef1..a924dff4 100644 --- a/src/index.js +++ b/src/index.js @@ -1,166 +1,9 @@ - var Gun = require('./root'); +require('./opt'); +require('./chain'); +require('./back'); +require('./put'); +require('./get'); module.exports = Gun; - -;(function(){ - function meta(v,f){ - if(obj_has(Gun.__._, f)){ return } - obj_put(this._, f, v); - } - function map(value, field){ - if(Gun._.node === field){ return } - var node = this.node, vertex = this.vertex, union = this.union, machine = this.machine; - var is = state_is(node, field), cs = state_is(vertex, field); - if(u === is || u === cs){ return true } // it is true that this is an invalid HAM comparison. - var iv = value, cv = vertex[field]; - - - - - - - - - // TODO: BUG! Need to compare relation to not relation, and choose the relation if there is a state conflict. - - - - - - - - - if(!val_is(iv) && u !== iv){ return true } // Undefined is okay since a value might not exist on both nodes. // it is true that this is an invalid HAM comparison. - if(!val_is(cv) && u !== cv){ return true } // Undefined is okay since a value might not exist on both nodes. // it is true that this is an invalid HAM comparison. - var HAM = Gun.HAM(machine, is, cs, iv, cv); - if(HAM.err){ - console.log(".!HYPOTHETICAL AMNESIA MACHINE ERR!.", field, HAM.err); // this error should never happen. - return; - } - if(HAM.state || HAM.historical || HAM.current){ // TODO: BUG! Not implemented. - //opt.lower(vertex, {field: field, value: value, state: is}); - return; - } - if(HAM.incoming){ - union[field] = value; - state_ify(union, field, is); - return; - } - if(HAM.defer){ // TODO: BUG! Not implemented. - union[field] = value; // WRONG! BUG! Need to implement correct algorithm. - state_ify(union, field, is); // WRONG! BUG! Need to implement correct algorithm. - // filler algorithm for now. - return; - /*upper.wait = true; - opt.upper.call(state, vertex, field, incoming, ctx.incoming.state); // signals that there are still future modifications. - Gun.schedule(ctx.incoming.state, function(){ - update(incoming, field); - if(ctx.incoming.state === upper.max){ (upper.last || function(){})() } - }, gun.__.opt.state);*/ - } - } - Gun.HAM.union = function(vertex, node, opt){ - if(!node || !node._){ return } - vertex = vertex || Gun.node.soul.ify({_:{'>':{}}}, Gun.node.soul(node)); - if(!vertex || !vertex._){ return } - opt = num_is(opt)? {machine: opt} : {machine: Gun.state()}; - opt.union = vertex || Gun.obj.copy(vertex); // TODO: PERF! This will slow things down! - // TODO: PERF! Biggest slowdown (after 1ocalStorage) is the above line. Fix! Fix! - opt.vertex = vertex; - opt.node = node; - //obj_map(node._, meta, opt.union); // TODO: Review at some point? - if(obj_map(node, map, opt)){ // if this returns true then something was invalid. - return; - } - return opt.union; - } - Gun.HAM.delta = function(vertex, node, opt){ - opt = num_is(opt)? {machine: opt} : {machine: Gun.state()}; - if(!vertex){ return Gun.obj.copy(node) } - opt.soul = Gun.node.soul(opt.vertex = vertex); - if(!opt.soul){ return } - opt.delta = Gun.node.soul.ify({}, opt.soul); - obj_map(opt.node = node, diff, opt); - return opt.delta; - } - function diff(value, field){ var opt = this; - if(Gun._.node === field){ return } - if(!val_is(value)){ return } - var node = opt.node, vertex = opt.vertex, is = state_is(node, field, true), cs = state_is(vertex, field, true), delta = opt.delta; - var HAM = Gun.HAM(opt.machine, is, cs, value, vertex[field]); - - - - // TODO: BUG!!!! WHAT ABOUT DEFERRED!??? - - - - if(HAM.incoming){ - delta[field] = value; - state_ify(delta, field, is); - } - } - 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 } - if(cat.put !== u){ return } - cat.on('in', { - //root.ack(at['@'], { - get: cat.get, - put: cat.put = u, - gun: gun, - via: at - }) - return; - } - // TODO: PERF! Have options to determine if this data should even be in memory on this peer! - obj_map(at.put, function(node, soul){ var graph = this.graph; - put[soul] = Gun.HAM.delta(graph[soul], node, {graph: graph}); // TODO: PERF! SEE IF WE CAN OPTIMIZE THIS BY MERGING UNION INTO DELTA! - graph[soul] = Gun.HAM.union(graph[soul], node) || graph[soul]; - }, root); - if(at.gun !== root.gun){ - put = at.put; - } - // TODO: PERF! Have options to determine if this data should even be in memory on this peer! - obj_map(put, function(node, soul){ - var root = this, next = root.next || (root.next = {}), gun = next[soul] || (next[soul] = root.gun.get(soul)), coat = (gun._); - coat.put = root.graph[soul]; // TODO: BUG! Clone! - if(cat.field && !obj_has(node, cat.field)){ - (at = obj_to(at, {})).put = u; - Gun.HAM.synth(at, ev, cat.gun); - return; - } - coat.on('in', { - put: node, - get: soul, - gun: gun, - via: at - }); - }, root); - } -}()); - -var Type = Gun; -var num = Type.num, num_is = num.is; -var obj = Type.obj, obj_has = obj.has, obj_put = obj.put, obj_to = obj.to, obj_map = obj.map; -var node = Gun.node, node_soul = node.soul, node_is = node.is, node_ify = node.ify; -var state = Gun.state, state_is = state.is, state_ify = state.ify; -var val = Gun.val, val_is = val.is, rel_is = val.rel.is; -var u; \ No newline at end of file diff --git a/src/map.js b/src/map.js index 949e04ff..b073c7ed 100644 --- a/src/map.js +++ b/src/map.js @@ -1,5 +1,5 @@ -var Gun = require('./core'); +var Gun = require('./index'); Gun.chain.map = function(cb, opt, t){ var gun = this, cat = gun._, chain; if(!cb){ diff --git a/src/not.js b/src/not.js deleted file mode 100644 index 3a488dc1..00000000 --- a/src/not.js +++ /dev/null @@ -1,12 +0,0 @@ - -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(); - if(at.err || (u !== at.put)){ return } - if(!this.not){ return } - this.not.call(at.gun, at.get, function(){ console.log("Please report this bug on https://gitter.im/amark/gun and in the issues."); need.to.implement; }); -} - \ No newline at end of file diff --git a/src/on.js b/src/on.js index 014de075..3ae85e76 100644 --- a/src/on.js +++ b/src/on.js @@ -1,5 +1,5 @@ -var Gun = require('./core'); +var Gun = require('./index'); Gun.chain.on = function(tag, arg, eas, as){ var gun = this, at = gun._, tmp, act, off; if(typeof tag === 'string'){ diff --git a/src/onify.js b/src/onify.js deleted file mode 100644 index 2d499f08..00000000 --- a/src/onify.js +++ /dev/null @@ -1,151 +0,0 @@ - -// TODO: Needs to be redone. -var On = require('./onto'); - -function Chain(create, opt){ - opt = opt || {}; - opt.id = opt.id || '#'; - opt.rid = opt.rid || '@'; - opt.uuid = opt.uuid || function(){ - return (+new Date()) + Math.random(); - }; - var on = On;//On.scope(); - - on.stun = function(chain){ - var stun = function(ev){ - if(stun.off && stun === this.stun){ - this.stun = null; - return false; - } - if(on.stun.skip){ - return false; - } - if(ev){ - ev.cb = ev.fn; - ev.off(); - res.queue.push(ev); - } - return true; - }, res = stun.res = function(tmp, as){ - if(stun.off){ return } - if(tmp instanceof Function){ - on.stun.skip = true; - tmp.call(as); - on.stun.skip = false; - return; - } - stun.off = true; - var i = 0, q = res.queue, l = q.length, act; - res.queue = []; - if(stun === at.stun){ - at.stun = null; - } - for(i; i < l; i++){ act = q[i]; - act.fn = act.cb; - act.cb = null; - on.stun.skip = true; - act.ctx.on(act.tag, act.fn, act); - on.stun.skip = false; - } - }, at = chain._; - res.back = at.stun || (at.back||{_:{}})._.stun; - if(res.back){ - res.back.next = stun; - } - res.queue = []; - at.stun = stun; - return res; - } - return on; - return; - return; - return; - return; - var ask = on.ask = function(cb, as){ - if(!ask.on){ ask.on = On.scope() } - var id = opt.uuid(); - if(cb){ ask.on(id, cb, as) } - return id; - } - ask._ = opt.id; - on.ack = function(at, reply){ - if(!at || !reply || !ask.on){ return } - var id = at[opt.id] || at; - if(!ask.ons[id]){ return } - ask.on(id, reply); - return true; - } - on.ack._ = opt.rid; - - - return on; - return; - return; - return; - return; - on.on('event', function event(act){ - var last = act.on.last, tmp; - if('in' === act.tag && Gun.chain.chain.input !== act.fn){ // TODO: BUG! Gun is not available in this module. - if((tmp = act.ctx) && tmp.stun){ - if(tmp.stun(act)){ - return; - } - } - } - if(!last){ return } - if(act.on.map){ - var map = act.on.map, v; - for(var f in map){ v = map[f]; - if(v){ - emit(v, act, event); - } - } - /* - Gun.obj.map(act.on.map, function(v,f){ // TODO: BUG! Gun is not available in this module. - //emit(v[0], act, event, v[1]); // below enables more control - //console.log("boooooooo", f,v); - emit(v, act, event); - //emit(v[1], act, event, v[2]); - }); - */ - } else { - emit(last, act, event); - } - if(last !== act.on.last){ - event(act); - } - }); - function emit(last, act, event, ev){ - if(last instanceof Array){ - act.fn.apply(act.as, last.concat(ev||act)); - } else { - act.fn.call(act.as, last, ev||act); - } - } - - /*on.on('emit', function(ev){ - if(ev.on.map){ - var id = ev.arg.via.gun._.id + ev.arg.get; - // - //ev.id = ev.id || Gun.text.random(6); - //ev.on.map[ev.id] = ev.arg; - //ev.proxy = ev.arg[1]; - //ev.arg = ev.arg[0]; - // below gives more control. - ev.on.map[id] = ev.arg; - //ev.proxy = ev.arg[2]; - } - ev.on.last = ev.arg; - });*/ - - on.on('emit', function(ev){ - var gun = ev.arg.gun; - if('in' === ev.tag && gun && !gun._.soul){ // TODO: BUG! Soul should be available. Currently not using it though, but should enable it (check for side effects if made available). - (ev.on.map = ev.on.map || {})[gun._.id || (gun._.id = Math.random())] = ev.arg; - } - ev.on.last = ev.arg; - }); - return on; -} -module.exports = Chain; - \ No newline at end of file diff --git a/src/path.js b/src/path.js deleted file mode 100644 index ea45d95a..00000000 --- a/src/path.js +++ /dev/null @@ -1,38 +0,0 @@ - -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 || '.'); - if(1 === tmp.length){ - gun = back.get(field, cb, opt); - gun._.opt = opt; - return gun; - } - field = tmp; - } - if(field instanceof Array){ - if(field.length > 1){ - gun = back; - var i = 0, l = field.length; - for(i; i < l; i++){ - gun = gun.get(field[i], (i+1 === l)? cb : null, opt); - } - //gun.back = back; // TODO: API change! - } else { - gun = back.get(field[0], cb, opt); - } - gun._.opt = opt; - return gun; - } - if(!field && 0 != field){ - return back; - } - gun = back.get(''+field, cb, opt); - gun._.opt = opt; - return gun; -} - \ No newline at end of file diff --git a/src/polyfill/request.js b/src/polyfill/request.js deleted file mode 100644 index 03ab4436..00000000 --- a/src/polyfill/request.js +++ /dev/null @@ -1,106 +0,0 @@ - -var Gun = require('./core'); - -if (typeof JSON === 'undefined') { - throw new Error( - 'Gun depends on JSON. Please load it first:\n' + - 'ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js' - ); -} - -var WebSocket; -if(typeof window !== 'undefined'){ - WebSocket = window.WebSocket || window.webkitWebSocket || window.mozWebSocket; -} else { - return; -} -var message, count = 0, noop = function(){}, wait; - -Gun.on('out', function(at){ - this.to.next(at); - var cat = at.gun._.root._, wsp = cat.wsp || (cat.wsp = {}); - if(at.wsp && 1 === wsp.count){ return } // if the message came FROM the only peer we are connected to, don't echo it back. - message = JSON.stringify(at); - //if(++count){ console.log("msg OUT:", count, Gun.obj.ify(message)) } - if(cat.udrain){ - cat.udrain.push(message); - return; - } - cat.udrain = []; - clearTimeout(wait); - wait = setTimeout(function(){ - if(!cat.udrain){ return } - var tmp = cat.udrain; - cat.udrain = null; - if( tmp.length ) { - message = JSON.stringify(tmp); - Gun.obj.map(cat.opt.peers, send, cat); - } - },1); - wsp.count = 0; - Gun.obj.map(cat.opt.peers, send, cat); -}); - -function send(peer){ - var msg = message, cat = this; - var wire = peer.wire || open(peer, cat); - if(cat.wsp){ cat.wsp.count++ } - if(!wire){ return } - if(wire.readyState === wire.OPEN){ - wire.send(msg); - return; - } - (peer.queue = peer.queue || []).push(msg); -} - -function receive(msg, peer, cat){ - if(!cat || !msg){ return } - try{msg = JSON.parse(msg.data || msg); - }catch(e){} - if(msg instanceof Array){ - var i = 0, m; - while(m = msg[i++]){ - receive(m, peer, cat); - } - return; - } - //if(++count){ console.log("msg in:", count, msg.body || msg) } - if(cat.wsp && 1 === cat.wsp.count){ (msg.body || msg).wsp = noop } // If there is only 1 client, just use noop since it doesn't matter. - cat.gun.on('in', msg.body || msg); -} - -function open(peer, as){ - if(!peer || !peer.url){ return } - var url = peer.url.replace('http', 'ws'); - var wire = peer.wire = new WebSocket(url, as.opt.wsc.protocols, as.opt.wsc ); - wire.onclose = function(){ - reconnect(peer, as); - }; - wire.onerror = function(error){ - reconnect(peer, as); - if(!error){ return } - if(error.code === 'ECONNREFUSED'){ - //reconnect(peer, as); - } - }; - wire.onopen = function(){ - var queue = peer.queue; - peer.queue = []; - Gun.obj.map(queue, function(msg){ - message = msg; - send.call(as, peer); - }); - } - wire.onmessage = function(msg){ - receive(msg, peer, as); - }; - return wire; -} - -function reconnect(peer, as){ - clearTimeout(peer.defer); - peer.defer = setTimeout(function(){ - open(peer, as); - }, 2 * 1000); -} - \ No newline at end of file diff --git a/src/put.js b/src/put.js index 7e1be741..d6549535 100644 --- a/src/put.js +++ b/src/put.js @@ -44,7 +44,7 @@ Gun.chain.put = function(data, cb, as){ as.ref.get('_').get(any, {as: as}); if(!as.out){ // TODO: Perf idea! Make a global lock, that blocks everything while it is on, but if it is on the lock it does the expensive lookup to see if it is a dependent write or not and if not then it proceeds full speed. Meh? For write heavy async apps that would be terrible. - as.res = as.res || Gun.on.stun(as.ref); + as.res = as.res || noop; // Gun.on.stun(as.ref); // TODO: BUG! Deal with locking? as.gun._.stun = as.ref._.stun; } return gun; diff --git a/src/root.js b/src/root.js index 472351ca..824df819 100644 --- a/src/root.js +++ b/src/root.js @@ -8,7 +8,7 @@ function Gun(o){ Gun.is = function(gun){ return (gun instanceof Gun) } -Gun.version = 0.7; +Gun.version = 0.8; Gun.chain = Gun.prototype; Gun.chain.toJSON = function(){}; @@ -21,8 +21,7 @@ Gun.node = require('./node'); Gun.state = require('./state'); Gun.graph = require('./graph'); Gun.dup = require('./dup'); -Gun.schedule = require('./schedule'); -Gun.on = require('./onify')(); +Gun.on = require('./onto'); Gun._ = { // some reserved key words, these are not the only ones. node: Gun.node._ // all metadata of a node is stored in the meta property on the node. @@ -37,7 +36,7 @@ Gun._ = { // some reserved key words, these are not the only ones. at.on = at.on || Gun.on; at.root = at.root || at.gun; at.graph = at.graph || {}; - at.dup = at.dup || new Gun.dup; + at.dup = at.dup || Gun.dup(); at.ask = Gun.on.ask; at.ack = Gun.on.ack; var gun = at.gun.opt(at.opt); @@ -52,41 +51,39 @@ 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, tmp; if(!at.gun){ at.gun = cat.gun } - if(!(tmp = at['#'])){ tmp = at['#'] = Gun.text.random() } // TODO: Use what is used other places instead. + if(!(tmp = at['#'])){ tmp = at['#'] = text_rand(9) } if(cat.dup.check(tmp)){ return } cat.dup.track(tmp); coat = obj_to(at, {gun: cat.gun}); if(!cat.ack(at['@'], at)){ if(at.get){ - //Gun.on.GET(coat); - Gun.on('get', coat); + Gun.on.get(coat); + //cat.on('get', get(coat)); } if(at.put){ - //Gun.on.PUT(coat); - Gun.on('put', coat); + Gun.on.put(coat); + //cat.on('put', put(coat)); } } - Gun.on('out', coat); + cat.on('out', coat); } }()); ;(function(){ - Gun.on('put', function(at){ - //Gun.on.PUT = function(at){ - if(!at['#']){ return this.to.next(at) } // for tests. // TODO: REMOVE THIS! - var ev = this, ctx = {gun: at.gun, graph: at.gun._.graph, put: {}, map: {}, machine: Gun.state()}; + Gun.on.put = function(at){ + var cat = at.gun._, ctx = {gun: at.gun, graph: at.gun._.graph, put: {}, map: {}, 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) }) } + if(ctx.err){ return cat.on('in', {'@': at['#'], err: Gun.log(ctx.err) }) } obj_map(ctx.put, merge, ctx); obj_map(ctx.map, map, ctx); if(u !== ctx.defer){ - Gun.schedule(ctx.defer, function(){ - Gun.on('put', at); - }, Gun.state); + setTimeout(function(){ + Gun.on.put(at); + }, ctx.defer - cat.machine); } if(!ctx.diff){ return } - ev.to.next(obj_to(at, {put: ctx.diff})); - }); + cat.on('put', 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+"'!" } @@ -102,7 +99,7 @@ Gun._ = { // some reserved key words, these are not the only ones. (ctx.diff || (ctx.diff = {}))[soul] = Gun.state.to(node, key, ctx.diff[soul]); } function merge(node, soul){ - var ref = ((this.gun._).next || empty)[soul]; + var cat = this.gun._, ref = (cat.next || empty)[soul]; if(!ref){ return } var at = this.map[soul] = { put: this.node = node, @@ -110,7 +107,7 @@ Gun._ = { // some reserved key words, these are not the only ones. gun: this.ref = ref }; obj_map(node, each, this); - Gun.on('node', at); + cat.on('node', at); } function each(val, key){ var graph = this.graph, soul = this.soul, cat = (this.ref._), tmp; @@ -121,24 +118,18 @@ Gun._ = { // some reserved key words, these are not the only ones. if(!at.gun){ return } (at.gun._).on('in', at); } -}()); -;(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; + Gun.on.get = function(at){ + var cat = at.gun._, soul = at.get[_soul], 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(!node || !as){ return cat.on('get', at) } if(field){ - if(!obj_has(node, field)){ return ev.to.next(at) } + if(!obj_has(node, field)){ return cat.on('get', 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? - //} else { - // cat = (at.gun._); - //} + node = Gun.graph.node(node); tmp = as.ack; cat.on('in', { '@': at['#'], @@ -149,14 +140,14 @@ Gun._ = { // some reserved key words, these are not the only ones. if(0 < tmp){ return; } - ev.to.next(at); - }); + cat.on('get', at); + } }()); ;(function(){ Gun.on.ask = function(cb, as){ if(!this.on){ return } - var id = Gun.text.random(); + var id = text_rand(9); if(cb){ this.on(id, cb, as) } return id; } @@ -183,7 +174,9 @@ Gun._ = { // some reserved key words, these are not the only ones. if(!obj_is(at.opt.peers)){ at.opt.peers = {}} at.opt.peers = obj_to(tmp, at.opt.peers); } - at.opt.wsc = at.opt.wsc || {protocols:[]} + at.opt.uuid = at.opt.uuid || function(){ + return state().toString(36).replace('.','') + text_rand(12); + } at.opt.peers = at.opt.peers || {}; obj_to(opt, at.opt); // copies options on to `at.opt` only if not already taken. Gun.on('opt', at); @@ -191,10 +184,10 @@ Gun._ = { // some reserved key words, these are not the only ones. } }()); -var text_is = Gun.text.is; var list_is = Gun.list.is; +var text = Gun.text, text_is = text.is, text_rand = text.random; 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 state = Gun.state, _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) }; @@ -209,4 +202,6 @@ Gun.log.once("welcome", "Hello wonderful person! :) Thanks for using GUN, feel f if(typeof window !== "undefined"){ window.Gun = Gun } if(typeof common !== "undefined"){ common.exports = Gun } module.exports = Gun; + +Gun.log.once("0.8", "0.8 WARNING! Breaking changes, test that your app works before upgrading! The adapter interface has been upgraded (non-default storage and transport layers probably won't work). Also, `.path()` and `.not()` are outside core and now in 'lib/'."); \ No newline at end of file diff --git a/src/schedule.js b/src/schedule.js deleted file mode 100644 index c69610a0..00000000 --- a/src/schedule.js +++ /dev/null @@ -1,39 +0,0 @@ - -// Generic javascript scheduler utility. -var Type = require('./type'); -function s(state, cb, time){ // maybe use lru-cache? - s.time = time; - s.waiting.push({when: state, event: cb || function(){}}); - if(s.soonest < state){ return } - s.set(state); -} -s.waiting = []; -s.soonest = Infinity; -s.sort = Type.list.sort('when'); -s.set = function(future){ - if(Infinity <= (s.soonest = future)){ return } - var now = s.time(); - future = (future <= now)? 0 : (future - now); - clearTimeout(s.id); - s.id = setTimeout(s.check, future); -} -s.each = function(wait, i, map){ - var ctx = this; - if(!wait){ return } - if(wait.when <= ctx.now){ - if(wait.event instanceof Function){ - setTimeout(function(){ wait.event() },0); - } - } else { - ctx.soonest = (ctx.soonest < wait.when)? ctx.soonest : wait.when; - map(wait); - } -} -s.check = function(){ - var ctx = {now: s.time(), soonest: Infinity}; - s.waiting.sort(s.sort); - s.waiting = Type.list.map(s.waiting, s.each, ctx) || []; - s.set(ctx.soonest); -} -module.exports = s; - \ No newline at end of file diff --git a/src/set.js b/src/set.js index 8371b344..d2113180 100644 --- a/src/set.js +++ b/src/set.js @@ -1,15 +1,15 @@ -var Gun = require('./core'); +var Gun = require('./index'); Gun.chain.set = function(item, cb, opt){ var gun = this, soul; cb = cb || function(){}; if(soul = Gun.node.soul(item)){ return gun.set(gun.back(-1).get(soul), cb, opt) } if(!Gun.is(item)){ if(Gun.obj.is(item)){ return gun.set(gun._.root.put(item), cb, opt) } - return gun.get(Gun.text.random()).put(item); + return gun.get(gun._.root._.opt.uuid()).put(item); } item.get('_').get(function(at, ev){ - if(!at.gun || !at.gun._.back); + if(!at.gun || !at.gun._.back){ return } ev.off(); at = (at.gun._.back._); var put = {}, node = at.put, soul = Gun.node.soul(node); diff --git a/src/type.js b/src/type.js index 7f351438..bb684f97 100644 --- a/src/type.js +++ b/src/type.js @@ -106,7 +106,7 @@ Type.obj.copy = function(o){ // because http://web.archive.org/web/2014032822402 var u, i = 0, x, r, ll, lle, f = fn_is(c); t.r = null; if(keys && obj_is(l)){ - ll = Object.keys(l); lle = true; + ll = keys(l); lle = true; } if(list_is(l) || ll){ x = (ll || l).length;