Browse Source

update gundb and small fixes

Nikolay Suslov 5 years ago
parent
commit
f17f8cd219

File diff suppressed because it is too large
+ 344 - 345
public/app.js


+ 2 - 3
public/helpers.js

@@ -98,7 +98,7 @@ class Helpers {
         var seperatorFixedPath = path.slice(1);//path.replace(/\//g, '/');
         let worldName = seperatorFixedPath.split('/')[0];
         let fileName = seperatorFixedPath.replace(worldName + '/', "");
-        let doc = await userDB.get('worlds').get(worldName).get(fileName).once().then();
+        let doc = await userDB.get('worlds').get(worldName).get(fileName).then();
         if (doc) {
             return true
         }
@@ -108,9 +108,8 @@ class Helpers {
     async IsExist(path) {
 
         let userDB = _LCSDB.user(_LCS_WORLD_USER.pub);
-        
         var seperatorFixedPath = path.slice(1);//path.replace(/\//g, '/');
-        let doc = await userDB.get('worlds').get(seperatorFixedPath).once().then();
+        let doc = await  userDB.get('worlds').get(seperatorFixedPath).then();
         if (doc) {
             return true
         }

+ 100 - 10
public/lib/gundb/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 <body peers=""> 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);
+	});
+}());

+ 34 - 1
public/lib/gundb/axe.js

@@ -42,7 +42,7 @@
 			if(at.axe){ return }
 			var opt = at.opt, peers = opt.peers;
 			if(false === opt.axe){ return }
-			if(false === process.env.NO_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
@@ -132,6 +132,31 @@
 				}
 			});
 
+			//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) {
@@ -143,6 +168,7 @@
 							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!
@@ -225,7 +251,14 @@
 					}, 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)){

+ 25 - 15
public/lib/gundb/gun.js

@@ -115,8 +115,9 @@
 				} t.r = t.r || [];
 				t.r.push(k);
 			};
-			var keys = Object.keys;
-			Type.obj.map = function(l, c, _){
+			var keys = Object.keys, map;
+			Object.keys = Object.keys || function(o){ return map(o, function(v,k,t){t(k)}) }
+			Type.obj.map = map = function(l, c, _){
 				var u, i = 0, x, r, ll, lle, f = fn_is(c);
 				t.r = null;
 				if(keys && obj_is(l)){
@@ -801,6 +802,7 @@
 			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];
+				// queue concurrent GETs?
 				if(!node){ return root.on('get', msg) }
 				if(has){
 					if('string' != typeof has || !obj_has(node, has)){ return root.on('get', msg) }
@@ -839,7 +841,11 @@
 					at.opt.peers = obj_to(tmp, at.opt.peers);
 				}
 				at.opt.peers = at.opt.peers || {};
-				obj_to(opt, at.opt); // copies options on to `at.opt` only if not already taken.
+				obj_map(opt, function each(v,k){
+					if(!obj_has(this, k) || text.is(v) || obj.empty(v)){ this[k] = v ; return }
+					if(v && v.constructor !== Object && !list_is(v)){ return }
+					obj_map(v, each, this[k]);
+				}, at.opt);
 				Gun.on('opt', at);
 				at.opt.uuid = at.opt.uuid || function(){ return state_lex() + text_rand(12) }
 				return gun;
@@ -1288,7 +1294,7 @@
 			var cat = gun._, acks = 0, tmp;
 			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){
+				if(u === msg.put && (tmp = Object.keys(cat.root.opt.peers).length) && ++acks < tmp){
 					return;
 				}
 				ev.rid(msg);
@@ -1479,7 +1485,6 @@
 			}, as);
 			if(as.res){ as.res() }
 		} function no(v,k){ if(v){ return true } }
-		//console.debug(999,1); var C = 0; setInterval(function(){ try{ debug.innerHTML = C }catch(e){console.log(e)} }, 500);
 
 		function map(v,k,n, at){ var as = this;
 			var is = Gun.is(v);
@@ -1509,7 +1514,7 @@
 			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
+				as.via.back('opt.uuid')(function(err, id){ // TODO: improve perf without anonymous callback
 					if(err){ return Gun.log(err) } // TODO: Handle error.
 					solve(at, at.dub = at.dub || id, cat, as);
 				});
@@ -1677,8 +1682,10 @@
 				}
 			}
 			if((tmp = eve.wait) && (tmp = tmp[at.id])){ clearTimeout(tmp) }
