diff --git a/gun.js b/gun.js index e01b93ce..2014ec62 100644 --- a/gun.js +++ b/gun.js @@ -807,25 +807,9 @@ Gun.on.get = function(msg, gun){ var root = gun._, get = msg.get, soul = get[_soul], node = root.graph[soul], has = get[_has], tmp; var next = root.next || (root.next = {}), at = next[soul]; - if(obj_has(soul, '*')){ // TEMPORARY HACK FOR MARTTI, TESTING - var graph = {}; - Gun.obj.map(root.graph, function(node, s){ - if(Gun.text.match(s, soul)){ - graph[s] = Gun.obj.copy(node); - } - }); - if(!Gun.obj.empty(graph)){ - root.on('in', { - '@': msg['#'], - how: '*', - put: graph, - $: gun - }); - } - } // TEMPORARY HACK FOR MARTTI, TESTING if(!node){ return root.on('get', msg) } if(has){ - if(!obj_has(node, has)){ return root.on('get', msg) } + if('string' != typeof has || !obj_has(node, has)){ return root.on('get', msg) } node = Gun.state.to(node, has); // If we have a key in-memory, do we really need to fetch? // Maybe... in case the in-memory key we have is a local write @@ -966,6 +950,7 @@ at.on('in', at); return; }*/ + if(at.lex){ msg.get = obj_to(at.lex, msg.get) } if(get['#'] || at.soul){ get['#'] = get['#'] || at.soul; msg['#'] || (msg['#'] = text_rand(9)); @@ -988,6 +973,17 @@ get: back.get }); if(tmp){ return } + } else + if('string' != typeof get){ + var put = {}, meta = (back.put||{})._; + Gun.obj.map(back.put, function(v,k){ + if(!Gun.text.match(k, get)){ return } + put[k] = v; + }) + if(!Gun.obj.empty(put)){ + put._ = meta; + back.on('in', {$: back.$, put: put, get: back.get}) + } } root.ask(ack, msg); return root.on('in', msg); @@ -1087,7 +1083,6 @@ relate(cat, msg, at, rel); echo(cat, msg, eve); } - var C = 0; function relate(at, msg, from, rel){ if(!rel || node_ === at.get){ return } @@ -1203,7 +1198,7 @@ function ack(msg, ev){ var as = this.as, get = as.get || empty, at = as.$._, tmp = (msg.put||empty)[get['#']]; if(at.ack){ at.ack = (at.ack + 1) || 1; } - if(!msg.put || (get['.'] && !obj_has(tmp, at.get))){ + if(!msg.put || ('string' == typeof get['.'] && !obj_has(tmp, at.get))){ if(at.put !== u){ return } at.on('in', { get: at.get, @@ -1259,12 +1254,18 @@ } else if(tmp = rel.is(key)){ return this.get(tmp, cb, as); + } else + if(obj.is(key)){ + gun = this; + if(tmp = ((tmp = key['#'])||empty)['='] || tmp){ gun = gun.get(tmp) } + gun._.lex = key; + return gun; } else { (as = this.chain())._.err = {err: Gun.log('Invalid get request!', key)}; // CLEAN UP if(cb){ cb.call(as, as._.err) } return as; } - if(tmp = cat.stun){ // TODO: Refactor? + if(tmp = this._.stun){ // TODO: Refactor? gun._.stun = gun._.stun || tmp; } if(cb && cb instanceof Function){ @@ -1748,8 +1749,9 @@ } function each(v,k){ if(n_ === k){ return } - var msg = this.msg, gun = msg.$, at = this.at, tmp = (gun.get(k)._); - (tmp.echo || (tmp.echo = {}))[at.id] = tmp.echo[at.id] || at; + var msg = this.msg, gun = msg.$, at = gun._, cat = this.at, tmp = at.lex; + if(tmp && !Gun.text.match(k, tmp['.'] || tmp['#'] || tmp)){ return } // TODO: Ugly hack! + ((tmp = gun.get(k)._).echo || (tmp.echo = {}))[cat.id] = tmp.echo[cat.id] || cat; } var obj_map = Gun.obj.map, noop = function(){}, event = {stun: noop, off: noop}, n_ = Gun.node._, u; })(USE, './map'); diff --git a/gun.min.js b/gun.min.js index 2a6b24fd..14a5c717 100644 --- a/gun.min.js +++ b/gun.min.js @@ -1 +1 @@ -!function(){var t;"undefined"!=typeof window&&(t=window),"undefined"!=typeof global&&(t=global);var b=(t=t||{}).console||{log:function(){}};function _(o,t){return t?require(o):o.slice?_[e(o)]:function(t,n){o(t={exports:{}}),_[e(n)]=t.exports};function e(t){return t.split("/").slice(-1).toString().replace(".js","")}}if("undefined"!=typeof module)var f=module;_(function(t){var p={fn:{is:function(t){return!!t&&"function"==typeof t}}};p.bi={is:function(t){return t instanceof Boolean||"boolean"==typeof t}},p.num={is:function(t){return!d(t)&&(0<=t-parseFloat(t)+1||1/0===t||-1/0===t)}},p.text={is:function(t){return"string"==typeof t}},p.text.ify=function(t){return p.text.is(t)?t:"undefined"!=typeof JSON?JSON.stringify(t):t&&t.toString?t.toString():t},p.text.random=function(t,n){var o="";for(t=t||24,n=n||"0123456789ABCDEFGHIJKLMNOPQRSTUVWXZabcdefghijklmnopqrstuvwxyz";0")){if(!(n>t[">"]))return!1;o=!0}if(p.obj.has(t,"<")){if(!(n",s.drift=0,s.is=function(t,n,o){var e=n&&t&&t[m]&&t[m][s._]||o;if(e)return g(e=e[n])?e:-1/0},s.lex=function(){return s().toString(36).replace(".","")},s.ify=function(t,n,o,e,i){if(!t||!t[m]){if(!i)return;t=a.soul.ify(t,i)}var r=c(t[m],s._);return void 0!==n&&n!==m&&(g(o)&&(r[n]=o),void 0!==e&&(t[n]=e)),t},s.to=function(t,n,o){var e=(t||{})[n];return p(e)&&(e=d(e)),s.ify(o,n,s.is(t,n),e,a.soul(t))},function(){function u(t,n){m!==n&&s.ify(this.o,n,this.s)}s.map=function(i,r,a){var t=p(t=i||r)?t:null;return i=v(i=i||r)?i:null,t&&!i?(r=g(r)?r:s(),t[m]=t[m]||{},h(t,u,{o:t,s:r}),t):(a=a||p(r)?r:void 0,r=g(r)?r:s(),function(t,n,o,e){if(!i)return u.call({o:o,s:r},t,n),t;i.call(a||this||{},t,n,o,e),l(o,n)&&void 0===o[n]||u.call({o:o,s:r},t,n)})}}();var f=n.obj,c=f.as,l=f.has,p=f.is,h=f.map,d=f.copy,g=n.num.is,v=n.fn.is,m=a._;t.exports=s})(_,"./state"),_(function(t){var a=_("./type"),f=_("./val"),c=_("./node"),r={};!function(){function i(t,n){if(!t||n!==c.soul(t)||!c.is(t,this.fn,this.as))return!0;this.cb&&(o.n=t,o.as=this.as,this.cb.call(o.as,t,n,o))}function o(t){t&&c.is(o.n,t,o.as)}r.is=function(t,n,o,e){return!(!t||!l(t)||u(t))&&!s(t,i,{cb:n,fn:o,as:e})}}(),function(){function u(t,n){var o;return(o=function(t,n){var o,e=t.seen,i=e.length;for(;i--;)if(o=e[i],n.obj===o.obj)return o;e.push(n)}(t,n))?o:(n.env=t,n.soul=i,c.ify(n.obj,e,n)&&(n.rel=n.rel||f.rel.ify(c.soul(n.node)),n.obj!==t.shell&&(t.graph[f.rel.is(n.rel)]=n.node)),n)}function e(t,n,o){var e,i,r=this,a=r.env;if(c._===n&&h(t,f.rel._))return o._;if(e=s(t,n,o,r,a)){if(n||(r.node=r.node||o||{},h(t,c._)&&c.soul(t)&&(r.node._=d(t._)),r.node=c.soul.ify(r.node,f.rel.is(r.rel)),r.rel=r.rel||f.rel.ify(c.soul(r.node))),(i=a.map)&&(i.call(a.as||{},t,n,o,r),h(o,n))){if(void 0===(t=o[n]))return void p(o,n);if(!(e=s(t,n,o,r,a)))return}if(!n)return r.node;if(!0===e)return t;if((i=u(a,{obj:t,path:r.path.concat(n)})).node)return i.rel}}function i(t){var n=this,o=f.link.is(n.rel),e=n.env.graph;n.rel=n.rel||f.rel.ify(t),n.rel[f.rel._]=t,n.node&&n.node[c._]&&(n.node[c._][f.rel._]=t),h(e,o)&&(e[t]=e[o],p(e,o))}function s(t,n,o,e,i){var r;return!!f.is(t)||(l(t)?1:(r=i.invalid)?s(t=r.call(i.as||{},t,n,o),n,o,e,i):(i.err="Invalid value at '"+e.path.concat(n).join(".")+"'!",void(a.list.is(t)&&(i.err+=" Use `.set(item)` instead of an Array."))))}r.ify=function(t,n,o){var e={path:[],obj:t};return n?"string"==typeof n?n={soul:n}:n instanceof Function&&(n.map=n):n={},n.soul&&(e.rel=f.rel.ify(n.soul)),n.shell=(o||{}).shell,n.graph=n.graph||{},n.seen=n.seen||[],n.as=n.as||o,u(n,e),n.root=e.node,n.graph}}(),r.node=function(t){var n=c.soul(t);if(n)return o({},n,t)},function(){function i(t,n){var o,e;if(c._!==n)(o=f.rel.is(t))?(e=this.opt.seen[o])?this.obj[n]=e:this.obj[n]=this.opt.seen[o]=r.to(this.graph,o,this.opt):this.obj[n]=t;else{if(u(t,f.rel._))return;this.obj[n]=d(t)}}r.to=function(t,n,o){if(t){var e={};return o=o||{seen:{}},s(t[n],i,{obj:e,graph:t,opt:o}),e}}}();a.fn.is;var n=a.obj,l=n.is,p=n.del,h=n.has,u=n.empty,o=n.put,s=n.map,d=n.copy;t.exports=r})(_,"./graph"),_(function(t){_("./onto"),t.exports=function(t,n){if(this.on){if(!(t instanceof Function)){if(!t||!n)return;var o=t["#"]||t,e=(this.tag||empty)[o];if(!e)return;return e=this.on(o,n),clearTimeout(e.err),!0}o=n&&n["#"]||Math.random().toString(36).slice(2);if(!t)return o;var i=this.on(o,t,n);return i.err=i.err||setTimeout(function(){i.next({err:"Error: No ACK received yet.",lack:!0}),i.off()},(this.opt||{}).lack||9e3),o}}})(_,"./ask"),_(function(t){var r=_("./type");var a=r.time.is;t.exports=function(e){var i={s:{}};return e=e||{max:1e3,age:9e3},i.check=function(t){var n;return!!(n=i.s[t])&&(n.pass?n.pass=!1:i.track(t))},i.track=function(t,n){var o=i.s[t]||(i.s[t]={});return o.was=a(),n&&(o.pass=!0),i.to||(i.to=setTimeout(function(){var o=a();r.obj.map(i.s,function(t,n){t&&e.age>o-t.was||r.obj.del(i.s,n)}),i.to=null},e.age+9)),o},i}})(_,"./dup"),_(function(t){function c(t){return t instanceof c?(this._={gun:this,$:this}).$:this instanceof c?c.create(this._={gun:this,$:this,opt:t}):new c(t)}c.is=function(t){return t instanceof c||t&&t._&&t===t._.$||!1},c.version=.9,(c.chain=c.prototype).toJSON=function(){};var n=_("./type");n.obj.to(n,c),c.HAM=_("./HAM"),c.val=_("./val"),c.node=_("./node"),c.state=_("./state"),c.graph=_("./graph"),c.on=_("./onto"),c.ask=_("./ask"),c.dup=_("./dup"),function(){function a(t){var n,o,e=this.as,i=e.at||e,r=i.$;(o=t["#"])||(o=t["#"]=u(9)),(n=i.dup).check(o)?e.out===t.out&&(t.out=void 0,this.to.next(t)):(n.track(o),i.ask(t["@"],t)||(t.get&&c.on.get(t,r),t.put&&c.on.put(t,r)),this.to.next(t),e.out||(t.out=a,i.on("out",t)))}c.create=function(t){t.root=t.root||t,t.graph=t.graph||{},t.on=t.on||c.on,t.ask=t.ask||c.ask,t.dup=t.dup||c.dup();var n=t.$.opt(t.opt);return t.once||(t.on("in",a,t),t.on("out",a,{at:t,out:a}),c.on("create",t),t.on("create",t)),t.once=1,n}}(),function(){function i(t,n,o,e){var i=this,r=c.state.is(o,n);if(!r)return i.err="Error: No state on '"+n+"' in node '"+e+"'!";var a=i.graph[e]||v,u=c.state.is(a,n,!0),s=a[n],f=c.HAM(i.machine,r,u,t,s);f.incoming?(i.put[e]=c.state.to(o,n,i.put[e]),(i.diff||(i.diff={}))[e]=c.state.to(o,n,i.diff[e]),i.souls[e]=!0):f.defer&&(i.defer=r<(i.defer||1/0)?r:i.defer)}function r(t,n){var o=this,e=o.$._,i=(e.next||v)[n];if(!i){if(!(e.opt||v).super)return void(o.souls[n]=!1);i=o.$.get(n)._}var r=o.map[n]={put:t,get:n,$:i.$},a={ctx:o,msg:r};o.async=!!e.tag.node,o.ack&&(r["@"]=o.ack),h(t,u,a),o.async&&(o.and||e.on("node",function(t){this.to.next(t),t===o.map[t.get]&&(o.souls[t.get]=!1,h(t.put,s,t),h(o.souls,function(t){if(t)return t})||o.c||(o.c=1,this.off(),h(o.map,f,o)))}),o.and=!0,e.on("node",r))}function u(t,n){var o=this.ctx,e=o.graph,i=this.msg,r=i.get,a=i.put,u=i.$._;e[r]=c.state.to(a,n,e[r]),o.async||(u.put=c.state.to(a,n,u.put))}function s(t,n){var o=this.put,e=this.$._;e.put=c.state.to(o,n,e.put)}function f(t,n){t.$&&(this.cat.stop=this.stop,t.$._.on("in",t),this.cat.stop=null)}c.on.put=function(t,n){var o=n._,e={$:n,graph:o.graph,put:{},map:{},souls:{},machine:c.state(),ack:t["@"],cat:o,stop:{}};if(c.graph.is(t.put,null,i,e)||(e.err="Error: Invalid graph!"),e.err)return o.on("in",{"@":t["#"],err:c.log(e.err)});h(e.put,r,e),e.async||h(e.map,f,e),void 0!==e.defer&&setTimeout(function(){c.on.put(t,n)},e.defer-e.machine),e.diff&&o.on("put",p(t,{put:e.diff}))},c.on.get=function(t,n){var o=n._,e=t.get,i=e[d],r=o.graph[i],a=e[g],u=(o.next||(o.next={}))[i];if(l(i,"*")){var s={};c.obj.map(o.graph,function(t,n){c.text.match(n,i)&&(s[n]=c.obj.copy(t))}),c.obj.empty(s)||o.on("in",{"@":t["#"],how:"*",put:s,$:n})}if(!r)return o.on("get",t);if(a){if(!l(r,a))return o.on("get",t);r=c.state.to(r,a)}else r=c.obj.copy(r);r=c.graph.node(r),(u||v).ack,o.on("in",{"@":t["#"],how:"mem",put:r,$:n}),o.on("get",t)}}(),c.chain.opt=function(t){t=t||{};var n=this._,o=t.peers||t;return a(t)||(t={}),a(n.opt)||(n.opt=t),i(o)&&(o=[o]),e(o)&&(o=h(o,function(t,n,o){o(t,{url:t})}),a(n.opt.peers)||(n.opt.peers={}),n.opt.peers=p(o,n.opt.peers)),n.opt.peers=n.opt.peers||{},p(t,n.opt),c.on("opt",n),n.opt.uuid=n.opt.uuid||function(){return s()+u(12)},this};var e=c.list.is,o=c.text,i=o.is,u=o.random,r=c.obj,a=r.is,l=r.has,p=r.to,h=r.map,s=(r.copy,c.state.lex),d=c.val.rel._,g=".",v=(c.node._,c.val.link.is,{});b.debug=function(t,n){return b.debug.i&&t===b.debug.i&&b.debug.i++&&(b.log.apply(b,arguments)||n)},(c.log=function(){return!c.log.off&&b.log.apply(b,arguments),[].slice.call(arguments).join(" ")}).once=function(t,n,o){return(o=c.log.once)[t]=o[t]||0,o[t]++||c.log(n)},c.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=window.Gun=c).window=window);try{void 0!==f&&(f.exports=c)}catch(t){}t.exports=c})(_,"./root"),_(function(t){var u=_("./root");u.chain.back=function(t,n){if(-1===(t=t||1)||1/0===t)return this._.root.$;if(1===t)return(this._.back||this._).$;var o=this._;if("string"==typeof t&&(t=t.split(".")),t instanceof Array){for(var e=0,i=t.length,r=o;e .once, apologies unexpected."),this.once(t,n)},f.chain.once=function(t,n){var o=this,e=o._,i=e.put;if(0=(a.batch||1e3))return f();e||(e=setTimeout(f,a.wait||1))}),r.on("get",function(n){this.to.next(n);var o,e,i=n.get;function t(){if(i&&(o=i["#"])){var t=i["."];(e=s[o]||void 0)&&t&&(e=Gun.state.to(e,t)),(e||Gun.obj.empty(a.peers))&&r.on("in",{"@":n["#"],put:Gun.graph.node(e),how:"lS",lS:n.$||r.$})}}Gun.debug?setTimeout(t,1):t()});var n=function(t,n,o,e){s[e]=Gun.state.to(o,n,s[e])},f=function(t){var o;u=0,clearTimeout(e),e=!1;var n=i;i={},t&&(s=t);try{p.setItem(a.prefix,JSON.stringify(s))}catch(t){Gun.log(o=(t||"localStorage failure")+" Consider using GUN's IndexedDB plugin for RAD for more storage space, temporary example at https://github.com/amark/gun/blob/master/test/tmp/indexedDB.html ."),r.on("localStorage:error",{err:o,file:a.prefix,flush:s,retry:f})}(o||Gun.obj.empty(a.peers))&&Gun.obj.map(n,function(t,n){r.on("in",{"@":n,err:o,ok:0})})}}})}})(_,"./adapters/localStorage"),_(function(t){var g=_("../type");function o(p){var h=function(){},d=p.opt||{};return d.log=d.log||b.log,d.gap=d.gap||d.wait||1,d.pack=d.pack||.3*(d.memory?1e3*d.memory*1e3:1399e6),h.out=function(t){var n;if(this.to&&this.to.next(t),(n=t["@"])&&(n=p.dup.s[n])&&(n=n.it)&&n._)return h.say(t,n._.via,1),void(n["##"]=t["##"]);h.say(t)},p.on("create",function(t){t.opt.pid=t.opt.pid||g.text.random(9),this.to.next(t),p.on("out",h.out)}),h.hear=function(t,n){if(t){var o,e,i,r=p.dup,a=t[0];if(d.pack<=t.length)return h.say({dam:"!",err:"Message too big!"},n);try{i=JSON.parse(t)}catch(t){d.log("DAM JSON parse error",t)}if("{"===a){if(!i)return;if(r.check(o=i["#"]))return;if((a=(r.track(o,!0).it=i)["@"])&&i.put&&(a+=e=i["##"]||(i["##"]=h.hash(i)))!=o){if(r.check(a))return;(a=r.s)[e]=a[o]}return(i._=function(){}).via=n,(a=i["><"])&&(i._.to=g.obj.map(a.split(","),function(t,n,o){o(t,!0)})),i.dam?void((a=h.hear[i.dam])&&a(i,n,p)):void p.on("in",i)}if("["!==a);else{if(!i)return;for(var u,s=0;u=i[s++];)h.hear(u,n)}}},function(){function a(t){var n=t.batch;if(n&&(t.batch=t.tail=null,n.length))try{u(JSON.stringify(n),t)}catch(t){d.log("DAM JSON stringify error",t)}}function u(n,o){var t=o.wire;try{t.send?t.send(n):o.say&&o.say(n)}catch(t){(o.queue=o.queue||[]).push(n)}}h.say=function(n,t,o){var e,i,r;if(t){if((t.wire||d.wire&&d.wire(t))&&(i=n._||s,t!==i.via&&((r=i.raw)||(r=h.raw(n)),!((e=n["@"])&&(e=p.dup.s[e])&&(e=e.it)&&e.get&&e["##"]&&e["##"]===n["##"])&&(!(e=i.to)||!e[t.url]&&!e[t.id]||o)))){if(t.batch){if(t.tail=(t.tail||0)+r.length,t.tail<=d.pack)return void t.batch.push(r);a(t)}t.batch=[],setTimeout(function(){a(t)},d.gap),u(r,t)}}else g.obj.map(d.peers,function(t){h.say(n,t)})}}(),function(){function f(t,n){var o;return n instanceof Object?(g.obj.map(Object.keys(n).sort(),e,{to:o={},on:n}),o):n}function e(t){this.to[t]=this.on[t]}h.raw=function(t){if(!t)return"";var n,o,e,i=p.dup,r=t._||{};if(e=r.raw)return e;if("string"==typeof t)return t;t["@"]&&(e=t.put)&&((o=t["##"])||(n=c(e,f)||"",o=h.hash(t,n),t["##"]=o),(e=i.s)[o=t["@"]+o]=e[t["#"]],t["#"]=o||t["#"],n&&((t=g.obj.to(t)).put=l));var a=0,u=[];g.obj.map(d.peers,function(t){if(u.push(t.url||t.id),9<++a)return!0}),t["><"]=u.join();var s=c(t);return v!==n&&(e=s.indexOf(l,s.indexOf("put")),s=s.slice(0,e-1)+n+s.slice(e+l.length+1)),r&&(r.raw=s),s},h.hash=function(t,n){return o.hash(n||c(t.put,f)||"")||t["#"]||g.text.random(9)};var c=JSON.stringify,l=":])([:"}(),h.hi=function(n){var t=n.wire||{};n.id||n.url?(d.peers[n.url||n.id]=n,g.obj.del(d.peers,t.id)):(t=t.id=t.id||g.text.random(9),h.say({dam:"?"},d.peers[t]=n)),t.hied||p.on(t.hied="hi",n),t=n.queue,n.queue=[],g.obj.map(t,function(t){h.say(t,n)})},h.bye=function(t){g.obj.del(d.peers,t.id),p.on("bye",t)},h.hear["!"]=function(t,n){d.log("Error:",t.err)},h.hear["?"]=function(t,n){if(!t.pid)return h.say({dam:"?",pid:d.pid,"@":t["#"]},n);n.id=n.id||t.pid,h.hi(n)},h}o.hash=function(t){if("string"!=typeof t)return{err:1};var n=0;if(!t.length)return n;for(var o=0,e=t.length;o")){if(!(n>t[">"]))return!1;o=!0}if(p.obj.has(t,"<")){if(!(n",s.drift=0,s.is=function(t,n,o){var i=n&&t&&t[m]&&t[m][s._]||o;if(i)return g(i=i[n])?i:-1/0},s.lex=function(){return s().toString(36).replace(".","")},s.ify=function(t,n,o,i,e){if(!t||!t[m]){if(!e)return;t=a.soul.ify(t,e)}var r=c(t[m],s._);return void 0!==n&&n!==m&&(g(o)&&(r[n]=o),void 0!==i&&(t[n]=i)),t},s.to=function(t,n,o){var i=(t||{})[n];return p(i)&&(i=d(i)),s.ify(o,n,s.is(t,n),i,a.soul(t))},function(){function u(t,n){m!==n&&s.ify(this.o,n,this.s)}s.map=function(e,r,a){var t=p(t=e||r)?t:null;return e=v(e=e||r)?e:null,t&&!e?(r=g(r)?r:s(),t[m]=t[m]||{},h(t,u,{o:t,s:r}),t):(a=a||p(r)?r:void 0,r=g(r)?r:s(),function(t,n,o,i){if(!e)return u.call({o:o,s:r},t,n),t;e.call(a||this||{},t,n,o,i),l(o,n)&&void 0===o[n]||u.call({o:o,s:r},t,n)})}}();var f=n.obj,c=f.as,l=f.has,p=f.is,h=f.map,d=f.copy,g=n.num.is,v=n.fn.is,m=a._;t.exports=s})(_,"./state"),_(function(t){var a=_("./type"),f=_("./val"),c=_("./node"),r={};!function(){function e(t,n){if(!t||n!==c.soul(t)||!c.is(t,this.fn,this.as))return!0;this.cb&&(o.n=t,o.as=this.as,this.cb.call(o.as,t,n,o))}function o(t){t&&c.is(o.n,t,o.as)}r.is=function(t,n,o,i){return!(!t||!l(t)||u(t))&&!s(t,e,{cb:n,fn:o,as:i})}}(),function(){function u(t,n){var o;return(o=function(t,n){var o,i=t.seen,e=i.length;for(;e--;)if(o=i[e],n.obj===o.obj)return o;i.push(n)}(t,n))?o:(n.env=t,n.soul=e,c.ify(n.obj,i,n)&&(n.link=n.link||f.link.ify(c.soul(n.node)),n.obj!==t.shell&&(t.graph[f.link.is(n.link)]=n.node)),n)}function i(t,n,o){var i,e,r=this,a=r.env;if(c._===n&&h(t,f.link._))return o._;if(i=s(t,n,o,r,a)){if(n||(r.node=r.node||o||{},h(t,c._)&&c.soul(t)&&(r.node._=d(t._)),r.node=c.soul.ify(r.node,f.link.is(r.link)),r.link=r.link||f.link.ify(c.soul(r.node))),(e=a.map)&&(e.call(a.as||{},t,n,o,r),h(o,n))){if(void 0===(t=o[n]))return void p(o,n);if(!(i=s(t,n,o,r,a)))return}if(!n)return r.node;if(!0===i)return t;if((e=u(a,{obj:t,path:r.path.concat(n)})).node)return e.link}}function e(t){var n=this,o=f.link.is(n.link),i=n.env.graph;n.link=n.link||f.link.ify(t),n.link[f.link._]=t,n.node&&n.node[c._]&&(n.node[c._][f.link._]=t),h(i,o)&&(i[t]=i[o],p(i,o))}function s(t,n,o,i,e){var r;return!!f.is(t)||(l(t)?1:(r=e.invalid)?s(t=r.call(e.as||{},t,n,o),n,o,i,e):(e.err="Invalid value at '"+i.path.concat(n).join(".")+"'!",void(a.list.is(t)&&(e.err+=" Use `.set(item)` instead of an Array."))))}r.ify=function(t,n,o){var i={path:[],obj:t};return n?"string"==typeof n?n={soul:n}:n instanceof Function&&(n.map=n):n={},n.soul&&(i.link=f.link.ify(n.soul)),n.shell=(o||{}).shell,n.graph=n.graph||{},n.seen=n.seen||[],n.as=n.as||o,u(n,i),n.root=i.node,n.graph}}(),r.node=function(t){var n=c.soul(t);if(n)return o({},n,t)},function(){function e(t,n){var o,i;if(c._!==n)(o=f.link.is(t))?(i=this.opt.seen[o])?this.obj[n]=i:this.obj[n]=this.opt.seen[o]=r.to(this.graph,o,this.opt):this.obj[n]=t;else{if(u(t,f.link._))return;this.obj[n]=d(t)}}r.to=function(t,n,o){if(t){var i={};return o=o||{seen:{}},s(t[n],e,{obj:i,graph:t,opt:o}),i}}}();a.fn.is;var n=a.obj,l=n.is,p=n.del,h=n.has,u=n.empty,o=n.put,s=n.map,d=n.copy;t.exports=r})(_,"./graph"),_(function(t){_("./onto"),t.exports=function(t,n){if(this.on){if(!(t instanceof Function)){if(!t||!n)return;var o=t["#"]||t,i=(this.tag||empty)[o];if(!i)return;return i=this.on(o,n),clearTimeout(i.err),!0}o=n&&n["#"]||Math.random().toString(36).slice(2);if(!t)return o;var e=this.on(o,t,n);return e.err=e.err||setTimeout(function(){e.next({err:"Error: No ACK received yet.",lack:!0}),e.off()},(this.opt||{}).lack||9e3),o}}})(_,"./ask"),_(function(t){var r=_("./type");var a=r.time.is;t.exports=function(i){var e={s:{}};return i=i||{max:1e3,age:9e3},e.check=function(t){var n;return!!(n=e.s[t])&&(n.pass?n.pass=!1:e.track(t))},e.track=function(t,n){var o=e.s[t]||(e.s[t]={});return o.was=a(),n&&(o.pass=!0),e.to||(e.to=setTimeout(function(){var o=a();r.obj.map(e.s,function(t,n){t&&i.age>o-t.was||r.obj.del(e.s,n)}),e.to=null},i.age+9)),o},e}})(_,"./dup"),_(function(t){function c(t){return t instanceof c?(this._={gun:this,$:this}).$:this instanceof c?c.create(this._={gun:this,$:this,opt:t}):new c(t)}c.is=function(t){return t instanceof c||t&&t._&&t===t._.$||!1},c.version=.9,(c.chain=c.prototype).toJSON=function(){};var n=_("./type");n.obj.to(n,c),c.HAM=_("./HAM"),c.val=_("./val"),c.node=_("./node"),c.state=_("./state"),c.graph=_("./graph"),c.on=_("./onto"),c.ask=_("./ask"),c.dup=_("./dup"),function(){function a(t){var n,o,i=this.as,e=i.at||i,r=e.$;(o=t["#"])||(o=t["#"]=u(9)),(n=e.dup).check(o)?i.out===t.out&&(t.out=void 0,this.to.next(t)):(n.track(o),e.ask(t["@"],t)||(t.get&&c.on.get(t,r),t.put&&c.on.put(t,r)),this.to.next(t),i.out||(t.out=a,e.on("out",t)))}c.create=function(t){t.root=t.root||t,t.graph=t.graph||{},t.on=t.on||c.on,t.ask=t.ask||c.ask,t.dup=t.dup||c.dup();var n=t.$.opt(t.opt);return t.once||(t.on("in",a,t),t.on("out",a,{at:t,out:a}),c.on("create",t),t.on("create",t)),t.once=1,n}}(),function(){function e(t,n,o,i){var e=this,r=c.state.is(o,n);if(!r)return e.err="Error: No state on '"+n+"' in node '"+i+"'!";var a=e.graph[i]||v,u=c.state.is(a,n,!0),s=a[n],f=c.HAM(e.machine,r,u,t,s);f.incoming?(e.put[i]=c.state.to(o,n,e.put[i]),(e.diff||(e.diff={}))[i]=c.state.to(o,n,e.diff[i]),e.souls[i]=!0):f.defer&&(e.defer=r<(e.defer||1/0)?r:e.defer)}function r(t,n){var o=this,i=o.$._,e=(i.next||v)[n];if(!e){if(!(i.opt||v).super)return void(o.souls[n]=!1);e=o.$.get(n)._}var r=o.map[n]={put:t,get:n,$:e.$},a={ctx:o,msg:r};o.async=!!i.tag.node,o.ack&&(r["@"]=o.ack),h(t,u,a),o.async&&(o.and||i.on("node",function(t){this.to.next(t),t===o.map[t.get]&&(o.souls[t.get]=!1,h(t.put,s,t),h(o.souls,function(t){if(t)return t})||o.c||(o.c=1,this.off(),h(o.map,f,o)))}),o.and=!0,i.on("node",r))}function u(t,n){var o=this.ctx,i=o.graph,e=this.msg,r=e.get,a=e.put,u=e.$._;i[r]=c.state.to(a,n,i[r]),o.async||(u.put=c.state.to(a,n,u.put))}function s(t,n){var o=this.put,i=this.$._;i.put=c.state.to(o,n,i.put)}function f(t,n){t.$&&(this.cat.stop=this.stop,t.$._.on("in",t),this.cat.stop=null)}c.on.put=function(t,n){var o=n._,i={$:n,graph:o.graph,put:{},map:{},souls:{},machine:c.state(),ack:t["@"],cat:o,stop:{}};if(c.graph.is(t.put,null,e,i)||(i.err="Error: Invalid graph!"),i.err)return o.on("in",{"@":t["#"],err:c.log(i.err)});h(i.put,r,i),i.async||h(i.map,f,i),void 0!==i.defer&&setTimeout(function(){c.on.put(t,n)},i.defer-i.machine),i.diff&&o.on("put",p(t,{put:i.diff}))},c.on.get=function(t,n){var o=n._,i=t.get,e=i[d],r=o.graph[e],a=i[g],u=(o.next||(o.next={}))[e];if(!r)return o.on("get",t);if(a){if("string"!=typeof a||!l(r,a))return o.on("get",t);r=c.state.to(r,a)}else r=c.obj.copy(r);r=c.graph.node(r),(u||v).ack,o.on("in",{"@":t["#"],how:"mem",put:r,$:n}),o.on("get",t)}}(),c.chain.opt=function(t){t=t||{};var n=this._,o=t.peers||t;return a(t)||(t={}),a(n.opt)||(n.opt=t),e(o)&&(o=[o]),i(o)&&(o=h(o,function(t,n,o){o(t,{url:t})}),a(n.opt.peers)||(n.opt.peers={}),n.opt.peers=p(o,n.opt.peers)),n.opt.peers=n.opt.peers||{},p(t,n.opt),c.on("opt",n),n.opt.uuid=n.opt.uuid||function(){return s()+u(12)},this};var i=c.list.is,o=c.text,e=o.is,u=o.random,r=c.obj,a=r.is,l=r.has,p=r.to,h=r.map,s=(r.copy,c.state.lex),d=c.val.link._,g=".",v=(c.node._,c.val.link.is,{});b.debug=function(t,n){return b.debug.i&&t===b.debug.i&&b.debug.i++&&(b.log.apply(b,arguments)||n)},(c.log=function(){return!c.log.off&&b.log.apply(b,arguments),[].slice.call(arguments).join(" ")}).once=function(t,n,o){return(o=c.log.once)[t]=o[t]||0,o[t]++||c.log(n)},c.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=window.Gun=c).window=window);try{void 0!==f&&(f.exports=c)}catch(t){}t.exports=c})(_,"./root"),_(function(t){var u=_("./root");u.chain.back=function(t,n){if(-1===(t=t||1)||1/0===t)return this._.root.$;if(1===t)return(this._.back||this._).$;var o=this._;if("string"==typeof t&&(t=t.split(".")),t instanceof Array){for(var i=0,e=t.length,r=o;i .once, apologies unexpected."),this.once(t,n)},f.chain.once=function(t,n){var o=this,i=o._,e=i.put;if(0=(u.batch||1e3))return f();i||(i=setTimeout(f,u.wait||1))}),a.on("get",function(n){this.to.next(n);var o,i,e,r=n.get;function t(){if(r&&(o=r["#"])){var t=r["."];(i=s[o]||e)&&t&&(i=Gun.state.to(i,t)),(i||Gun.obj.empty(u.peers))&&a.on("in",{"@":n["#"],put:Gun.graph.node(i),how:"lS",lS:n.$||a.$})}}Gun.debug?setTimeout(t,1):t()});var n=function(t,n,o,i){s[i]=Gun.state.to(o,n,s[i])},f=function(t){var o;r=0,clearTimeout(i),i=!1;var n=e;e={},t&&(s=t);try{p.setItem(u.prefix,JSON.stringify(s))}catch(t){Gun.log(o=(t||"localStorage failure")+" Consider using GUN's IndexedDB plugin for RAD for more storage space, temporary example at https://github.com/amark/gun/blob/master/test/tmp/indexedDB.html ."),a.on("localStorage:error",{err:o,file:u.prefix,flush:s,retry:f})}(o||Gun.obj.empty(u.peers))&&Gun.obj.map(n,function(t,n){a.on("in",{"@":n,err:o,ok:0})})}}})}})(_,"./adapters/localStorage"),_(function(t){var g=_("../type");function o(p){var h=function(){},d=p.opt||{};return d.log=d.log||b.log,d.gap=d.gap||d.wait||1,d.pack=d.pack||.3*(d.memory?1e3*d.memory*1e3:1399e6),h.out=function(t){var n;if(this.to&&this.to.next(t),(n=t["@"])&&(n=p.dup.s[n])&&(n=n.it)&&n._)return h.say(t,n._.via,1),void(n["##"]=t["##"]);h.say(t)},p.on("create",function(t){t.opt.pid=t.opt.pid||g.text.random(9),this.to.next(t),p.on("out",h.out)}),h.hear=function(t,n){if(t){var o,i,e,r=p.dup,a=t[0];if(d.pack<=t.length)return h.say({dam:"!",err:"Message too big!"},n);try{e=JSON.parse(t)}catch(t){d.log("DAM JSON parse error",t)}if("{"===a){if(!e)return;if(r.check(o=e["#"]))return;if((a=(r.track(o,!0).it=e)["@"])&&e.put&&(a+=i=e["##"]||(e["##"]=h.hash(e)))!=o){if(r.check(a))return;(a=r.s)[i]=a[o]}return(e._=function(){}).via=n,(a=e["><"])&&(e._.to=g.obj.map(a.split(","),function(t,n,o){o(t,!0)})),e.dam?void((a=h.hear[e.dam])&&a(e,n,p)):void p.on("in",e)}if("["!==a);else{if(!e)return;for(var u,s=0;u=e[s++];)h.hear(u,n)}}},function(){function a(t){var n=t.batch;if(n&&(t.batch=t.tail=null,n.length))try{u(JSON.stringify(n),t)}catch(t){d.log("DAM JSON stringify error",t)}}function u(n,o){var t=o.wire;try{t.send?t.send(n):o.say&&o.say(n)}catch(t){(o.queue=o.queue||[]).push(n)}}h.say=function(n,t,o){var i,e,r;if(t){if((t.wire||d.wire&&d.wire(t))&&(e=n._||s,t!==e.via&&((r=e.raw)||(r=h.raw(n)),!((i=n["@"])&&(i=p.dup.s[i])&&(i=i.it)&&i.get&&i["##"]&&i["##"]===n["##"])&&(!(i=e.to)||!i[t.url]&&!i[t.id]||o)))){if(t.batch){if(t.tail=(t.tail||0)+r.length,t.tail<=d.pack)return void t.batch.push(r);a(t)}t.batch=[],setTimeout(function(){a(t)},d.gap),u(r,t)}}else g.obj.map(d.peers,function(t){h.say(n,t)})}}(),function(){function f(t,n){var o;return n instanceof Object?(g.obj.map(Object.keys(n).sort(),i,{to:o={},on:n}),o):n}function i(t){this.to[t]=this.on[t]}h.raw=function(t){if(!t)return"";var n,o,i,e=p.dup,r=t._||{};if(i=r.raw)return i;if("string"==typeof t)return t;t["@"]&&(i=t.put)&&((o=t["##"])||(n=c(i,f)||"",o=h.hash(t,n),t["##"]=o),(i=e.s)[o=t["@"]+o]=i[t["#"]],t["#"]=o||t["#"],n&&((t=g.obj.to(t)).put=l));var a=0,u=[];g.obj.map(d.peers,function(t){if(u.push(t.url||t.id),9<++a)return!0}),t["><"]=u.join();var s=c(t);return v!==n&&(i=s.indexOf(l,s.indexOf("put")),s=s.slice(0,i-1)+n+s.slice(i+l.length+1)),r&&(r.raw=s),s},h.hash=function(t,n){return o.hash(n||c(t.put,f)||"")||t["#"]||g.text.random(9)};var c=JSON.stringify,l=":])([:"}(),h.hi=function(n){var t=n.wire||{};n.id||n.url?(d.peers[n.url||n.id]=n,g.obj.del(d.peers,t.id)):(t=t.id=t.id||g.text.random(9),h.say({dam:"?"},d.peers[t]=n)),t.hied||p.on(t.hied="hi",n),t=n.queue,n.queue=[],g.obj.map(t,function(t){h.say(t,n)})},h.bye=function(t){g.obj.del(d.peers,t.id),p.on("bye",t)},h.hear["!"]=function(t,n){d.log("Error:",t.err)},h.hear["?"]=function(t,n){if(!t.pid)return h.say({dam:"?",pid:d.pid,"@":t["#"]},n);n.id=n.id||t.pid,h.hi(n)},h}o.hash=function(t){if("string"!=typeof t)return{err:1};var n=0;if(!t.length)return n;for(var o=0,i=t.length;o 1){ return } + if(++i > 1){ opt.log('RAD ERR: Radisk has callbacked multiple times, please report this as a BUG at github.com/amark/gun/issues ! ' + i); return } if(err){ opt.log('err', err) } map(batch.acks, function(cb){ cb(err, ok) }); thrash.at = null; @@ -90,7 +98,7 @@ 4. Read the previous file to that into memory 5. Scan through the in memory radix for all values lexically less than the limit. 6. Merge and write all of those to the in-memory file and back to disk. - 7. If file to large, split. More details needed here. + 7. If file too large, split. More details needed here. */ r.save = function(rad, cb){ var s = function Span(){}; @@ -142,6 +150,7 @@ f.count = 0; f.file = file; f.each = function(val, key, k, pre){ + //console.log("RAD:::", JSON.stringify([val, key, k, pre])); if(u !== val){ f.count++ } if(opt.pack <= (val||'').length){ return cb("Record too big!"), true } var enc = Radisk.encode(pre.length) +'#'+ Radisk.encode(k) + (u === val? '' : ':'+ Radisk.encode(val)) +'\n'; @@ -150,7 +159,7 @@ f.limit = Math.ceil(f.count/2); f.count = 0; f.sub = Radix(); - Radix.map(rad, f.slice) + Radix.map(rad, f.slice); return true; } f.text += enc; @@ -185,19 +194,21 @@ ;(function(){ var Q = {}; - r.read = function(key, cb, next){ - if(RAD && !next){ // cache + r.read = function(key, cb, o){ + o = o || {}; + if(RAD && !o.next){ // cache var val = RAD(key); - if(u !== val){ + //if(u !== val){ + //cb(u, val, o); + if(atomic(val)){ cb(u, val, o); return } // if a node is requested and some of it is cached... the other parts might not be. - return cb(u, val); - } + //} } var g = function Get(){}, tmp; g.lex = function(file){ file = (u === file)? u : decodeURIComponent(file); - if(!file || file > (next || key)){ - if(next){ g.file = file } + if(!file || file > (o.next || key)){ + if(o.next){ g.file = file } if(tmp = Q[g.file]){ tmp.push({key: key, ack: cb, file: g.file}); return true; @@ -208,20 +219,25 @@ } g.file = file; } - g.it = function(err, disk){ + g.it = function(err, disk, info){ if(g.err = err){ opt.log('err', err) } if(disk){ RAD = g.disk = disk } + o.parsed = (o.parsed || 0) + (info.parsed||0); + o.chunks = (o.chunks || 0) + 1; disk = Q[g.file]; delete Q[g.file]; map(disk, g.ack); } g.ack = function(as){ if(!as.ack){ return } var tmp = as.key, rad = g.disk || noop, data = rad(tmp), last = rad.last; - if(data){ as.ack(g.err, data) } - else if(!as.file){ return as.ack(g.err, u) } - if(!last || last === tmp){ return as.ack(g.err, u) } // is this correct? - if(last > tmp && 0 > last.indexOf(tmp)){ return as.ack(g.err, u) } - r.read(tmp, as.ack, as.file); + if(!o.some){ o.some = (u !== data) } + if(u !== data){ as.ack(g.err, data, o) } + else if(!as.file){ !o.some && as.ack(g.err, u, o); return } + if(!last || last === tmp){ !o.some && as.ack(g.err, u, o); return } + if(last > tmp && 0 != last.indexOf(tmp)){ !o.some && as.ack(g.err, u, o); return } + if(o.some && o.parsed >= o.limit){ return } + o.next = as.file; + r.read(tmp, as.ack, o); } r.list(g.lex); } @@ -236,14 +252,13 @@ Then we can work on the harder problem of being multi-process. */ var Q = {}, s = String.fromCharCode(31); - r.parse = function(file, cb){ var q; + r.parse = function(file, cb, raw){ var q; if(q = Q[file]){ return q.push(cb) } q = Q[file] = [cb]; - var p = function Parse(){}; + var p = function Parse(){}, info = {}; p.disk = Radix(); p.read = function(err, data){ var tmp; delete Q[file]; if((p.err = err) || (p.not = !data)){ - //return cb(err, u);//map(q, p.ack); return map(q, p.ack); } if(typeof data !== 'string'){ @@ -257,6 +272,10 @@ if(p.err){ return map(q, p.ack) } } var tmp = p.split(data), pre = [], i, k, v; + if(!tmp || 0 !== tmp[1]){ + p.err = "File '"+file+"' does not have root radix! "; + return map(q, p.ack); + } while(tmp){ k = v = u; i = tmp[1]; @@ -275,6 +294,7 @@ tmp = p.split(tmp[2]); } //cb(err, p.disk); + info.parsed = data.length; map(q, p.ack); }; p.split = function(t){ @@ -290,9 +310,10 @@ } p.ack = function(cb){ if(!cb){ return } - if(p.err || p.not){ return cb(p.err, u) } - cb(u, p.disk); + if(p.err || p.not){ return cb(p.err, u, info) } + cb(u, p.disk, info); } + if(raw){ return p.read(null, raw) } opt.store.get(ename(file), p.read); } }()); @@ -315,8 +336,11 @@ return cb(u, 1); } dir(file, true); + cb.listed = (cb.listed || 0) + 1; r.write(f, dir, function(err, ok){ if(err){ return cb(err) } + cb.listed = (cb.listed || 0) - 1; + if(cb.listed !== 0){ return } cb(u, 1); }, true); } @@ -353,6 +377,7 @@ }()); var noop = function(){}, RAD, u; + Radisk.has[opt.file] = r; return r; } diff --git a/lib/radix.js b/lib/radix.js index a0b270cb..03fa31bb 100644 --- a/lib/radix.js +++ b/lib/radix.js @@ -5,9 +5,9 @@ key = ''+key; if(!t && u !== val){ radix.last = (key < radix.last)? radix.last : key; - radix.sort = null; + delete (radix.$||{})[_]; } - t = t || radix[_] || (radix[_] = {}); + t = t || radix.$ || (radix.$ = {}); var i = 0, l = key.length-1, k = key[i], at, tmp; while(!(at = t[k]) && i < l){ k += key[++i]; @@ -15,9 +15,9 @@ if(!at){ if(!map(t, function(r, s){ var ii = 0, kk = ''; - while(s[ii] == key[ii]){ + if((s||'').length){ while(s[ii] == key[ii]){ kk += s[ii++]; - } + } } if(kk){ if(u === val){ if(ii <= l){ return } @@ -25,47 +25,52 @@ } var __ = {}; __[s.slice(ii)] = r; - (__[key.slice(ii)] = {})[$] = val; - (t[kk] = {})[_] = __; + ii = key.slice(ii); + ('' === ii)? (__[''] = val) : ((__[ii] = {})[''] = val); + t[kk] = __; delete t[s]; return true; } })){ if(u === val){ return; } - (t[k] || (t[k] = {}))[$] = val; + (t[k] || (t[k] = {}))[''] = val; } if(u === val){ return tmp; } } else if(i == l){ - if(u === val){ return (u === (tmp = at[$]))? at[_] : tmp } - at[$] = val; + if(u === val){ return (u === (tmp = at['']))? at : tmp } + at[''] = val; } else { - if(u !== val){ at.sort = null } - return radix(key.slice(++i), val, at[_] || (at[_] = {})); + if(u !== val){ delete at[_] } + return radix(key.slice(++i), val, at || (at = {})); } } return radix; }; Radix.map = function map(radix, cb, opt, pre){ pre = pre || []; - var t = radix[_] || radix, keys = radix.sort || (radix.sort = Object.keys(t).sort()), i = 0, l = keys.length; - for(;i < l; i++){ var key = keys[i], tree = t[key], tmp; - if(u !== (tmp = tree[$])){ - tmp = cb(tmp, pre.join('') + key, key, pre); + var t = ('function' == typeof radix)? radix.$ || {} : radix; + if(!t){ return } + var keys = (t[_]||no).sort || (t[_] = function $(){ $.sort = Object.keys(t).sort(); return $ }()).sort; + //var keys = Object.keys(t).sort(); + var i = 0, l = keys.length; + for(;i < l; i++){ var key = keys[i], tree = t[key], tmp, p; + if(!tree || '' === key || _ === key){ continue } + p = pre.slice(); p.push(key); + if(u !== (tmp = tree[''])){ + tmp = cb(tmp, p.join(''), key, pre); if(u !== tmp){ return tmp } - } else + } else if(opt){ - cb(u, pre.join(''), key, pre); - } - if(tmp = tree[_]){ - pre.push(key); - tmp = map(tree, cb, opt, pre); - //tmp = map(tmp, cb, opt, pre); + tmp = cb(u, pre.join(''), key, pre); if(u !== tmp){ return tmp } - pre.pop(); } + pre = p; + tmp = map(tree, cb, opt, pre); + if(u !== tmp){ return tmp } + pre.pop(); } }; @@ -80,6 +85,6 @@ } var map = Gun.obj.map, no = {}, u; - var $ = String.fromCharCode(30), _ = String.fromCharCode(29); + var _ = String.fromCharCode(24); }()); \ No newline at end of file diff --git a/lib/rfs.js b/lib/rfs.js index 05595a28..42a49e23 100644 --- a/lib/rfs.js +++ b/lib/rfs.js @@ -3,6 +3,7 @@ var Gun = (typeof window !== "undefined")? window.Gun : require('../gun'); function Store(opt){ opt = opt || {}; opt.file = String(opt.file || 'radata'); + if(Gun.TESTING){ opt.file = 'radatatest' } var fs = require('fs'), u; var store = function Store(){}; diff --git a/lib/rindexed.js b/lib/rindexed.js index 532e4e30..05683bed 100644 --- a/lib/rindexed.js +++ b/lib/rindexed.js @@ -9,11 +9,19 @@ function Store(opt){ opt = opt || {}; opt.file = String(opt.file || 'radata'); + if(Gun.TESTING){ opt.file = 'radatatest' } var db = null; - opt.indexedDB = opt.indexedDB || window.indexedDB; + try{opt.indexedDB = opt.indexedDB || indexedDB}catch(e){} + try{if(!opt.indexedDB || 'file:' == location.protocol){ + var store = {}, s = {}, u; + store.put = function(f, d, cb){ s[f] = d; cb(null, 1) }; + store.get = function(f, cb){ cb(null, s[f] || u) }; + return store; + }}catch(e){} + // Initialize indexedDB. Version 1. - var request = opt.indexedDB.open(opt.file, 1) + var request = opt.indexedDB.open(opt.file, 1); // Create schema. onupgradeneeded is called only when DB is first created or when the DB version increases. request.onupgradeneeded = function(event){ @@ -116,6 +124,10 @@ } }; checkFunc(); + try{ + //if(/^((?!chrome|android).)*safari/i.test(navigator.userAgent)){ return } + setTimeout(function(){ db && db.close(); db = null }, 1000 * 15); // reset webkit bug + }catch(e){} }; return store; diff --git a/lib/store.js b/lib/store.js index 10230707..72eaae62 100644 --- a/lib/store.js +++ b/lib/store.js @@ -1,58 +1,86 @@ var Gun = (typeof window !== "undefined")? window.Gun : require('../gun'); - + Gun.on('create', function(root){ - this.to.next(root); - var opt = root.opt, u; - if(false === opt.radisk){ return } - var Radisk = (Gun.window && Gun.window.Radisk) || require('./radisk'); - var Radix = Radisk.Radix; - - opt.store = opt.store || (!Gun.window && require('./rfs')(opt)); - var rad = Radisk(opt), esc = String.fromCharCode(27); - - root.on('put', function(msg){ - this.to.next(msg); - var id = msg['#'], track = !msg['@'], acks = track? 0 : u; // only ack non-acks. - if(msg.rad && !track){ return } // don't save our own acks - Gun.graph.is(msg.put, null, function(val, key, node, soul){ - if(track){ ++acks } - val = Radisk.encode(val, null, esc)+'>'+Radisk.encode(Gun.state.is(node, key), null, esc); - rad(soul+'.'+key, val, (track? ack : u)); - }); - function ack(err, ok){ - acks--; - if(ack.err){ return } - if(ack.err = err){ - root.on('in', {'@': id, err: err}); - return; - } - if(acks){ return } - root.on('in', {'@': id, ok: 1}); - } - }); - - root.on('get', function(msg){ - this.to.next(msg); - var id = msg['#'], soul = msg.get['#'], key = msg.get['.']||'', tmp = soul+'.'+key, node; - rad(tmp, function(err, val){ - if(val){ - if(val && typeof val !== 'string'){ - if(key){ - val = u; - } else { - Radix.map(val, each) - } - } - if(!node && val){ each(val, key) } - } - root.on('in', {'@': id, put: Gun.graph.node(node), err: err? err : u, rad: Radix}); - }); - function each(val, key){ - tmp = val.lastIndexOf('>'); - var state = Radisk.decode(val.slice(tmp+1), null, esc); - val = Radisk.decode(val.slice(0,tmp), null, esc); - node = Gun.state.ify(node, key, state, val, soul); - } - }); - + this.to.next(root); + var opt = root.opt, u; + if(false === opt.radisk){ return } + var Radisk = (Gun.window && Gun.window.Radisk) || require('./radisk'); + var Radix = Radisk.Radix; + + opt.store = opt.store || (!Gun.window && require('./rfs')(opt)); + var rad = Radisk(opt), esc = String.fromCharCode(27); + + root.on('put', function(msg){ + this.to.next(msg); + var id = msg['#'] || Gun.text.random(3), track = !msg['@'], acks = track? 0 : u; // only ack non-acks. + if(msg.rad && !track){ return } // don't save our own acks + Gun.graph.is(msg.put, null, function(val, key, node, soul){ + if(track){ ++acks } + //console.log('put:', soul, key, val); + val = Radisk.encode(val, null, esc)+'>'+Radisk.encode(Gun.state.is(node, key), null, esc); + //rad(soul+'.'+key, val, (track? ack : u)); + //console.log("PUT!", id, JSON.stringify(soul+esc+key)); + rad(soul+esc+key, val, (track? ack : u)); + }); + function ack(err, ok){ + acks--; + if(ack.err){ return } + if(ack.err = err){ + root.on('in', {'@': id, err: err}); + return; + } + if(acks){ return } + //console.log("PAT!", id); + root.on('in', {'@': id, ok: 1}); + } + }); + + root.on('get', function(msg){ + this.to.next(msg); + var id = msg['#'], get = msg.get, soul = msg.get['#'], has = msg.get['.']||'', opt = {}, graph, lex, key, tmp; + if(typeof soul == 'string'){ + key = soul; + } else + if(soul){ + if(tmp = soul['*']){ opt.limit = 1 } + key = tmp || soul['=']; + } + if(key && !opt.limit){ // a soul.has must be on a soul, and not during soul* + if(typeof has == 'string'){ + key = key+esc+(opt.atom = has); + } else + if(has){ + if(tmp = has['*']){ opt.limit = 1 } + if(key){ key = key+esc + (tmp || (opt.atom = has['='])) } + } + } + if((tmp = get['%']) || opt.limit){ + opt.limit = (tmp <= (opt.pack || (1000 * 100)))? tmp : 1; + } + //console.log("GET!", id, JSON.stringify(key)); + rad(key||'', function(err, data, o){ + if(data){ + if(typeof data !== 'string'){ + if(opt.atom){ + data = u; + } else { + Radix.map(data, each) + } + } + if(!graph && data){ each(data, '') } + } + //console.log("GOT!", id, JSON.stringify(key)); + root.on('in', {'@': id, put: graph, err: err? err : u, rad: Radix}); + }, opt); + function each(val, has, a,b){ + if(!val){ return } + has = (key+has).split(esc); + var soul = has.slice(0,1)[0]; + has = has.slice(-1)[0]; + tmp = val.lastIndexOf('>'); + var state = Radisk.decode(val.slice(tmp+1), null, esc); + val = Radisk.decode(val.slice(0,tmp), null, esc); + (graph = graph || {})[soul] = Gun.state.ify(graph[soul], has, state, val, soul); + } + }); }); \ No newline at end of file diff --git a/lib/unbuild.js b/lib/unbuild.js index ef51e1bb..0e4a8e20 100644 --- a/lib/unbuild.js +++ b/lib/unbuild.js @@ -11,19 +11,7 @@ var write = function(path, data){ return fs.writeFileSync(nodePath.join(dir, path), data); } -var rm = function(path, full) { - path = full || nodePath.join(dir, path); - if(!fs.existsSync(path)){ return } - fs.readdirSync(path).forEach(function(file,index){ - var curPath = path + "/" + file; - if(fs.lstatSync(curPath).isDirectory()) { // recurse - rm(null, curPath); - } else { // delete file - fs.unlinkSync(curPath); - } - }); - fs.rmdirSync(path); -}; +var rm = require('./fsrm'); var mk = function(path){ path = nodePath.join(dir, path); diff --git a/package.json b/package.json index 2cf8e82d..09ece699 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { "name": "gun", - "version": "0.9.9999991", + "version": "0.9.9999992", "description": "A realtime, decentralized, offline-first, graph data synchronization engine.", "main": "index.js", - "browser": "gun.min.js", + "browser": "gun.js", "scripts": { "start": "node examples/http.js 8765", "https": "HTTPS_KEY=test/https/server.key HTTPS_CERT=test/https/server.crt npm start", @@ -12,7 +12,8 @@ "testsea": "mocha test/sea.js", "e2e": "mocha e2e/distributed.js", "docker": "hooks/build", - "unbuild": "node lib/unbuild.js && uglifyjs gun.js -o gun.min.js -c -m" + "minify": "uglifyjs gun.js -o gun.min.js -c -m", + "unbuild": "node lib/unbuild.js" }, "repository": { "type": "git", diff --git a/src/chain.js b/src/chain.js index a707a940..18104481 100644 --- a/src/chain.js +++ b/src/chain.js @@ -23,6 +23,7 @@ function output(msg){ at.on('in', at); return; }*/ + if(at.lex){ msg.get = obj_to(at.lex, msg.get) } if(get['#'] || at.soul){ get['#'] = get['#'] || at.soul; msg['#'] || (msg['#'] = text_rand(9)); @@ -45,6 +46,17 @@ function output(msg){ get: back.get }); if(tmp){ return } + } else + if('string' != typeof get){ + var put = {}, meta = (back.put||{})._; + Gun.obj.map(back.put, function(v,k){ + if(!Gun.text.match(k, get)){ return } + put[k] = v; + }) + if(!Gun.obj.empty(put)){ + put._ = meta; + back.on('in', {$: back.$, put: put, get: back.get}) + } } root.ask(ack, msg); return root.on('in', msg); @@ -144,7 +156,6 @@ function input(msg){ relate(cat, msg, at, rel); echo(cat, msg, eve); } -var C = 0; function relate(at, msg, from, rel){ if(!rel || node_ === at.get){ return } @@ -190,11 +201,11 @@ function map(data, key){ // Map over only the changes on every update. if(!(at = next[key])){ return; } - //if(data && data[_soul] && (tmp = Gun.val.rel.is(data)) && (tmp = (cat.root.$.get(tmp)._)) && obj_has(tmp, 'put')){ + //if(data && data[_soul] && (tmp = Gun.val.link.is(data)) && (tmp = (cat.root.$.get(tmp)._)) && obj_has(tmp, 'put')){ // data = tmp.put; //} if(at.has){ - //if(!(data && data[_soul] && Gun.val.rel.is(data) === Gun.node.soul(at.put))){ + //if(!(data && data[_soul] && Gun.val.link.is(data) === Gun.node.soul(at.put))){ if(u === at.put || !Gun.val.link.is(data)){ at.put = data; } @@ -217,7 +228,10 @@ function not(at, msg){ if(!(at.has || at.soul)){ return } var tmp = at.map, root = at.root; at.map = null; - if(at.has){ at.link = null } + if(at.has){ + if(at.dub && at.root.stop){ at.dub = null } + at.link = null; + } //if(!root.now || !root.now[at.id]){ if(!at.pass){ if((!msg['@']) && null === tmp){ return } @@ -257,7 +271,7 @@ function ask(at, soul){ function ack(msg, ev){ var as = this.as, get = as.get || empty, at = as.$._, tmp = (msg.put||empty)[get['#']]; if(at.ack){ at.ack = (at.ack + 1) || 1; } - if(!msg.put || (get['.'] && !obj_has(tmp, at.get))){ + if(!msg.put || ('string' == typeof get['.'] && !obj_has(tmp, at.get))){ if(at.put !== u){ return } at.on('in', { get: at.get, @@ -276,5 +290,5 @@ function ack(msg, ev){ 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 text_rand = Gun.text.random; -var _soul = Gun.val.rel._, node_ = Gun.node._; +var _soul = Gun.val.link._, node_ = Gun.node._; \ No newline at end of file diff --git a/src/get.js b/src/get.js index 06c96a84..9f622b60 100644 --- a/src/get.js +++ b/src/get.js @@ -32,12 +32,18 @@ Gun.chain.get = function(key, cb, as){ } else if(tmp = rel.is(key)){ return this.get(tmp, cb, as); + } else + if(obj.is(key)){ + gun = this; + if(tmp = ((tmp = key['#'])||empty)['='] || tmp){ gun = gun.get(tmp) } + gun._.lex = key; + return gun; } else { (as = this.chain())._.err = {err: Gun.log('Invalid get request!', key)}; // CLEAN UP if(cb){ cb.call(as, as._.err) } return as; } - if(tmp = cat.stun){ // TODO: Refactor? + if(tmp = this._.stun){ // TODO: Refactor? gun._.stun = gun._.stun || tmp; } if(cb && cb instanceof Function){ @@ -62,8 +68,7 @@ function cache(key, back){ } function soul(gun, cb, opt, as){ var cat = gun._, acks = 0, tmp; - if(tmp = cat.soul){ return cb(tmp, as, cat), gun } - if(tmp = cat.link){ return cb(tmp, as, cat), gun } + if(tmp = cat.soul || cat.link || cat.dub){ return cb(tmp, as, cat), gun } gun.get(function(msg, ev){ if(u === msg.put && (tmp = (obj_map(cat.root.opt.peers, function(v,k,t){t(k)})||[]).length) && ++acks < tmp){ return; diff --git a/src/graph.js b/src/graph.js index a7f6f682..eb96fffe 100644 --- a/src/graph.js +++ b/src/graph.js @@ -31,7 +31,7 @@ var Graph = {}; env.map = env; } if(env.soul){ - at.rel = Val.rel.ify(env.soul); + at.link = Val.link.ify(env.soul); } env.shell = (as||{}).shell; env.graph = env.graph || {}; @@ -46,16 +46,16 @@ var Graph = {}; at.env = env; at.soul = soul; if(Node.ify(at.obj, map, at)){ - at.rel = at.rel || Val.rel.ify(Node.soul(at.node)); + at.link = at.link || Val.link.ify(Node.soul(at.node)); if(at.obj !== env.shell){ - env.graph[Val.rel.is(at.rel)] = at.node; + env.graph[Val.link.is(at.link)] = at.node; } } return at; } function map(v,k,n){ var at = this, env = at.env, is, tmp; - if(Node._ === k && obj_has(v,Val.rel._)){ + if(Node._ === k && obj_has(v,Val.link._)){ return n._; // TODO: Bug? } if(!(is = valid(v,k,n, at,env))){ return } @@ -64,8 +64,8 @@ var Graph = {}; if(obj_has(v, Node._) && Node.soul(v)){ // ? for safety ? at.node._ = obj_copy(v._); } - at.node = Node.soul.ify(at.node, Val.rel.is(at.rel)); - at.rel = at.rel || Val.rel.ify(Node.soul(at.node)); + at.node = Node.soul.ify(at.node, Val.link.is(at.link)); + at.link = at.link || Val.link.ify(Node.soul(at.node)); } if(tmp = env.map){ tmp.call(env.as || {}, v,k,n, at); @@ -84,14 +84,14 @@ var Graph = {}; } tmp = node(env, {obj: v, path: at.path.concat(k)}); if(!tmp.node){ return } - return tmp.rel; //{'#': Node.soul(tmp.node)}; + return tmp.link; //{'#': Node.soul(tmp.node)}; } function soul(id){ var at = this; - var prev = Val.link.is(at.rel), graph = at.env.graph; - at.rel = at.rel || Val.rel.ify(id); - at.rel[Val.rel._] = id; + var prev = Val.link.is(at.link), graph = at.env.graph; + at.link = at.link || Val.link.ify(id); + at.link[Val.link._] = id; if(at.node && at.node[Node._]){ - at.node[Node._][Val.rel._] = id; + at.node[Node._][Val.link._] = id; } if(obj_has(graph, prev)){ graph[id] = graph[prev]; @@ -131,13 +131,13 @@ Graph.node = function(node){ } function map(v,k){ var tmp, obj; if(Node._ === k){ - if(obj_empty(v, Val.rel._)){ + if(obj_empty(v, Val.link._)){ return; } this.obj[k] = obj_copy(v); return; } - if(!(tmp = Val.rel.is(v))){ + if(!(tmp = Val.link.is(v))){ this.obj[k] = v; return; } diff --git a/src/map.js b/src/map.js index b3072500..cb60a711 100644 --- a/src/map.js +++ b/src/map.js @@ -28,8 +28,9 @@ function map(msg){ } function each(v,k){ if(n_ === k){ return } - var msg = this.msg, gun = msg.$, at = this.at, tmp = (gun.get(k)._); - (tmp.echo || (tmp.echo = {}))[at.id] = tmp.echo[at.id] || at; + var msg = this.msg, gun = msg.$, at = gun._, cat = this.at, tmp = at.lex; + if(tmp && !Gun.text.match(k, tmp['.'] || tmp['#'] || tmp)){ return } // TODO: Ugly hack! + ((tmp = gun.get(k)._).echo || (tmp.echo = {}))[cat.id] = tmp.echo[cat.id] || cat; } 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/put.js b/src/put.js index 967310b1..a21202b1 100644 --- a/src/put.js +++ b/src/put.js @@ -40,10 +40,11 @@ Gun.chain.put = function(data, cb, as){ if(!soul && Gun.val.is(msg.put)){ return Gun.log("The reference you are saving is a", typeof msg.put, '"'+ msg.put +'", not a node (object)!'); } - gun.put(Gun.val.rel.ify(soul), cb, as); + gun.put(Gun.val.link.ify(soul), cb, as); }, true); return gun; } + if(at.has && (tmp = Gun.val.link.is(data))){ at.dub = tmp } as.ref = as.ref || (root._ === (tmp = at.back))? gun : tmp.$; if(as.ref._.soul && Gun.val.is(as.data) && at.get){ as.data = obj_put({}, at.get, as.data); @@ -139,7 +140,7 @@ function map(v,k,n, at){ var as = this; function soul(id, as, msg, eve){ var as = as.as, cat = as.at; as = as.as; var at = ((msg || {}).$ || {})._ || {}; - id = at.dub = at.dub || id || Gun.node.soul(cat.obj) || Gun.node.soul(msg.put || at.put) || Gun.val.rel.is(msg.put || at.put) || (as.via.back('opt.uuid') || Gun.text.random)(); // TODO: BUG!? Do we really want the soul of the object given to us? Could that be dangerous? + id = at.dub = at.dub || id || Gun.node.soul(cat.obj) || Gun.node.soul(msg.put || at.put) || Gun.val.link.is(msg.put || at.put) || (as.via.back('opt.uuid') || Gun.text.random)(); // TODO: BUG!? Do we really want the soul of the object given to us? Could that be dangerous? if(eve){ eve.stun = true } if(!id){ // polyfill async uuid for SEA at.via.back('opt.uuid')(function(err, id){ // TODO: improve perf without anonymous callback @@ -198,7 +199,7 @@ function any(soul, as, msg, eve){ if(node_ == at.get){ as.soul = (at.put||empty)['#'] || at.dub; } - as.soul = as.soul || at.soul || at.soul || (opt.uuid || as.via.back('opt.uuid') || Gun.text.random)(); + as.soul = as.soul || at.soul || at.link || (opt.uuid || as.via.back('opt.uuid') || Gun.text.random)(); } if(!as.soul){ // polyfill async uuid for SEA as.via.back('opt.uuid')(function(err, soul){ // TODO: improve perf without anonymous callback diff --git a/src/root.js b/src/root.js index 642a96b7..fc9bc474 100644 --- a/src/root.js +++ b/src/root.js @@ -153,25 +153,9 @@ Gun.dup = require('./dup'); Gun.on.get = function(msg, gun){ var root = gun._, get = msg.get, soul = get[_soul], node = root.graph[soul], has = get[_has], tmp; var next = root.next || (root.next = {}), at = next[soul]; - if(obj_has(soul, '*')){ // TEMPORARY HACK FOR MARTTI, TESTING - var graph = {}; - Gun.obj.map(root.graph, function(node, s){ - if(Gun.text.match(s, soul)){ - graph[s] = Gun.obj.copy(node); - } - }); - if(!Gun.obj.empty(graph)){ - root.on('in', { - '@': msg['#'], - how: '*', - put: graph, - $: gun - }); - } - } // TEMPORARY HACK FOR MARTTI, TESTING if(!node){ return root.on('get', msg) } if(has){ - if(!obj_has(node, has)){ return root.on('get', msg) } + if('string' != typeof has || !obj_has(node, has)){ return root.on('get', msg) } node = Gun.state.to(node, has); // If we have a key in-memory, do we really need to fetch? // Maybe... in case the in-memory key we have is a local write @@ -217,7 +201,7 @@ Gun.dup = require('./dup'); 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 state_lex = Gun.state.lex, _soul = Gun.val.rel._, _has = '.', node_ = Gun.node._, rel_is = Gun.val.link.is; +var state_lex = Gun.state.lex, _soul = Gun.val.link._, _has = '.', node_ = Gun.node._, rel_is = Gun.val.link.is; var empty = {}, u; console.debug = function(i, s){ return (console.debug.i && i === console.debug.i && console.debug.i++) && (console.log.apply(console, arguments) || s) }; diff --git a/src/val.js b/src/val.js index fb7cf4ee..50b4c43e 100644 --- a/src/val.js +++ b/src/val.js @@ -10,11 +10,11 @@ Val.is = function(v){ // Valid values are a subset of JSON: null, binary, number || 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. + return Val.link.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. } Val.link = Val.rel = {_: '#'}; ;(function(){ - Val.rel.is = function(v){ // this defines whether an object is a soul relation or not, they look like this: {'#': 'UUID'} + Val.link.is = function(v){ // this defines whether an object is a soul relation or not, they look like this: {'#': 'UUID'} if(v && v[rel_] && !v._ && obj_is(v)){ // must be an object. var o = {}; obj_map(v, map, o); @@ -33,7 +33,7 @@ Val.link = Val.rel = {_: '#'}; } } }()); -Val.rel.ify = function(t){ return obj_put({}, rel_, t) } // convert a soul into a relation and return it. +Val.link.ify = function(t){ return obj_put({}, rel_, t) } // convert a soul into a relation and return it. Type.obj.has._ = '.'; var rel_ = Val.link._, u; var bi_is = Type.bi.is; diff --git a/test/common.js b/test/common.js index 5254bbcd..2d95a8a9 100644 --- a/test/common.js +++ b/test/common.js @@ -1,5 +1,4 @@ describe('Gun', function(){ - var root; (function(){ var env; @@ -8,6 +7,7 @@ describe('Gun', function(){ root = env.window? env.window : global; try{ env.window && root.localStorage && root.localStorage.clear() }catch(e){} try{ require('fs').unlinkSync('data.json') }catch(e){} + try{ require('../lib/fsrm')('radatatest') }catch(e){} //root.Gun = root.Gun || require('../gun'); if(root.Gun){ root.Gun = root.Gun; @@ -19,6 +19,7 @@ describe('Gun', function(){ //require('../lib/file'); require('../lib/store'); require('../lib/rfs'); + require('./rad/rad.js'); require('./sea/sea.js'); } }(this)); @@ -613,6 +614,7 @@ describe('Gun', function(){ }); describe('Gun Safety', function(){ /* WARNING NOTE: Internal API has significant breaking changes! */ + var gun = Gun(); it('is',function(){ expect(Gun.is(gun)).to.be(true); @@ -3048,7 +3050,7 @@ describe('Gun', function(){ }); it('get put get get put reload get get then get', function(done){ - this.timeout(6000); + this.timeout(9000); var gun = Gun(); gun.get('stef').put({name:'Stef'}); @@ -3081,7 +3083,7 @@ describe('Gun', function(){ if(done.c){ return } done.c = 1; done(); }); - },5000); + },1200); }); it('get get get any parallel', function(done){ @@ -3762,9 +3764,9 @@ describe('Gun', function(){ var msg = {what: 'hello world'}; //var ref = user.get('who').get('all').set(msg); //user.get('who').get('said').set(ref); - var ref = gun.get('who').get('all').set(msg); - gun.get('who').get('said').set(ref); - gun.get('who').get('said').map().once(function(data){ + var ref = gun.get('s/r/who').get('all').set(msg); + gun.get('s/r/who').get('said').set(ref); + gun.get('s/r/who').get('said').map().once(function(data){ expect(data.what).to.be.ok(); done(); }) diff --git a/test/mocha.html b/test/mocha.html index f09ea754..229040e6 100644 --- a/test/mocha.html +++ b/test/mocha.html @@ -23,8 +23,15 @@ - + + + + + + + + +