diff --git a/.travis.yml b/.travis.yml
index 4cf6f163..9ae50c30 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,8 +3,7 @@ branches:
except:
- debug
node_js:
- - 8
- 10
cache:
directories:
- - node_modules
\ No newline at end of file
+ - node_modules
diff --git a/README.md b/README.md
index c2438c08..c584a776 100644
--- a/README.md
+++ b/README.md
@@ -1,10 +1,9 @@
-[](https://www.npmjs.com/package/gun)
+[](https://www.jsdelivr.com/package/npm/gun)
[](https://travis-ci.org/amark/gun)
[](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Famark%2Fgun?ref=badge_shield)
[](https://gitter.im/amark/gun)
-[](https://www.jsdelivr.com/package/npm/gun)
**GUN** is an _ecosystem_ of tools that let you build tomorrow's dApps, today.
@@ -12,7 +11,7 @@ Decentralized alternatives to [Reddit](https://notabug.io/t/whatever/comments/36
-
+
@@ -20,8 +19,9 @@ Decentralized alternatives to [Reddit](https://notabug.io/t/whatever/comments/36
+
-The ecosystem is one nice stack of technologies that looks like this:
+The ecosystem is one nice stack of technologies that looks like this: (names -> use case)
@@ -167,7 +167,7 @@ Technically, **GUN is a graph synchronization protocol** with a *lightweight emb
This would not be possible without **community contributors**, big shout out to:
-**[ajmeyghani](https://github.com/ajmeyghani) ([Learn GUN Basics with Diagrams](https://medium.com/@ajmeyghani/gundb-a-graph-database-in-javascript-3860a08d873c))**; **[anywhichway](https://github.com/anywhichway) ([Block Storage](https://github.com/anywhichway/gun-block))**; **[beebase](https://github.com/beebase) ([Quasar](https://github.com/beebase/gun-vuex-quasar))**; **[BrockAtkinson](https://github.com/BrockAtkinson) ([brunch config](https://github.com/BrockAtkinson/brunch-gun))**; **[Brysgo](https://github.com/brysgo) ([GraphQL](https://github.com/brysgo/graphql-gun))**; **[d3x0r](https://github.com/d3x0r) ([SQLite](https://github.com/d3x0r/gun-db))**; **[forrestjt](https://github.com/forrestjt) ([file.js](https://github.com/amark/gun/blob/master/lib/file.js))**; **[hillct](https://github.com/hillct) (Docker)**; **[JosePedroDias](https://github.com/josepedrodias) ([graph visualizer](http://acor.sl.pt:9966))**; **[JuniperChicago](https://github.com/JuniperChicago) ([cycle.js bindings](https://github.com/JuniperChicago/cycle-gun))**; **[jveres](https://github.com/jveres) ([todoMVC](https://github.com/jveres/todomvc))**; **[kristianmandrup](https://github.com/kristianmandrup) ([edge](https://github.com/kristianmandrup/gun-edge))**; **[Lightnet](https://github.com/Lightnet)** ([Awesome Vue User Examples](https://glitch.com/edit/#!/jsvuegunui?path=README.md:1:0) & [User Kitchen Sink Playground](https://gdb-auth-vue-node.glitch.me/)); **[lmangani](https://github.com/lmangani) ([Cytoscape Visualizer](https://github.com/lmangani/gun-scape), [Cassandra](https://github.com/lmangani/gun-cassandra), [Fastify](https://github.com/lmangani/fastify-gundb), [LetsEncrypt](https://github.com/lmangani/polyGun-letsencrypt))**; **[mhelander](https://github.com/mhelander) ([SEA](https://github.com/amark/gun/blob/master/sea.js))**; [omarzion](https://github.com/omarzion) ([Sticky Note App](https://github.com/omarzion/stickies)); [PsychoLlama](https://github.com/PsychoLlama) ([LevelDB](https://github.com/PsychoLlama/gun-level)); **[RangerMauve](https://github.com/RangerMauve) ([schema](https://github.com/gundb/gun-schema))**; **[robertheessels](https://github.com/swifty) ([gun-p2p-auth](https://github.com/swifty/gun-p2p-auth))**; **[rogowski](https://github.com/rogowski) (AXE)**; [sbeleidy](https://github.com/sbeleidy); **[sbiaudet](https://github.com/sbiaudet) ([C# Port](https://github.com/sbiaudet/cs-gun))**; **[Sean Matheson](https://github.com/ctrlplusb) ([Observable/RxJS/Most.js bindings](https://github.com/ctrlplusb/gun-most))**; **[Shadyzpop](https://github.com/Shadyzpop) ([React Native example](https://github.com/amark/gun/tree/master/examples/react-native))**; **[sjones6](https://github.com/sjones6) ([Flint](https://github.com/sjones6/gun-flint))**; **[Stefdv](https://github.com/stefdv) (Polymer/web components)**; **[zrrrzzt](https://github.com/zrrrzzt) ([JWT Auth](https://gist.github.com/zrrrzzt/6f88dc3cedee4ee18588236756d2cfce))**; **[xmonader](https://github.com/xmonader) ([Python Port](https://github.com/xmonader/pygundb))**; **[88dev](https://github.com/88dev) ([Database Viewer](https://github.com/88dev/gun-show))**;
+**[ajmeyghani](https://github.com/ajmeyghani) ([Learn GUN Basics with Diagrams](https://medium.com/@ajmeyghani/gundb-a-graph-database-in-javascript-3860a08d873c))**; **[anywhichway](https://github.com/anywhichway) ([Block Storage](https://github.com/anywhichway/gun-block))**; **[beebase](https://github.com/beebase) ([Quasar](https://github.com/beebase/gun-vuex-quasar))**; **[BrockAtkinson](https://github.com/BrockAtkinson) ([brunch config](https://github.com/BrockAtkinson/brunch-gun))**; **[Brysgo](https://github.com/brysgo) ([GraphQL](https://github.com/brysgo/graphql-gun))**; **[d3x0r](https://github.com/d3x0r) ([SQLite](https://github.com/d3x0r/gun-db))**; **[forrestjt](https://github.com/forrestjt) ([file.js](https://github.com/amark/gun/blob/master/lib/file.js))**; **[hillct](https://github.com/hillct) (Docker)**; **[JosePedroDias](https://github.com/josepedrodias) ([graph visualizer](http://acor.sl.pt:9966))**; **[JuniperChicago](https://github.com/JuniperChicago) ([cycle.js bindings](https://github.com/JuniperChicago/cycle-gun))**; **[jveres](https://github.com/jveres) ([todoMVC](https://github.com/jveres/todomvc))**; **[kristianmandrup](https://github.com/kristianmandrup) ([edge](https://github.com/kristianmandrup/gun-edge))**; **[Lightnet](https://github.com/Lightnet)** ([Awesome Vue User Examples](https://glitch.com/edit/#!/jsvuegunui?path=README.md:1:0) & [User Kitchen Sink Playground](https://gdb-auth-vue-node.glitch.me/)); **[lmangani](https://github.com/lmangani) ([Cytoscape Visualizer](https://github.com/lmangani/gun-scape), [Cassandra](https://github.com/lmangani/gun-cassandra), [Fastify](https://github.com/lmangani/fastify-gundb), [LetsEncrypt](https://github.com/lmangani/polyGun-letsencrypt))**; **[mhelander](https://github.com/mhelander) ([SEA](https://github.com/amark/gun/blob/master/sea.js))**; [omarzion](https://github.com/omarzion) ([Sticky Note App](https://github.com/omarzion/stickies)); [PsychoLlama](https://github.com/PsychoLlama) ([LevelDB](https://github.com/PsychoLlama/gun-level)); **[RangerMauve](https://github.com/RangerMauve) ([schema](https://github.com/gundb/gun-schema))**; **[robertheessels](https://github.com/swifty) ([gun-p2p-auth](https://github.com/swifty/gun-p2p-auth))**; **[rogowski](https://github.com/rogowski) (AXE)**; [sbeleidy](https://github.com/sbeleidy); **[sbiaudet](https://github.com/sbiaudet) ([C# Port](https://github.com/sbiaudet/cs-gun))**; **[Sean Matheson](https://github.com/ctrlplusb) ([Observable/RxJS/Most.js bindings](https://github.com/ctrlplusb/gun-most))**; **[Shadyzpop](https://github.com/Shadyzpop) ([React Native example](https://github.com/amark/gun/tree/master/examples/react-native))**; **[sjones6](https://github.com/sjones6) ([Flint](https://github.com/sjones6/gun-flint))**; **[Stefdv](https://github.com/stefdv) (Polymer/web components)**; **[zrrrzzt](https://github.com/zrrrzzt) ([JWT Auth](https://gist.github.com/zrrrzzt/6f88dc3cedee4ee18588236756d2cfce))**; **[xmonader](https://github.com/xmonader) ([Python Port](https://github.com/xmonader/pygundb))**;
I am missing many others, apologies, will be adding them soon!
@@ -190,7 +190,7 @@ var Gun = require('gun/gun');
If you also need to install SEA for user auth and crypto, also install some of its dependencies like this:
-`npm install @trust/crypto text-encoding node-webcrypto-ossl --save`
+`npm install text-encoding node-webcrypto-ossl --save`
You will need to require it too (it will be automatically added to the Gun object):
@@ -208,6 +208,8 @@ To quickly spin up a Gun test server for your development team, utilize either [
[](https://heroku.com/deploy?template=https://github.com/amark/gun)
+ > Heroku deletes your data every 15 minutes, one way to fix this is by adding [cheap storage](https://gun.eco/docs/Using-Amazon-S3-for-Storage).
+
Or:
```bash
diff --git a/app.json b/app.json
index 005f6f0e..441f5c9a 100644
--- a/app.json
+++ b/app.json
@@ -1,6 +1,7 @@
{
"name": "gun-server",
- "website": "http://gun.js.org",
+ "stack": "heroku-18",
+ "website": "http://gun.eco/",
"repository": "https://github.com/amark/gun",
"logo": "https://avatars3.githubusercontent.com/u/8811914",
"keywords": ["node", "gun", "gunDB", "database","graph","offline-first"],
diff --git a/as.js b/as.js
index f6ac4f37..9be7c337 100644
--- a/as.js
+++ b/as.js
@@ -1,7 +1,73 @@
;(function(){
- function as(el, gun, cb){
+ function as(el, gun, cb, opt){
el = $(el);
if(gun === as.gui && as.el && as.el.is(el)){ return }
+
+ opt = opt || {};
+ opt.match = opt.match || '{{ ';
+ opt.end = opt.end || ' }}';
+ ;(function(){ // experimental
+ function nest(t, s,e, r, i,tmp,u){
+ if(r && !r.length){ return t||'' }
+ if(!t){ return [] }
+ e = e || s;
+ i = t.indexOf(s, i||0);
+ if(0 > i){ return [] }
+ tmp = t.indexOf(e, i+1);
+ if(!r){ return [t.slice(i+s.length, tmp)].concat(nest(t, s,e, r, tmp,tmp,u)) }
+ return t.slice(0,i)+r[0]+nest(t.slice(tmp+e.length), s,e, r.slice(1), 0,tmp,u);
+ }
+
+ /* experimental */
+ function template(tag, attr){
+ var html = (tag = $(tag))[0].outerHTML, sub, tmp;
+ if(html && (0 > html.indexOf(opt.match))){ return }
+ if(!attr){
+ $.each(tag[0].attributes, function(i,v){
+ if(!v){ return }
+ if(!nest(v.value, opt.match, opt.end).length){ return }
+ template(tag, v.name)
+ });
+ if((sub = tag.children()).length){
+ return sub.each(function(){ template(this) });
+ }
+ }
+ var data = [], plate = attr? tag.attr(attr) : tag.html();
+ tmp = nest(plate, opt.match, opt.end);
+ if(!tmp.length){ return }
+ $.each(tmp, function(pos, match){
+ var expr = match.split(' ');
+ var path = (expr[0]).split('.');
+ if(expr = expr.slice(1).join(' ')){
+ expr = new Function("_", "b", "return (_)" + expr);
+ }
+ var val = (expr && expr('')) || '';
+ data.push(val);
+ if(!attr){ tag.text(val) }
+
+ var ref = gun, sup = [], tmp;
+ if(tmp = tag.attr('name')){ sup.push(tmp) }
+ tag.parents("[name]").each(function(){
+ sup.push($(this).attr('name'));
+ });
+ $.each(path = sup.reverse().concat(path), function(i,v){
+ ref = ref.get(v);
+ });
+ ref.on(function(v){
+ v = data[pos] = expr? expr(v) : v;
+ var tmp = nest(plate, opt.match, opt.end, data);
+ if(attr){
+ tag.attr(attr, tmp);
+ } else {
+ tag.text(tmp);
+ }
+ });
+ });
+ }
+ template(el);
+
+ }());
+
as.gui = gun;
as.el = el;
if(el.data('as')){
@@ -59,10 +125,12 @@
if(many && ui.is('.sort')){
var up = ui.closest("[name='#']");
var tmp = as.sort(data, up.parent().children().last());
- up.insertAfter(tmp);
+ tmp? up.insertAfter(tmp) : up.prependTo(up.parent());
}
if(as.lock === gui){ return }
- (ui[0] && u === ui[0].value)? ui.text(data) : ui.val(data);
+ if(!(data && data instanceof Object)){
+ (ui[0] && u === ui[0].value)? ui.text(data) : ui.val(data);
+ }
ui.data('was', data);
if(cb){
cb(data, key, ui);
@@ -80,12 +148,7 @@
}, wait || 200);
}
}
- as.sort = function sort(id, li){
- var num = parseFloat(id);
- var id = $(li).find('.sort').text() || -Infinity;
- var at = num >= parseFloat(id);
- return at ? li : sort(id, li.prev());
- }
+ as.sort = function sort(num, li){ return parseFloat(num) >= parseFloat($(li).find('.sort').text() || -Infinity)? li : sort(num, li.prev()) }
$(document).on('keyup', 'input, textarea, [contenteditable]', as.wait(function(){
var el = $(this);
var data = (el[0] && u === el[0].value)? el.text() : el.val();
@@ -94,7 +157,7 @@
as.lock = g;
g.put(data);
}, 99));
- $(document).on('submit', 'form', function(e){ e.preventDefault() });
+ //$(document).on('submit', 'form', function(e){ e.preventDefault() });
var u;
window.as = as;
$.as = as;
@@ -146,4 +209,31 @@
;$(function(){
$('.page').not(':first').hide();
$.as.route(location.hash.slice(1));
+ $(JOY.start = JOY.start || function(){ $.as(document, gun, null, JOY.opt) });
+
+ if($('body').attr('peers')){ (console.warn || console.log)('Warning: Please upgrade to https://github.com/eraeco/joydb#peers !') }
+
});
+;(function(){ // need to isolate into separate module!
+ var joy = window.JOY = function(){};
+ joy.auth = function(a,b,cb,o){
+ if(!o){ o = cb ; cb = 0 }
+ if(o === true){
+ gun.user().create(a, b);
+ return;
+ }
+ gun.user().auth(a,b, cb,o);
+ }
+
+ var opt = joy.opt = window.CONFIG || {}, peers;
+ $('link[type=peer]').each(function(){ (peers || (peers = [])).push($(this).attr('href')) });
+ !window.gun && (opt.peers = opt.peers || peers || (function(){
+ (console.warn || console.log)('Warning: No peer provided, defaulting to DEMO peer. Do not run in production, or your data will be regularly wiped, reset, or deleted. For more info, check https://github.com/eraeco/joydb#peers !');
+ return ['https://gunjs.herokuapp.com/gun'];
+ }()));
+ window.gun = window.gun || Gun(opt);
+
+ gun.on('auth', function(ack){
+ console.log("Your namespace is publicly available at", ack.soul);
+ });
+}());
\ No newline at end of file
diff --git a/axe.js b/axe.js
index a950e363..bb7a2008 100644
--- a/axe.js
+++ b/axe.js
@@ -1,99 +1,287 @@
;(function(){
- /* UNBUILD */
- var root;
- if(typeof window !== "undefined"){ root = window }
- if(typeof global !== "undefined"){ root = global }
- root = root || {};
- var console = root.console || {log: function(){}};
- function USE(arg, req){
- return req? require(arg) : arg.slice? USE[R(arg)] : function(mod, path){
- arg(mod = {exports: {}});
- USE[R(path)] = mod.exports;
- }
- function R(p){
- return p.split('/').slice(-1).toString().replace('.js','');
- }
- }
- if(typeof module !== "undefined"){ var common = module }
- /* UNBUILD */
+ /* UNBUILD */
+ var root;
+ if(typeof window !== "undefined"){ root = window }
+ if(typeof global !== "undefined"){ root = global }
+ root = root || {};
+ var console = root.console || {log: function(){}};
+ function USE(arg, req){
+ return req? require(arg) : arg.slice? USE[R(arg)] : function(mod, path){
+ arg(mod = {exports: {}});
+ USE[R(path)] = mod.exports;
+ }
+ function R(p){
+ return p.split('/').slice(-1).toString().replace('.js','');
+ }
+ }
+ if(typeof module !== "undefined"){ var common = module }
+ /* UNBUILD */
- ;USE(function(module){
+ ;USE(function(module){
if(typeof window !== "undefined"){ module.window = window }
var tmp = module.window || module;
- var AXE = tmp.AXE || function(){};
-
- if(AXE.window = module.window){ try{
- AXE.window.AXE = AXE;
- tmp = document.createEvent('CustomEvent');
- tmp.initCustomEvent('extension', false, false, {type: "AXE"});
- (window.dispatchEvent || window.fireEvent)(tmp);
- window.postMessage({type: "AXE"}, '*');
- } catch(e){} }
+ var AXE = tmp.AXE || function(){};
+ if(AXE.window = module.window){ AXE.window.AXE = AXE }
try{ if(typeof common !== "undefined"){ common.exports = AXE } }catch(e){}
module.exports = AXE;
- })(USE, './root');
+ })(USE, './root');
- ;USE(function(module){
+ ;USE(function(module){
- var AXE = USE('./root'), Gun = (AXE.window||{}).Gun || USE('./gun', 1);
- (Gun.AXE = AXE).GUN = AXE.Gun = Gun;
+ var AXE = USE('./root'), Gun = (AXE.window||{}).Gun || USE('./gun', 1);
+ (Gun.AXE = AXE).GUN = AXE.Gun = Gun;
- Gun.on('opt', function(at){
- if(!at.axe){
- at.axe = {};
- var p = at.opt.peers, tmp;
- // 1. If any remembered peers or from last cache or extension
- // 2. Fallback to use hard coded peers from dApp
- // 3. Or any offered peers.
- //if(Gun.obj.empty(p)){
- // Gun.obj.map(['http://localhost:8765/gun'/*, 'https://guntest.herokuapp.com/gun'*/], function(url){
- // p[url] = {url: url, axe: {}};
- // });
- //}
- // Our current hypothesis is that it is most optimal
- // to take peers in a common network, and align
- // them in a line, where you only have left and right
- // peers, so messages propagate left and right in
- // a linear manner with reduced overlap, and
- // with one common superpeer (with ready failovers)
- // in case the p2p linear latency is high.
- // Or there could be plenty of other better options.
- console.log("axe", at.opt);
- if(at.opt.super){
- function verify(msg, send, at) {
- var peers = Object.keys(p), puts = Object.keys(msg.put), i, j, peer;
- var soul = puts[0]; /// TODO: verify all souls in puts. Copy the msg only with subscribed souls?
- for (i=0; i < peers.length; ++i) {
- peer = p[peers[i]];
- //if (peer.url) {console.log('AXE do not reject superpeers'); send(msg, peer); continue;} /// always send to superpeers?
- if (!peer.id) {console.log('AXE peer without id: ', peer); continue;}
- if (!Gun.subscribe[soul] || !Gun.subscribe[soul][peer.id]) { console.log('AXE SAY reject msg to peer: %s, soul: %s', peer.id, soul); continue; }
- send(msg, peer);
- }
- }
- AXE.say = function(msg, send, at) {
- if (!msg.put) { send(msg); return; }
- console.log('AXE HOOK!! ', msg);
- verify(msg, send, at);
- };
- /// TODO: remove peer from all Gun.subscribe. On `mesh.bye` event?
- }
- if(at.opt.super){
- at.on('in', USE('./lib/super', 1), at);
- } else {
- //at.on('in', input, at);
- }
- }
- this.to.next(at); // make sure to call the "next" middleware adapter.
- });
+ Gun.on('opt', function(at){
+ start(at);
+ this.to.next(at); // make sure to call the "next" middleware adapter.
+ });
- function input(msg){
- var at = this.as, to = this.to;
- }
+ function start(at){
+ if(at.axe){ return }
+ var opt = at.opt, peers = opt.peers;
+ if(false === opt.axe){ return }
+ if((typeof process !== "undefined") && 'false' === ''+(process.env||{}).AXE){ return }
+ var axe = at.axe = {}, tmp;
+ // 1. If any remembered peers or from last cache or extension
+ // 2. Fallback to use hard coded peers from dApp
+ // 3. Or any offered peers.
+ //if(Gun.obj.empty(p)){
+ // Gun.obj.map(['http://localhost:8765/gun'/*, 'https://guntest.herokuapp.com/gun'*/], function(url){
+ // p[url] = {url: url, axe: {}};
+ // });
+ //}
+ // Our current hypothesis is that it is most optimal
+ // to take peers in a common network, and align
+ // them in a line, where you only have left and right
+ // peers, so messages propagate left and right in
+ // a linear manner with reduced overlap, and
+ // with one common superpeer (with ready failovers)
+ // in case the p2p linear latency is high.
+ // Or there could be plenty of other better options.
+ var mesh = opt.mesh = opt.mesh || Gun.Mesh(at);
+ console.log("AXE enabled.");
- module.exports = AXE;
- })(USE, './axe');
+ function verify(dht, msg) {
+ var puts = Object.keys(msg.put);
+ var soul = puts[0]; /// TODO: verify all souls in puts. Copy the msg only with subscribed souls?
+ var subs = dht(soul);
+ if (!subs) { return; }
+ var tmp = [];
+ Gun.obj.map(subs.split(','), function(pid) {
+ if (pid in peers) {
+ tmp.push(pid);
+ mesh.say(msg, peers[pid]);
+ }
+ });
+ /// Only connected peers in the tmp array.
+ if (opt.super) {
+ dht(soul, tmp.join(','));
+ }
+ }
+ function route(get){ var tmp;
+ if(!get){ return }
+ if('string' != typeof (tmp = get['#'])){ return }
+ return tmp;
+ }
+ var Rad = (Gun.window||{}).Radix || USE('./lib/radix', 1);
+ at.opt.dht = Rad();
+ at.on('in', function input(msg){
+ var to = this.to, peer = (msg._||{}).via;
+ var dht = opt.dht;
+ var routes = axe.routes || (axe.routes = {}); // USE RAD INSTEAD! TMP TESTING!
+ var get = msg.get, hash, tmp;
+ //if(get && opt.super && peer){
+ if(get && opt.super && peer && (tmp = route(get))){
+ hash = tmp; //Gun.obj.hash(get); // USE RAD INSTEAD!
+ (routes[hash] || (routes[hash] = {}))[peer.id] = peer;
+ (peer.routes || (peer.routes = {}))[hash] = routes[hash];
+
+ /*if(soul = get['#']){ // SWITCH BACK TO USING DHT!
+ if(key = get['.']){
+
+ } else {
+
+ }
+ if (!peer.id) {console.log('[*** WARN] no peer.id %s', soul);}
+ var pids = joindht(dht, soul, peer.id);
+ if (pids) {
+ var dht = {};
+ dht[soul] = pids;
+ mesh.say({dht:dht}, opt.peers[peer.id]);
+ }
+ }*/
+ }
+ if((tmp = msg['@']) && (tmp = at.dup.s[tmp]) && (tmp = tmp.it)){
+ (tmp = (tmp._||ok)).ack = (tmp.ack || 0) + 1; // count remote ACKs to GET.
+ }
+ to.next(msg);
+
+ if (opt.rtc && msg.dht) {
+ Gun.obj.map(msg.dht, function(pids, soul) {
+ dht(soul, pids);
+ Gun.obj.map(pids.split(','), function(pid) {
+ /// TODO: here we can put an algorithm of who must connect?
+ if (!pid || pid in opt.peers || pid === opt.pid || opt.announce[pid]) { return; }
+ opt.announce[pid] = true; /// To try only one connection to the same peer.
+ opt.announce(pid);
+ });
+ });
+ }
+ });
+
+ //try{console.log(req.connection.remoteAddress)}catch(e){};
+ mesh.hear['opt'] = function(msg, peer){
+ if(msg.ok){ return opt.log(msg) }
+ var tmp = msg.opt;
+ if(!tmp){ return }
+ tmp = tmp.peers;
+ if(!tmp || !Gun.text.is(tmp)){ return }
+ if(axe.up[tmp] || 6 <= Object.keys(axe.up).length){ return }
+ var o = tmp; //{peers: tmp};
+ at.$.opt(o);
+ o = peers[tmp];
+ if(!o){ return }
+ o.retry = 9;
+ mesh.wire(o);
+ if(peer){ mesh.say({dam: 'opt', ok: 1, '@': msg['#']}, peer) }
+ }
+ setInterval(function(tmp){
+ if(!(tmp = at.stats && at.stats.stay)){ return }
+ (tmp.axe = tmp.axe || {}).up = Object.keys(axe.up||{});
+ },1000 * 60)
+ setTimeout(function(tmp){
+ if(!(tmp = at.stats && at.stats.stay)){ return }
+ Gun.obj.map((tmp.axe||{}).up, function(url){ mesh.hear.opt({opt: {peers: url}}) })
+ },1000);
+
+ if(at.opt.super){
+ var rotate = 0;
+ mesh.way = function(msg) {
+ if (msg.rtc) {
+ if (msg.rtc.to) {
+ /// Send announce to one peer only if the msg have 'to' attr
+ var peer = (peers) ? peers[msg.rtc.to] : null;
+ if (peer) { mesh.say(msg, peer); }
+ return;
+ }
+ }
+ if(msg.get){ mesh.say(msg, axe.up) } // always send gets up!
+ if(msg.get && (tmp = route(msg.get))){
+ var hash = tmp; //Gun.obj.hash(msg.get);
+ var routes = axe.routes || (axe.routes = {}); // USE RAD INSTEAD! TMP TESTING!
+ var peers = routes[hash];
+ function chat(peers, old){ // what about optimizing for directed peers?
+ if(!peers){ return chat(opt.peers) }
+ var ids = Object.keys(peers); // TODO: BUG! THIS IS BAD PERFORMANCE!!!!
+ var meta = (msg._||yes);
+ clearTimeout(meta.lack);
+ var id, peer, c = 1; // opt. ?redundancy?
+ while((id = ids[meta.turn || 0]) && c--){ // TODO: This hits peers in order, not necessarily best for load balancing. And what about optimizing for directed peers?
+ peer = peers[id];
+ meta.turn = (meta.turn || 0) + 1;
+ if((old && old[id]) || false === mesh.say(msg, peer)){ ++c }
+ }
+ //console.log("AXE:", Gun.obj.copy(msg), meta.turn, c, ids, opt.peers === peers);
+ if(0 < c){
+ if(peers === opt.peers){ return } // prevent infinite lack loop.
+ return meta.turn = 0, chat(opt.peers, peers)
+ }
+ var hash = msg['##'], ack = meta.ack;
+ meta.lack = setTimeout(function(){
+ if(ack && hash && hash === msg['##']){ return }
+ if(meta.turn >= (axe.turns || 3)){ return } // variable for later! Also consider ACK based turn limit.
+ //console.log(msg['#'], "CONTINUE:", ack, hash, msg['##']);
+ chat(peers, old); // keep asking for data if there is mismatching hashes.
+ }, 25);
+ }
+ return chat(peers);
+ }
+ // TODO: PUTs need to only go to subs!
+ if(msg.put){
+ var routes = axe.routes || (axe.routes = {}); // USE RAD INSTEAD! TMP TESTING!
+ var peers = {};
+ Gun.obj.map(msg.put, function(node, soul){
+ var hash = soul; //Gun.obj.hash({'#': soul});
+ var to = routes[hash];
+ if(!to){ return }
+ Gun.obj.to(to, peers);
+ });
+ mesh.say(msg, peers);
+ return;
+ }
+ mesh.say(msg, opt.peers); return; // TODO: DISABLE THIS!!! USE DHT!
+
+
+ if (!msg.put) { mesh.say(msg); return; }
+ //console.log('AXE HOOK!! ', msg);
+ verify(opt.dht, msg);
+ };
+ } else {
+ mesh.route = function(msg) {
+ if (msg.rtc) {
+ }
+ if (!msg.put) { mesh.say(msg); return; }
+ verify(opt.dht, msg);
+ /// Always send to superpeers?
+ Gun.obj.map(peers, function(peer) {
+ if (peer.url) {
+ mesh.say(msg, peer);
+ }
+ });
+ };
+ /*var connections = 0; // THIS HAS BEEN MOVED TO CORE NOW!
+ at.on('hi', function(opt) {
+ this.to.next(opt);
+ //console.log('AXE PEER [HI]', new Date(), opt);
+ connections++;
+ /// The first connection don't need to resubscribe the nodes.
+ if (connections === 1) { return; }
+ /// Resubscribe all nodes.
+ setTimeout(function() {
+ var souls = Object.keys(at.graph);
+ for (var i=0; i < souls.length; ++i) {
+ //at.gun.get(souls[i]).off();
+ at.next[souls[i]].ack = 0;
+ at.gun.get(souls[i]).once(function(){});
+ }
+ //location.reload();
+ }, 500);
+ }, at);*/
+ }
+ axe.up = {};
+ at.on('hi', function(peer){
+ this.to.next(peer);
+ if(!peer.url){ return }
+ axe.up[peer.id] = peer;
+ })
+ at.on('bye', function(peer){ this.to.next(peer);
+ if(peer.url){ delete axe.up[peer.id] }
+ Gun.obj.map(peer.routes, function(route, hash){
+ delete route[peer.id];
+ if(Gun.obj.empty(route)){
+ delete axe.routes[hash];
+ }
+ });
+ });
+ }
+
+ function joindht(dht, soul, pids) {
+ if (!pids || !soul || !dht) { return; }
+ var subs = dht(soul);
+ var tmp = subs ? subs.split(',') : [];
+ Gun.obj.map(pids.split(','), function(pid) {
+ if (pid && tmp.indexOf(pid) === -1) { tmp.push(pid); }
+ });
+ tmp = tmp.join(',');
+ dht(soul, tmp);
+ return tmp;
+ }
+
+ var empty = {}, yes = true, u;
+
+ module.exports = AXE;
+ })(USE, './axe');
}());
diff --git a/examples/axe.html b/examples/axe.html
index 40dade3b..5c2caa09 100644
--- a/examples/axe.html
+++ b/examples/axe.html
@@ -8,8 +8,11 @@
+
-
+
+
+
:
+
+
+
+
+
+
+
+
+
+