+			eve.ack = (eve.ack||0)+1;
+			if(!to && u === data && eve.ack <= (opt.acks || Object.keys(at.root.opt.peers).length)){ return }
 			if((!to && (u === data || at.soul || at.link || (link && !(0 < link.ack))))
-			|| (u === data && (tmp = (obj_map(at.root.opt.peers, function(v,k,t){t(k)})||[]).length) && (!to && (link||at).ack <= tmp))){
+			|| (u === data && (tmp = Object.keys(at.root.opt.peers).length) && (!to && (link||at).ack < tmp))){
 				tmp = (eve.wait = {})[at.id] = setTimeout(function(){
 					val.call({as:opt}, msg, eve, tmp || 1);
 				}, opt.wait || 99);
@@ -1921,7 +1928,7 @@
 				if(data){ disk = data }
 				try{store.setItem(opt.prefix, JSON.stringify(disk));
 				}catch(e){
-					Gun.log(err = (e || "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 .");
+					Gun.log(err = (e || "localStorage failure") + " Consider using GUN's IndexedDB plugin for RAD for more storage space, https://gun.eco/docs/RAD#install");
 					root.on('localStorage:error', {err: err, file: opt.prefix, flush: disk, retry: flush});
 				}
 				if(!err && !Gun.obj.empty(opt.peers)){ return } // only ack if there are no peers.
@@ -2018,6 +2025,7 @@
 						return;
 					}
 					if(!peer.wire && mesh.wire){ mesh.wire(peer) }
+					if(id === peer.last){ return } peer.last = id;  // was it just sent?
 					if(peer === meta.via){ return false }
 					if((tmp = meta.to) && (tmp[peer.url] || tmp[peer.pid] || tmp[peer.id]) /*&& !o*/){ return false }
 					if(peer.batch){
@@ -2100,7 +2108,6 @@
 				});
 			}
 			mesh.bye = function(peer){
-				Type.obj.del(opt.peers, peer.id); // assume if peer.url then reconnect
 				root.on('bye', peer);
 				var tmp = +(new Date); tmp = (tmp - (peer.met||tmp));
 				mesh.bye.time = ((mesh.bye.time || tmp) + tmp) / 2;
@@ -2127,6 +2134,14 @@
 				root.on('out', mesh.say);
 			});
 
+			root.on('bye', function(peer, tmp){
+				peer = opt.peers[peer.id || peer] || peer; 
+				this.to.next(peer);
+				peer.bye? peer.bye() : (tmp = peer.wire) && tmp.close && tmp.close();
+				Type.obj.del(opt.peers, peer.id);
+				peer.wire = null;
+			});
+
 			var gets = {};
 			root.on('bye', function(peer, tmp){ this.to.next(peer);
 				if(!(tmp = peer.url)){ return } gets[tmp] = true;
@@ -2176,7 +2191,6 @@
 		}());
 
 	  var empty = {}, ok = true, u;
-	  Object.keys = Object.keys || function(o){ return map(o, function(v,k,t){t(k)}) }
 
 	  try{ module.exports = Mesh }catch(e){}
 
@@ -2214,11 +2228,7 @@
 					reconnect(peer);
 				};
 				wire.onerror = function(error){
-					reconnect(peer); // placement?
-					if(!error){ return }
-					if(error.code === 'ECONNREFUSED'){
-						//reconnect(peer, as);
-					}
+					reconnect(peer);
 				};
 				wire.onopen = function(){
 					opt.mesh.hi(peer);

File diff suppressed because it is too large
+ 0 - 0
public/lib/gundb/gun.min.js


+ 13 - 0
public/lib/gundb/lib/afore.js

@@ -0,0 +1,13 @@
+function afore(tag, hear){
+	if(!tag){ return }
+	tag = tag.the; // grab the linked list root
+	var tmp = tag.to; // grab first listener
+	hear = tmp.on.on(tag.tag, hear); // add us to end
+	hear.to = tmp || hear.to; // make our next be current first
+	hear.back.to = hear.to; // make our back point to our next
+	tag.last = hear.back; // make last be same as before
+	hear.back = tag; // make our back be the start
+	tag.to = hear; // make the start be us
+	return hear;
+}
+if(typeof module !== "undefined"){ module.exports = afore } // afore(gun._.on('in'), function(){ })

+ 44 - 0
public/lib/gundb/lib/doll.js

@@ -0,0 +1,44 @@
+;(function(){ // jQuery shim
+	if(window.$){ return }
+	(($ = window.$ = function(q, tag){
+		if(!(this instanceof $)){ return new $(q, tag) }
+		this.tags = (q && q.tags) || (('string' != typeof q)?
+			(q?[q]:[]) : (tag||document).querySelectorAll(q));
+		return this;
+	}).fn = $.prototype).each = function(cb){ return $.each(this.tags, cb), this }
+	$.each = function(o, cb){ Object.keys(o).forEach(function(k){ cb(k, o[k]) }) }
+	$.fn.get = function(i, l, u){ return l = this.tags, (i === u)? l : l[i] }
+	$.fn.on = function(eve, cb){ return this.each(function(i, tag){ tag.addEventListener(eve, cb) })}
+	$.fn.is = function(q, b){ return this.each(function(i, tag){ b = b || tag.matches(q) }), b }
+	$.fn.css = function(obj){ return this.each(function(i, tag){ $.each(obj, function(k,v){ tag.style[k] = v }) })}
+	$.fn.text = function(text, key, f, u){
+		text = (text === u)? '' : (f = 1) && text;
+		key = key || 'textContent';
+		this.each(function(i, tag){
+			if(f){ tag[key] = text }
+			else { text += (tag[key]||'') }
+		});
+		return f? this : text;
+	}
+	$.fn.html = function(html){ return this.text(html, 'innerHTML') }
+	$.fn.find = function(q){
+		var I = $(), l = I.tags;
+		this.each(function(i, tag){
+			$(q, tag).each(function(i, tag){
+				if(0 > l.indexOf(tag)){ l.push(tag) }
+			});
+		});
+		return I;
+	}
+	$.fn.add = function(html, div){
+		(div = document.createElement('div')).innerHTML = html;
+		this.tags = [].slice.call(this.tags).concat([].slice.call(div.childNodes));
+		return this;
+	}
+	$.fn.append = function(html, op, f){ return this.each(function(i, tag){
+		(('<' === html[0])? $().add(html) : $(html)).each(function(i, node){
+			(f? node : tag)[op || 'appendChild'](f? tag : node);
+		})
+	})}
+	$.fn.appendTo = function(html){ return this.append(html, 0, 1) }
+}());

+ 12 - 0
public/lib/gundb/lib/email.js

@@ -0,0 +1,12 @@
+;(function(){
+	var email, fail = {send: function(opt, cb){ cb && cb("You do not have email installed.") } };
+	if(!process.env.EMAIL){ return module.exports = fail }
+	try{ email = require('emailjs') }catch(e){};
+	if(!email){ return module.exports = fail }
+	return module.exports = email.server.connect({
+	  user: process.env.EMAIL,
+	  password: process.env.EMAIL_KEY,
+	  host: process.env.EMAIL_HOST || "smtp.gmail.com",
+	  ssl: process.env.EMAIL_SSL || true
+	});
+}());

+ 95 - 0
public/lib/gundb/lib/hot.js

@@ -0,0 +1,95 @@
+;(function(){
+	// on fires when shortcut keydowns or on touch after command selected and then touchdown
+	var m = meta;
+	m.edit({name: "Add", combo: ['A']});
+	m.edit({name: "Row", combo: ['A', 'R'],
+		on: function(eve){
+			m.tap().append('<div class="hold center" style="min-height: 9em; padding: 2%;">');
+		}
+	});
+	m.edit({name: "Columns", combo: ['A','C'],
+		on: function(eve){
+			var on = m.tap(), tmp, c;
+			var html = '<div class="unit col" style="min-height: 9em; padding: 2%;"></div>';
+			if(!on.children('.col').length){ html += html }
+			c = (tmp = on.append(html).children('.col')).length;
+			tmp.each(function(){
+				$(this).css('width', (100/c)+'%');
+			})
+		}
+	});
+	m.edit({name: "Text", combo: ['A','T'],
+		on: function(eve){
+			m.tap().append('<p contenteditable="true">Text</p>');
+		}
+	});
+	m.edit({name: "Drag", combo: ['D']});
+	;(function(){
+		$(document).on('click', function(){
+			var tmp = $('.m-on');
+			if(!tmp.length){ return }
+			tmp.removeClass('m-on');
+		})
+		m.edit({combo: [38], // up
+			on: function(eve){
+				var on = m.tap().removeClass('m-on');
+				on = on.prev().or(on.parent()).or(on);
+				on.addClass('m-on');
+			}, up: function(){ 
+			}
+		});
+		m.edit({combo: [40], // down
+			on: function(eve){
+				var on = m.tap().removeClass('m-on');
+				on = on.next().or(on.children().first()).or(on);
+				on.addClass('m-on');
+			}, up: function(){ 
+			}
+		});
+		m.edit({combo: [39], // right
+			on: function(eve){
+				var on = m.tap().removeClass('m-on');
+				on = on.children().first().or(on.next()).or(on.parent()).or(on);
+				on.addClass('m-on');
+			}, up: function(){ 
+			}
+		});
+		m.edit({combo: [37], // left
+			on: function(eve){
+				var on = m.tap().removeClass('m-on');
+				on = on.parent().or(on);
+				on.addClass('m-on');
+			}, up: function(){ 
+			}
+		});
+	}());
+	m.edit({name: "Turn", combo: ['T']});
+	m.edit({name: "Size", combo: ['S']});
+	m.edit({name: "X", combo: ['S','X'],
+		on: function(eve){
+			var on = m.tap(), was = on.width();
+			$(document).on('mousemove.tmp', function(eve){
+				var be = was + ((eve.pageX||0) - was);
+				on.css({'max-width': be, width: '100%'});
+			})
+		}, up: function(){ $(document).off('mousemove.tmp') }
+	});
+	m.edit({name: "Y", combo: ['S','Y'],
+		on: function(eve){
+			var on = m.tap(), was = on.height();
+			$(document).on('mousemove.tmp', function(eve){
+				var be = was + ((eve.pageY||0) - was);
+				on.css({'min-height': be});
+			})
+		}, up: function(){ $(document).off('mousemove.tmp') }
+	});
+	m.edit({name: "Fill", combo: ['F'],
+		on: function(eve){
+			var on = m.tap();
+			m.ask('Color name, code, or URL?', function(color){
+				var css = on.closest('p').length? 'color' : 'background';
+				on.css(css, color);
+			});
+		}
+	});
+}());

+ 2 - 2
public/lib/gundb/lib/meta.js

@@ -1,4 +1,4 @@
-$(function(){
+;(function(){
 	var noop = function(){}, u;
 	var m = window.meta = {edit:[]};
 	var k = m.key = {};
@@ -380,4 +380,4 @@ $(function(){
 			up: function(){}
 		});
 	}());
-});
+}());

+ 17 - 0
public/lib/gundb/lib/mix.js

@@ -0,0 +1,17 @@
+;(function(){
+	var Gun = (typeof window !== "undefined")? window.Gun : require('../gun');
+	Gun.state.node = function(node, vertex, opt){
+		opt = opt || {};
+		opt.state = opt.state || Gun.state();
+		var now = Gun.obj.copy(vertex);
+		Gun.node.is(node, function(val, key){
+			var ham = Gun.HAM(opt.state, Gun.state.is(node, key), Gun.state.is(vertex, key), val, vertex[key]);
+			if(!ham.incoming){
+				// if(ham.defer){}
+				return;
+			}
+			now = Gun.state.to(node, key, now);
+		});
+		return now;
+	}
+}());

+ 34 - 10
public/lib/gundb/lib/multicast.js

@@ -4,22 +4,26 @@ Gun.on('create', function(root){
 	this.to.next(root);
 	var opt = root.opt;
   if(false === opt.multicast){ return }
-	if(true !== opt.multicast){ return } // disable multicast by default for now.
+  if((typeof process !== "undefined") && 'false' === ''+(process.env||{}).MULTICAST){ return }
+	//if(true !== opt.multicast){ return } // disable multicast by default for now.
 
   var udp = opt.multicast = opt.multicast || {};
   udp.address = udp.address || '233.255.255.255';
   udp.pack = udp.pack || 50000; // UDP messages limited to 65KB.
-  udp.port  = udp.port || 23456;
+  udp.port  = udp.port || 8765;
 
-  var noop = function(){}, port;
+  var noop = function(){}, u;
+  var pid = '2'+Math.random().toString().slice(-8);
+  var mesh = opt.mesh = opt.mesh || Gun.Mesh(root);
+  var dgram;
 
-  var dgram = require("dgram");
+  try{ dgram = require("dgram") }catch(e){ return }
   var socket = dgram.createSocket({type: "udp4", reuseAddr: true});
   socket.bind(udp.port);
 
-  socket.on("listening", function() {
+  socket.on("listening", function(){
     socket.addMembership(udp.address);
-    udp.peer = {url: udp.address + ':' + udp.port, wire: socket};
+    udp.peer = {id: udp.address + ':' + udp.port, wire: socket};
 
     udp.peer.say = function(raw){
       var buf = Buffer.from(raw, 'utf8');
@@ -28,9 +32,8 @@ Gun.on('create', function(root){
       }
       socket.send(buf, 0, buf.length, udp.port, udp.address, noop);
     }
-    opt.mesh.hi(udp.peer);
 
-    console.log('multicasting on', udp.peer.url);
+    console.log('Multicast on', udp.peer.id);
     return; // below code only needed for when WebSocket connections desired!
     setInterval(function broadcast(){
       port = port || (opt.web && opt.web.address()||{}).port;
@@ -42,6 +45,7 @@ Gun.on('create', function(root){
   socket.on("message", function(raw, info) { try {
     if(!raw){ return }
     raw = raw.toString('utf8');
+    if('2'===raw[0]){ return check(raw, info) }
     opt.mesh.hear(raw, udp.peer);
 
     return; // below code only needed for when WebSocket connections desired!
@@ -53,12 +57,32 @@ Gun.on('create', function(root){
     var url = 'http://' + info.address + ':' + (port || (opt.web && opt.web.address()||{}).port) + '/gun';
     if(root.opt.peers[url]){ return }
   
-    console.log('discovered', url, message, info);
+    //console.log('discovered', url, message, info);
     root.$.opt(url);
 
   } catch(e){
-    console.log('multicast error', e, raw);
+    //console.log('multicast error', e, raw);
     return;
   } });
 
+  function say(msg){
+    this.to.next(msg);
+    if(!udp.peer){ return }
+    mesh.say(msg, udp.peer);
+  }
+
+  function check(id, info){ var tmp;
+    if(!udp.peer){ return }
+    if(!id){
+      id = check.id = check.id || Buffer.from(pid, 'utf8');
+      socket.send(id, 0, id.length, udp.port, udp.address, noop);
+      return;
+    }
+    if((tmp = root.stats) && (tmp = tmp.gap) && info){ (tmp.near || (tmp.near = {}))[info.address] = info.port || 1 } // STATS!
+    if(check.on || id === pid){ return }
+    root.on('out', check.on = say);
+  }
+
+  setInterval(check, 1000 * 1);
+
 });

+ 8 - 4
public/lib/gundb/lib/open.js

@@ -35,15 +35,19 @@ Gun.chain.open = function(cb, opt, at){
 		}
 		var tmp = this, id;
 		Gun.obj.map(data, function(val, key){
+			var doc = at || opt.doc;
+			if (!doc) {
+				return;
+			}
 			if(!(id = Gun.val.link.is(val))){
-				(at || opt.doc)[key] = val;
+				doc[key] = val;
 				return;
 			}
 			if(opt.ids[id]){
-				(at || opt.doc)[key] = opt.ids[id];
+				doc[key] = opt.ids[id];
 				return;
 			}
-			tmp.get(key).open(opt.any, opt, opt.ids[id] = (at || opt.doc)[key] = {});
+			tmp.get(key).open(opt.any, opt, opt.ids[id] = doc[key] = {});
 		});
 	})
-}
+}

+ 9 - 3
public/lib/gundb/lib/serve.js

@@ -9,17 +9,18 @@ function CDN(dir){
 		if(serve(req, res)){ return } // filters GUN requests!
 		fs.createReadStream(path.join(dir, req.url)).on('error',function(tmp){ // static files!
 			try{ tmp = fs.readFileSync(path.join(dir, 'index.html')) }catch(e){}
-			res.writeHead(200, {'Content-Type': 'text/html'});
-			res.end(tmp+''); // or default to index
+			try{ res.writeHead(200, {'Content-Type': 'text/html'});
+			res.end(tmp+''); }catch(e){} // or default to index
 		}).pipe(res); // stream
 	}
 }
 
-function serve(req, res, next){
+function serve(req, res, next){ var tmp;
 	if(typeof req === 'string'){ return CDN(req) }
 	if(!req || !res){ return false }
 	next = next || serve;
 	if(!req.url){ return next() }
+	if(res.setHeader){ res.setHeader('Access-Control-Allow-Origin', '*') }
 	if(0 <= req.url.indexOf('gun.js')){
 		res.writeHead(200, {'Content-Type': 'text/javascript'});
 		res.end(serve.js = serve.js || require('fs').readFileSync(__dirname + '/../gun.js'));
@@ -34,6 +35,11 @@ function serve(req, res, next){
 			return true;
 		}
 	}
+	if((tmp = req.socket) && (tmp = tmp.server) && (tmp = tmp.route)){ var url;
+		if(tmp = tmp[(((req.url||'').slice(1)).split('/')[0]||'').split('.')[0]]){
+			try{ return tmp(req, res, next) }catch(e){ console.log(req.url+' crashed with '+e) }
+		}
+	} 
 	return next();
 }
 

+ 4 - 0
public/lib/gundb/lib/stats.js

@@ -19,10 +19,13 @@ Gun.on('opt', function(root){
 	os.loadavg = os.loadavg || noop;
 	os.cpus = os.cpus || noop;
 	setTimeout(function(){
+		root.opt.file += (process.argv[2]||'');
 		root.stats = Gun.obj.ify((fs.existsSync(__dirname+'/../stats.'+root.opt.file) && fs.readFileSync(__dirname+'/../stats.'+root.opt.file).toString())) || {};
 		root.stats.up = root.stats.up || {};
 		root.stats.up.start = root.stats.up.start || +(new Date);
 		root.stats.up.count = (root.stats.up.count || 0) + 1;
+		root.stats.stay = root.stats.stay || {};
+		root.stats.gap = {};
 	},1);
 	setInterval(function(){
 		if(!root.stats){ root.stats = {} }
@@ -50,6 +53,7 @@ Gun.on('opt', function(root){
 		}
 
 		fs.writeFile(__dirname+'/../stats.'+root.opt.file, JSON.stringify(stats, null, 2), function(err){});
+		stats.gap = {};
 	}, 1000 * 15);
 	Object.keys = Object.keys || function(o){ return Gun.obj.map(o, function(v,k,t){t(k)}) }
 });

+ 14 - 21
public/lib/gundb/lib/webrtc.js

@@ -31,16 +31,13 @@
     opt.rtc.dataChannel = opt.rtc.dataChannel || {ordered: false, maxRetransmits: 2};
     opt.rtc.sdp = opt.rtc.sdp || {mandatory: {OfferToReceiveAudio: false, OfferToReceiveVideo: false}};
     opt.announce = function(to){
-      //setTimeout(function() {
-	console.log('[WEBRTC] announce ', opt.pid, to); 
-	root.on('out', {rtc: {id: opt.pid, to:to}});
-//      }, 1);
-    }; // announce ourself
+			root.on('out', {rtc: {id: opt.pid, to:to}}); // announce ourself
+    };
 		var mesh = opt.mesh = opt.mesh || Gun.Mesh(root);
-// 		root.on('create', function(at){
-// 			this.to.next(at);
-// 			setTimeout(function(){ root.on('out', {rtc: {id: opt.pid}}) },1); // announce ourself
-// 		});
+		root.on('create', function(at){
+			this.to.next(at);
+			setTimeout(opt.announce, 1);
+		});
 		root.on('in', function(msg){
 			if(msg.rtc){ open(msg) }
 			this.to.next(msg);
@@ -51,30 +48,26 @@
 			if(!rtc || !rtc.id){ return }
 			delete opt.announce[rtc.id]; /// remove after connect
 			if(tmp = rtc.answer){
-				if(!(peer = opt.peers[rtc.id]) || peer.remoteSet){ return }
+				if(!(peer = opt.peers[rtc.id] || open[rtc.id]) || peer.remoteSet){ return }
 				return peer.setRemoteDescription(peer.remoteSet = new opt.RTCSessionDescription(tmp)); 
 			}
 			if(tmp = rtc.candidate){
-				peer = opt.peers[rtc.id] || open({rtc: {id: rtc.id}});
+				peer = opt.peers[rtc.id] || open[rtc.id] || open({rtc: {id: rtc.id}});
 				return peer.addIceCandidate(new opt.RTCIceCandidate(tmp));
 			}
-			if(opt.peers[rtc.id]){ return }
+			//if(opt.peers[rtc.id]){ return }
+			if(open[rtc.id]){ return }
 			(peer = new opt.RTCPeerConnection(opt.rtc)).id = rtc.id;
 			var wire = peer.wire = peer.createDataChannel('dc', opt.rtc.dataChannel);
-			mesh.hi(peer);
+			open[rtc.id] = peer;
 			wire.onclose = function(){
+				delete open[rtc.id];
 				mesh.bye(peer);
-				peer.wire = null;
 				//reconnect(peer);
 			};
-			wire.onerror = function(error){
-				//reconnect(peer); // placement?
-				if(!error){ return }
-				if(error.code === 'ECONNREFUSED'){
-					//reconnect(peer, as);
-				}
-			};
+			wire.onerror = function(err){};
 			wire.onopen = function(e){
+				//delete open[rtc.id];
 				mesh.hi(peer);
 			}
 			wire.onmessage = function(msg){

+ 1 - 1
public/lib/gundb/lib/wire.js

@@ -58,7 +58,7 @@ Gun.on('opt', function(root){
 
 	var url = require('url');
 	opt.WebSocket = opt.WebSocket || require('ws');
-	var ws = opt.ws || {};
+	var ws = opt.ws = opt.ws || {};
 	ws.server = ws.server || opt.web;
 
 	if(ws.server && !ws.web){

+ 1 - 1
public/lib/polyglot/language.js

@@ -52,4 +52,4 @@ class Lang {
 
 }
 
-export { Lang }
+export {Lang as default}

+ 3 - 3
public/vwf/view/document.js

@@ -57,13 +57,13 @@ define( [ "module", "vwf/view", "vwf/utility"], function( module, view, utility)
                let dbPath = appName + '_html';
               let worldName = path.slice(1);
               let userDB = _LCSDB.user(_LCS_WORLD_USER.pub);
-              userDB.get('worlds').get(worldName).get(dbPath).once().then(function(res) {
+
+              userDB.get('worlds').get(worldName).get(dbPath).get('file').then(function(res) {
                    
                    var responseText = "";
                    
-
                    if (res) { 
-                    responseText = res.file;
+                    responseText = res//.file;
                    }
 
                      // If the overlay attached a `createdNode` handler, forward this first call

+ 2 - 2
public/vwf/view/editor-new.js

@@ -3133,9 +3133,9 @@ define([
                     let worldName = self.helpers.getRoot(true).root;//url.split('/')[0];
                     let userDB = _LCSDB.user(_LCS_WORLD_USER.pub);
 
-                    userDB.get('worlds').get(worldName).get(fileName).once(res => {
+                    userDB.get('worlds').get(worldName).get(fileName).get('file').once(res => {
 
-                        this._importScript(res.file);
+                        this._importScript(res);
                     })
 
 

+ 2 - 2
public/web/index-app.js

@@ -3,7 +3,7 @@ The MIT License (MIT)
 Copyright (c) 2014-2018 Nikolai Suslov and the Krestianstvo.org project contributors. (https://github.com/NikolaySuslov/livecodingspace/blob/master/LICENSE.md)
 */
 
-import page from '/lib/page.mjs';
+//import page from '/lib/page.mjs';
 import { Header } from '/web/header.js';
 
 
@@ -1052,5 +1052,5 @@ class IndexApp {
 
 
 }
-export { IndexApp }
+export { IndexApp as default }
     //export {getAppDetails, generateFrontPage, setLanguage, initLocale};

+ 3 - 4
public/web/world-app.js

@@ -3,7 +3,7 @@ The MIT License (MIT)
 Copyright (c) 2014-2018 Nikolai Suslov and the Krestianstvo.org project contributors. (https://github.com/NikolaySuslov/livecodingspace/blob/master/LICENSE.md)
 */
 
-import page from '/lib/page.mjs';
+//import page from '/lib/page.mjs';
 
 class WorldApp {
     constructor(userAlias, worldName, saveName) {
@@ -509,7 +509,7 @@ class WorldApp {
     }
 
 
-    async initWorldGUI() {
+    initWorldGUI() {
 
         //  _LCSDB.on('auth',
         //     function (ack) {
@@ -519,8 +519,7 @@ class WorldApp {
         //     });
 
         let self = this;
-        let users = await _LCSDB.get('users').then();
-        await _LCSDB.get('users').get(this.userAlias).get('pub').then(function (res) {
+     _LCSDB.get('users').get(this.userAlias).get('pub').once(function (res) {
 
             self.makeGUI(res)
 

Some files were not shown because too many files changed in this diff