mirror of
https://github.com/amark/gun.git
synced 2025-03-30 15:08:33 +00:00
Merge to gun/master 0.9.94 conflicts resolved
This commit is contained in:
commit
b7aa61f57e
@ -1,6 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Converse</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
|
||||
<link rel="stylesheet" type="text/css" href="/style.css">
|
||||
<link href='https://fonts.googleapis.com/css?family=Poiret+One' rel='stylesheet' type='text/css'>
|
||||
@ -49,7 +50,7 @@
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.send {
|
||||
.say {
|
||||
margin: 0 0 0.4em 0.4em;
|
||||
padding: 0.2em 0.5em;
|
||||
}
|
||||
@ -75,7 +76,7 @@
|
||||
|
||||
<form class="white huet2 box">
|
||||
<div>
|
||||
<div class="send hue2 right whitet box act">send</div>
|
||||
<div class="say hue2 right whitet box act">say</div>
|
||||
<b id="name-input" class="jot left who" contenteditable="true" data-text="Name"></b>
|
||||
<p id="message-input" class="jot left what" contenteditable="true" data-text="Write a message..."></p>
|
||||
</div>
|
||||
@ -98,75 +99,62 @@
|
||||
<script src="/gun/nts.js"></script>
|
||||
<script>
|
||||
var gun = Gun(location.origin + '/gun');
|
||||
var chat = gun.get('converse');
|
||||
var chat = gun.get('converse/' + location.hash.slice(1));
|
||||
|
||||
chat.map()
|
||||
.val(mapChatToUI);
|
||||
$("form .send").on('click', submit);
|
||||
$("form .what").on('keydown', handleEnterPressed);
|
||||
|
||||
function mapChatToUI (msg, field) {
|
||||
var ul = $('ul'),
|
||||
last = sort(field, ul.children('li').last());
|
||||
|
||||
// Grab message to update or model
|
||||
var msgField = $("#msg-" + field)[0];
|
||||
if (!msgField) {
|
||||
msgField = $('.model li')
|
||||
.clone(true)
|
||||
.attr('id', 'msg-' + field)
|
||||
.insertAfter(last);
|
||||
}
|
||||
|
||||
// Merge message data to UI model
|
||||
var li = $(msgField);
|
||||
li.find('.who').text(msg.who);
|
||||
li.find('.what').text(msg.what);
|
||||
li.find('.sort').text(field);
|
||||
|
||||
var time = new Date(msg.when);
|
||||
li.find('.when').text(time.toDateString() + ', ' + time.toLocaleTimeString());
|
||||
|
||||
$('html, body').stop(true, true)
|
||||
.animate({
|
||||
scrollTop: ul.height(),
|
||||
});
|
||||
$("form .say").on('click', submit);
|
||||
$("form .what").on('keydown', enter);
|
||||
function enter(e){
|
||||
if(e.which !== 13){ return }
|
||||
submit(e);
|
||||
}
|
||||
|
||||
function submit (e) {
|
||||
function submit(e){
|
||||
e.preventDefault();
|
||||
|
||||
var msg = {
|
||||
when: Gun.time.is(),
|
||||
};
|
||||
var msg = {when: Gun.time.is()};
|
||||
|
||||
msg.who = $('form .who').text();
|
||||
if (!msg.who) {
|
||||
if(!msg.who){
|
||||
msg.who = 'user' + Gun.text.random(3);
|
||||
$('form .who').text(msg.who);
|
||||
}
|
||||
|
||||
msg.what = $('form .what').text();
|
||||
if (!msg.what) {
|
||||
return;
|
||||
}
|
||||
if(!msg.what){ return }
|
||||
|
||||
chat.get(msg.when + 'r' + Gun.text.random(3)).put(msg);
|
||||
chat.set(msg);
|
||||
$('form .what').text('');
|
||||
}
|
||||
|
||||
function handleEnterPressed (e) {
|
||||
if (e.which == 13) {
|
||||
submit(e);
|
||||
}
|
||||
}
|
||||
chat.map().val(function(msg, id){
|
||||
var ul = $('ul');
|
||||
var last = sort(msg.when, ul.children('li').last());
|
||||
|
||||
function sort(fieldId, element) {
|
||||
var numericId = parseFloat(fieldId);
|
||||
var idFromText = $(element).find('.sort').text() || -Infinity;
|
||||
var currentId = numericId >= parseFloat(idFromText);
|
||||
return currentId ? element : sort(fieldId, element.prev());
|
||||
var li = $("#msg-" + id)[0]; // grab if exists
|
||||
if(!li){
|
||||
li = $('.model li').clone(true) // else create it
|
||||
.attr('id', 'msg-' + id)
|
||||
.insertAfter(last);
|
||||
}
|
||||
|
||||
// bind the message data into the UI
|
||||
li = $(li);
|
||||
li.find('.who').text(msg.who);
|
||||
li.find('.what').text(msg.what);
|
||||
li.find('.sort').text(msg.when);
|
||||
|
||||
var time = new Date(msg.when);
|
||||
li.find('.when').text(time.toDateString() + ', ' + time.toLocaleTimeString());
|
||||
|
||||
$('html, body').stop(true, true)
|
||||
.animate({scrollTop: ul.height()});
|
||||
});
|
||||
|
||||
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());
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
@ -4,12 +4,10 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" type="text/css" href="../style.css">
|
||||
</head>
|
||||
<body class="whitet black">
|
||||
|
||||
<body>
|
||||
<div id="sign" class="hue page">
|
||||
<style>
|
||||
input, button {
|
||||
font-size: 1em;
|
||||
margin: 1em 0;
|
||||
padding: 1em;
|
||||
}
|
||||
@ -17,15 +15,6 @@
|
||||
display: inline-block;
|
||||
width: 15%;
|
||||
}
|
||||
.loading {
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
@keyframes pulse
|
||||
{
|
||||
0% {opacity: 1;}
|
||||
50% {opacity: 0.5;}
|
||||
100% {opacity: 1;}
|
||||
}
|
||||
</style>
|
||||
<form id="inup" class="sign pad center">
|
||||
<div class="loud">Welcome,</div>
|
||||
@ -212,10 +201,10 @@
|
||||
c.tell("Passphrase needs to be longer than 9 characters.");
|
||||
return;
|
||||
}
|
||||
but.addClass('loading');
|
||||
but.addClass('pulse');
|
||||
data.alias = data.alias.toLowerCase();
|
||||
user.create(data.alias, data.pass, function(ack){
|
||||
if(!ack.wait){ but.removeClass('loading') }
|
||||
if(!ack.wait){ but.removeClass('pulse') }
|
||||
if(ack.err){ c.tell(ack.err); return }
|
||||
if(ack.pub){
|
||||
gun.get('users').get(data.alias).put(gun.get('alias/'+data.alias));
|
||||
@ -237,10 +226,10 @@
|
||||
return;
|
||||
}
|
||||
var but = form.find('button:first');
|
||||
but.addClass('loading');
|
||||
but.addClass('pulse');
|
||||
data.alias = data.alias.toLowerCase();
|
||||
user.auth(data.alias, data.pass, function(ack){
|
||||
if(!ack.wait){ but.removeClass('loading') }
|
||||
if(!ack.wait){ but.removeClass('pulse') }
|
||||
if(ack.err){ c.tell(ack.err); return }
|
||||
session(data);
|
||||
});
|
||||
|
@ -5,24 +5,33 @@ html, body {
|
||||
padding: 0;
|
||||
font-family: 'Oxygen', 'Trebuchet MS', arial;
|
||||
position: relative;
|
||||
background: black;
|
||||
color: white;
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: 18pt;
|
||||
}
|
||||
|
||||
div, ul, li, form, p, span, button, input, textarea {
|
||||
div, ul, li, p, span, form, button, input, textarea {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
font-size: 1em;
|
||||
line-height: 1.5em;
|
||||
-webkit-transition: all 0.3s;
|
||||
transition: all 0.3s;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
button, input, textarea {
|
||||
background: white;
|
||||
border: none;
|
||||
color: black;
|
||||
}
|
||||
|
||||
input, textarea {
|
||||
border: none;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@ -132,6 +141,17 @@ ul, li {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.pulse {
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
|
||||
@keyframes pulse
|
||||
{
|
||||
0% {opacity: 1;}
|
||||
50% {opacity: 0.5;}
|
||||
100% {opacity: 1;}
|
||||
}
|
||||
|
||||
.hue {
|
||||
background: #4D79D8;
|
||||
-webkit-animation: hue 900s infinite;
|
||||
|
@ -1,6 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Think</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
|
||||
<link rel="stylesheet" type="text/css" href="/style.css">
|
||||
</head>
|
||||
@ -50,7 +51,7 @@
|
||||
// for how to build a simplified version
|
||||
// of this example: https://scrimba.com/c/cW2Vsa
|
||||
var gun = Gun(location.origin+'/gun');
|
||||
var think = gun.get('think');
|
||||
var think = gun.get('think/' + location.hash.slice(1));
|
||||
var typing, throttle;
|
||||
$('.add').on('click', function(){
|
||||
$('<li>').attr('contenteditable', true).prependTo('ul');
|
||||
|
@ -1,11 +1,11 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>GPS by GUN</title>
|
||||
<title>Where</title>
|
||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport" />
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.0.3/dist/leaflet.css"/>
|
||||
<script src="https://unpkg.com/leaflet@1.0.3/dist/leaflet.js"></script>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/leaflet@1.0.3/dist/leaflet.css"/>
|
||||
<script src="https://cdn.jsdelivr.net/npm/leaflet@1.0.3/dist/leaflet.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="map"></div>
|
||||
@ -68,7 +68,7 @@
|
||||
word-wrap: break-word;
|
||||
}
|
||||
</style>
|
||||
<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
|
||||
<script src="/jquery.js"></script>
|
||||
<script src="/gun.js"></script>
|
||||
<script>
|
||||
function Where(opt, cb){
|
||||
@ -96,7 +96,7 @@
|
||||
where.map.on('zoomlevelschange', where.opt.zoom.ing, where.opt.err);
|
||||
|
||||
where.update = function(latlng){
|
||||
if(new Date().getTime() - where.update.last < 1000){
|
||||
if((+new Date) - where.update.last < 400){
|
||||
clearTimeout(where.update.to);
|
||||
where.update.to = setTimeout(function(){
|
||||
where.update(latlng);
|
||||
@ -106,7 +106,7 @@
|
||||
where.map.setView(latlng, where.opt.zoom.level, {animate: true});
|
||||
where.marker = where.marker || L.marker().setLatLng(latlng).addTo(where.map);
|
||||
where.marker.setLatLng(latlng).update();
|
||||
where.update.last = new Date().getTime();
|
||||
where.update.last = (+new Date);
|
||||
}
|
||||
|
||||
if(where.opt.track){
|
||||
@ -149,7 +149,7 @@
|
||||
//$('#debug').value = 'track ' + JSON.stringify(latlng);
|
||||
gps.where.update(latlng);
|
||||
});
|
||||
$('#share').toggleClass("hide");
|
||||
$('#share').addClass("hide");
|
||||
} else {
|
||||
document.cookie = 'gps=' + (gps.track = (document.cookie.match(/gps\=(.*?)(\&|$|\;)/i)||[])[1] || Gun.text.random(5)); // trick with cookies!
|
||||
gps.ref = gun.get('gps/' + gps.track);
|
||||
@ -165,8 +165,8 @@
|
||||
//$('#debug').value = JSON.stringify(gps.last);
|
||||
}
|
||||
gps.where = gps.where || Where(gps.opt);
|
||||
$('#follow').text(("gps.gunDB.io/" || (location.origin + location.pathname)) + '#' + gps.track);
|
||||
$('#share').toggleClass("hide");
|
||||
$('#follow').text(("where.gunDB.io/" || (location.origin + location.pathname)) + '#' + gps.track);
|
||||
$('#share').removeClass("hide");
|
||||
$('#share').on('click', function(){
|
||||
$('#link').toggleClass("hide");
|
||||
});
|
31
gun.js
31
gun.js
@ -288,6 +288,7 @@
|
||||
}
|
||||
}());
|
||||
Val.rel.ify = function(t){ return obj_put({}, rel_, t) } // convert a soul into a relation and return it.
|
||||
Type.obj.has._ = '.';
|
||||
var rel_ = Val.rel._, u;
|
||||
var bi_is = Type.bi.is;
|
||||
var num_is = Type.num.is;
|
||||
@ -711,7 +712,10 @@
|
||||
if(!Gun.graph.is(msg.put, null, verify, ctx)){ ctx.err = "Error: Invalid graph!" }
|
||||
if(ctx.err){ return at.on('in', {'@': msg['#'], err: Gun.log(ctx.err) }) }
|
||||
obj_map(ctx.put, merge, ctx);
|
||||
if(!ctx.async){ obj_map(ctx.map, map, ctx) }
|
||||
if(!ctx.async){
|
||||
at.stop = {}; // temporary fix till a better solution?
|
||||
obj_map(ctx.map, map, ctx)
|
||||
}
|
||||
if(u !== ctx.defer){
|
||||
setTimeout(function(){
|
||||
Gun.on.put(msg, gun);
|
||||
@ -760,6 +764,7 @@
|
||||
if(obj_map(ctx.souls, function(v){ if(v){ return v } })){ return } // if flag still outstanding, keep waiting.
|
||||
if(ctx.c){ return } ctx.c = 1; // failsafe for only being called once per context.
|
||||
this.off();
|
||||
cat.stop = {}; // temporary fix till a better solution?
|
||||
obj_map(ctx.map, map, ctx); // all done, trigger chains.
|
||||
});
|
||||
}
|
||||
@ -778,10 +783,8 @@
|
||||
}
|
||||
function map(msg, soul){
|
||||
if(!msg.gun){ return }
|
||||
msg.gun._.root._.stop = {};
|
||||
//console.log('map ->', soul, msg.put);
|
||||
(msg.gun._).on('in', msg);
|
||||
msg.gun._.root._.stop = {};
|
||||
}
|
||||
|
||||
Gun.on.get = function(msg, gun){
|
||||
@ -944,9 +947,7 @@
|
||||
//if(u !== back.put){
|
||||
back.on('in', back);
|
||||
}
|
||||
if(back.ack){
|
||||
return;
|
||||
}
|
||||
if(back.ack){ return }
|
||||
msg.gun = back.gun;
|
||||
back.ack = -1;
|
||||
} else
|
||||
@ -1002,7 +1003,7 @@
|
||||
}
|
||||
if(u === change){
|
||||
ev.to.next(msg);
|
||||
if(cat.soul){ return }
|
||||
if(cat.soul){ return } // TODO: BUG, I believe the fresh input refactor caught an edge case that a `gun.get('soul').get('key')` that points to a soul that doesn't exist will not trigger val/get etc.
|
||||
echo(cat, msg, ev);
|
||||
if(cat.has){
|
||||
not(cat, msg);
|
||||
@ -1017,13 +1018,6 @@
|
||||
obj_map(change, map, {at: msg, cat: cat});
|
||||
return;
|
||||
}
|
||||
/*if(rel = Gun.val.rel.is(change)){
|
||||
if(tmp = (gun.back(-1).get(rel)._).put){
|
||||
change = tmp; // this will cause performance to turn to mush, maybe use `.now` check?
|
||||
}
|
||||
//if(tmp.put){ change = tmp.put; }
|
||||
}
|
||||
if(!rel || tmp){*/
|
||||
if(!(rel = Gun.val.rel.is(change))){
|
||||
if(Gun.val.is(change)){
|
||||
if(cat.has || cat.soul){
|
||||
@ -1078,10 +1072,11 @@
|
||||
// neither of these are ideal, need to be fixed without hacks,
|
||||
// but for now, this works for current tests. :/
|
||||
if(!now){
|
||||
var stop = at.root._.stop;
|
||||
return;
|
||||
/*var stop = at.root._.stop;
|
||||
if(!stop){ return }
|
||||
if(stop[at.id] === rel){ return }
|
||||
stop[at.id] = rel;
|
||||
stop[at.id] = rel;*/
|
||||
} else {
|
||||
if(u === now[at.id]){ return }
|
||||
if((now._ || (now._ = {}))[at.id] === rel){ return }
|
||||
@ -1151,7 +1146,6 @@
|
||||
function ask(at, soul){
|
||||
var tmp = (at.root.get(soul)._);
|
||||
if(at.ack){
|
||||
//tmp.ack = tmp.ack || -1;
|
||||
tmp.on('out', {get: {'#': soul}});
|
||||
if(!at.ask){ return } // TODO: PERFORMANCE? More elegant way?
|
||||
}
|
||||
@ -1371,13 +1365,14 @@
|
||||
// and STOP is a hack to get async behavior to correctly call.
|
||||
// neither of these are ideal, need to be fixed without hacks,
|
||||
// but for now, this works for current tests. :/
|
||||
var tmp = cat.root._.now; obj.del(cat.root._, 'now');
|
||||
var tmp = cat.root._.now; obj.del(cat.root._, 'now'); cat.root._.PUT = true;
|
||||
var tmp2 = cat.root._.stop;
|
||||
(as.ref._).now = true;
|
||||
(as.ref._).on('out', {
|
||||
gun: as.ref, put: as.out = as.env.graph, opt: as.opt, '#': ask
|
||||
});
|
||||
obj.del((as.ref._), 'now');
|
||||
obj.del((cat.root._), 'PUT');
|
||||
cat.root._.now = tmp;
|
||||
cat.root._.stop = tmp2;
|
||||
}, as);
|
||||
|
2
gun.min.js
vendored
2
gun.min.js
vendored
File diff suppressed because one or more lines are too long
50
lib/untitled.js
Normal file
50
lib/untitled.js
Normal file
@ -0,0 +1,50 @@
|
||||
function input(msg){
|
||||
var ev = this, cat = this.as, gun = msg.gun, at = gun._, change = msg.put, rel, tmp;
|
||||
// dispatch to chain listeners.
|
||||
// dispatch to children.
|
||||
// dispatch to echoes.
|
||||
if(u === change){
|
||||
// Here are the possible options:
|
||||
// 1. We think the data does not exist because peers/disk cannot find it.
|
||||
// 2. We know the data does not exist because a parent is or was changed to a primitive.
|
||||
// Souls can only (1) because they have no parent.
|
||||
// Has can be (1) or (2).
|
||||
// Gets and chains can be (1) or (2).
|
||||
if(cat.soul || cat.has){
|
||||
// a soul can never become undefined.
|
||||
// a soul can only not be found.
|
||||
if(cat.soul && u !== cat.put){
|
||||
return;
|
||||
}
|
||||
// a key may sometimes might not be found.
|
||||
// a key on a soul can not become undefined,
|
||||
// but the chain might be on a chain that
|
||||
// does not exist, and therefore can be undefined.
|
||||
ev.to.next(msg); // ex, notify val and stuff.
|
||||
echo(cat, msg, ev); // ex, notify a sub-object pointer like `mark.pet`! // TODO: BUG ON VAL, it will still not get called because it checks !node when it should also check ack.
|
||||
if(cat.soul){ return }
|
||||
obj_map(cat.next, unknown); // notify children.
|
||||
}
|
||||
if(cat.has){
|
||||
if()
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(cat.soul){
|
||||
return;
|
||||
}
|
||||
if(cat.has){
|
||||
return;
|
||||
}
|
||||
if(cat.get){
|
||||
return;
|
||||
}
|
||||
ev.to.next(msg);
|
||||
}
|
||||
|
||||
function unknown(ref, key){
|
||||
(ref = (ref._)).put = u;
|
||||
ref.on('in', {get: key, put: u, gun: ref.gun});
|
||||
}
|
||||
|
||||
gun.get('users').map().map().get('who').get('say').map().on(cb);
|
40
lib/upload.js
Normal file
40
lib/upload.js
Normal file
@ -0,0 +1,40 @@
|
||||
;(function(){
|
||||
function upload(cb, opt){
|
||||
var el = $(this); cb = cb || function(){}; opt = opt || {};
|
||||
el.on('drop', function(e){
|
||||
e.preventDefault();
|
||||
upload.drop(((e.originalEvent||{}).dataTransfer||{}).files, 0);
|
||||
}).on('dragover', function(e){
|
||||
e.preventDefault();
|
||||
});
|
||||
upload.drop = function(files,i){
|
||||
if(opt.max && (files[i].fileSize > opt.max || files[i].size > opt.max)){
|
||||
cb({err: "File size is too large.", file: file[i]}, upload);
|
||||
if(files[++i]){ upload.drop(files,i) }
|
||||
return false;
|
||||
}
|
||||
reader = new FileReader();
|
||||
reader.onload = function(e){
|
||||
cb({file: files[i], event: e, id: i}, upload);
|
||||
if(files[++i]){ upload.drop(files,i) }
|
||||
};
|
||||
if(files[i]){ reader.readAsDataURL(files[i]) }
|
||||
}
|
||||
}
|
||||
upload.shrink = function(e, cb, w, h){ // via stackoverflow
|
||||
if(!e){ return cb && cb({err: "No file!"}) }
|
||||
if(e.err){ return }
|
||||
var file = (((e.event || e).target || e).result || e), img = new Image();
|
||||
img.src = file;
|
||||
img.onload = function(){
|
||||
if(!h && img.width > w){ h = img.height * (w / img.width) }
|
||||
var canvas = document.createElement('canvas'), ctx = canvas.getContext('2d');
|
||||
canvas.width = w;
|
||||
canvas.height = h;
|
||||
ctx.drawImage(img, 0, 0, w, h); // draw source image to canvas.
|
||||
var b64 = e.base64 = canvas.toDataURL(); // base64 the compressed image.
|
||||
cb((e.base64 && e) || b64);
|
||||
};
|
||||
}
|
||||
$.fn.upload = upload;
|
||||
}());
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "gun",
|
||||
"version": "0.9.93",
|
||||
"version": "0.9.94",
|
||||
"description": "A realtime, decentralized, offline-first, graph data synchronization engine.",
|
||||
"main": "index.js",
|
||||
"browser": "gun.min.js",
|
||||
|
19
src/chain.js
19
src/chain.js
@ -32,9 +32,7 @@ function output(msg){
|
||||
//if(u !== back.put){
|
||||
back.on('in', back);
|
||||
}
|
||||
if(back.ack){
|
||||
return;
|
||||
}
|
||||
if(back.ack){ return }
|
||||
msg.gun = back.gun;
|
||||
back.ack = -1;
|
||||
} else
|
||||
@ -90,7 +88,7 @@ function input(msg){
|
||||
}
|
||||
if(u === change){
|
||||
ev.to.next(msg);
|
||||
if(cat.soul){ return }
|
||||
if(cat.soul){ return } // TODO: BUG, I believe the fresh input refactor caught an edge case that a `gun.get('soul').get('key')` that points to a soul that doesn't exist will not trigger val/get etc.
|
||||
echo(cat, msg, ev);
|
||||
if(cat.has){
|
||||
not(cat, msg);
|
||||
@ -105,13 +103,6 @@ function input(msg){
|
||||
obj_map(change, map, {at: msg, cat: cat});
|
||||
return;
|
||||
}
|
||||
/*if(rel = Gun.val.rel.is(change)){
|
||||
if(tmp = (gun.back(-1).get(rel)._).put){
|
||||
change = tmp; // this will cause performance to turn to mush, maybe use `.now` check?
|
||||
}
|
||||
//if(tmp.put){ change = tmp.put; }
|
||||
}
|
||||
if(!rel || tmp){*/
|
||||
if(!(rel = Gun.val.rel.is(change))){
|
||||
if(Gun.val.is(change)){
|
||||
if(cat.has || cat.soul){
|
||||
@ -166,10 +157,11 @@ function relate(at, msg, from, rel){
|
||||
// neither of these are ideal, need to be fixed without hacks,
|
||||
// but for now, this works for current tests. :/
|
||||
if(!now){
|
||||
var stop = at.root._.stop;
|
||||
return;
|
||||
/*var stop = at.root._.stop;
|
||||
if(!stop){ return }
|
||||
if(stop[at.id] === rel){ return }
|
||||
stop[at.id] = rel;
|
||||
stop[at.id] = rel;*/
|
||||
} else {
|
||||
if(u === now[at.id]){ return }
|
||||
if((now._ || (now._ = {}))[at.id] === rel){ return }
|
||||
@ -239,7 +231,6 @@ function not(at, msg){
|
||||
function ask(at, soul){
|
||||
var tmp = (at.root.get(soul)._);
|
||||
if(at.ack){
|
||||
//tmp.ack = tmp.ack || -1;
|
||||
tmp.on('out', {get: {'#': soul}});
|
||||
if(!at.ask){ return } // TODO: PERFORMANCE? More elegant way?
|
||||
}
|
||||
|
@ -101,13 +101,14 @@ function batch(){ var as = this;
|
||||
// and STOP is a hack to get async behavior to correctly call.
|
||||
// neither of these are ideal, need to be fixed without hacks,
|
||||
// but for now, this works for current tests. :/
|
||||
var tmp = cat.root._.now; obj.del(cat.root._, 'now');
|
||||
var tmp = cat.root._.now; obj.del(cat.root._, 'now'); cat.root._.PUT = true;
|
||||
var tmp2 = cat.root._.stop;
|
||||
(as.ref._).now = true;
|
||||
(as.ref._).on('out', {
|
||||
gun: as.ref, put: as.out = as.env.graph, opt: as.opt, '#': ask
|
||||
});
|
||||
obj.del((as.ref._), 'now');
|
||||
obj.del((cat.root._), 'PUT');
|
||||
cat.root._.now = tmp;
|
||||
cat.root._.stop = tmp2;
|
||||
}, as);
|
||||
|
@ -67,7 +67,10 @@ Gun.dup = require('./dup');
|
||||
if(!Gun.graph.is(msg.put, null, verify, ctx)){ ctx.err = "Error: Invalid graph!" }
|
||||
if(ctx.err){ return at.on('in', {'@': msg['#'], err: Gun.log(ctx.err) }) }
|
||||
obj_map(ctx.put, merge, ctx);
|
||||
if(!ctx.async){ obj_map(ctx.map, map, ctx) }
|
||||
if(!ctx.async){
|
||||
at.stop = {}; // temporary fix till a better solution?
|
||||
obj_map(ctx.map, map, ctx)
|
||||
}
|
||||
if(u !== ctx.defer){
|
||||
setTimeout(function(){
|
||||
Gun.on.put(msg, gun);
|
||||
@ -116,6 +119,7 @@ Gun.dup = require('./dup');
|
||||
if(obj_map(ctx.souls, function(v){ if(v){ return v } })){ return } // if flag still outstanding, keep waiting.
|
||||
if(ctx.c){ return } ctx.c = 1; // failsafe for only being called once per context.
|
||||
this.off();
|
||||
cat.stop = {}; // temporary fix till a better solution?
|
||||
obj_map(ctx.map, map, ctx); // all done, trigger chains.
|
||||
});
|
||||
}
|
||||
@ -134,10 +138,8 @@ Gun.dup = require('./dup');
|
||||
}
|
||||
function map(msg, soul){
|
||||
if(!msg.gun){ return }
|
||||
msg.gun._.root._.stop = {};
|
||||
//console.log('map ->', soul, msg.put);
|
||||
(msg.gun._).on('in', msg);
|
||||
msg.gun._.root._.stop = {};
|
||||
}
|
||||
|
||||
Gun.on.get = function(msg, gun){
|
||||
|
@ -34,6 +34,7 @@ Val.rel = {_: '#'};
|
||||
}
|
||||
}());
|
||||
Val.rel.ify = function(t){ return obj_put({}, rel_, t) } // convert a soul into a relation and return it.
|
||||
Type.obj.has._ = '.';
|
||||
var rel_ = Val.rel._, u;
|
||||
var bi_is = Type.bi.is;
|
||||
var num_is = Type.num.is;
|
||||
|
@ -3753,18 +3753,18 @@ describe('Gun', function(){
|
||||
}, 1);
|
||||
|
||||
});
|
||||
return;
|
||||
it.only('get map should not slowdown', function(done){
|
||||
|
||||
it('get map should not slowdown', function(done){
|
||||
this.timeout(5000);
|
||||
var gun = (window.gun = Gun()).get('g/m/no/slow');
|
||||
var gun = Gun().get('g/m/no/slow');
|
||||
//console.log("---------- setup data done -----------");
|
||||
var prev, diff, max = 25, total = 2, largest = -1, gone = {};
|
||||
var prev, diff, max = 25, total = 9, largest = -1, gone = {};
|
||||
//var prev, diff, max = Infinity, total = 10000, largest = -1, gone = {};
|
||||
// TODO: It would be nice if we could change these numbers for different platforms/versions of javascript interpreters so we can squeeze as much out of them.
|
||||
gun.get('history').map().on(function(time, index){
|
||||
console.log(">>>", index, time);
|
||||
//console.log(">>>", index, time);
|
||||
diff = Gun.time.is() - time;
|
||||
return;
|
||||
//return;
|
||||
expect(gone[index]).to.not.be.ok();
|
||||
gone[index] = diff;
|
||||
largest = (largest < diff)? diff : largest;
|
||||
@ -3783,8 +3783,8 @@ describe('Gun', function(){
|
||||
prev = Gun.time.is();
|
||||
var put = {}; put[turns += 1] = prev;
|
||||
//console.log("put", put);
|
||||
console.log("------", turns, "-------");
|
||||
2 === turns && (console.debug.i = 1);
|
||||
//console.log("------", turns, "-------");
|
||||
//3 === turns && (console.debug.i = 1);
|
||||
console.debug(1, 'save', {history: put});
|
||||
gun.put({history: put});
|
||||
}, 1);
|
||||
|
322
test/panic/speak.js
Normal file
322
test/panic/speak.js
Normal file
@ -0,0 +1,322 @@
|
||||
var config = {
|
||||
IP: require('ip').address(),
|
||||
port: 8080,
|
||||
servers: 1,
|
||||
browsers: 2,
|
||||
each: 250,
|
||||
burst: 1, // do not go below 1!
|
||||
wait: 1,
|
||||
route: {
|
||||
'/': __dirname + '/index.html',
|
||||
'/gun.js': __dirname + '/../../gun.js',
|
||||
'/jquery.js': __dirname + '/../../examples/jquery.js',
|
||||
'/cryptomodules.js': __dirname + '/../../lib/cryptomodules.js',
|
||||
'/sea.js': __dirname + '/../../sea.js'
|
||||
}
|
||||
}
|
||||
|
||||
var fs = require('fs');
|
||||
var server = require('https').createServer({
|
||||
key: fs.readFileSync(__dirname+'/../https/server.key'),
|
||||
cert: fs.readFileSync(__dirname+'/../https/server.crt'),
|
||||
ca: fs.readFileSync(__dirname+'/../https/ca.crt'),
|
||||
requestCert: true,
|
||||
rejectUnauthorized: false
|
||||
});
|
||||
|
||||
var panic = require('panic-server');
|
||||
panic.server(server).on('request', function(req, res){
|
||||
config.route[req.url] && require('fs').createReadStream(config.route[req.url]).pipe(res);
|
||||
}).listen(config.port);
|
||||
|
||||
var clients = panic.clients;
|
||||
var manager = require('panic-manager')();
|
||||
|
||||
manager.start({
|
||||
clients: Array(config.servers).fill().map(function(u, i){
|
||||
return {
|
||||
type: 'node',
|
||||
port: config.port + (i + 1)
|
||||
}
|
||||
}),
|
||||
panic: 'https://' + config.IP + ':' + config.port
|
||||
});
|
||||
|
||||
// Now lets divide our clients into "servers" and "browsers".
|
||||
var servers = clients.filter('Node.js');
|
||||
var browsers = clients.excluding(servers);
|
||||
|
||||
// Sweet! Now we can start the tests.
|
||||
// PANIC works with Mocha and other testing libraries!
|
||||
// So it is easy to use PANIC.
|
||||
|
||||
describe("Stress test GUN with SEA users causing PANIC!", function(){
|
||||
this.timeout(10 * 60 * 1000);
|
||||
|
||||
it("Servers have joined!", function(){
|
||||
return servers.atLeast(config.servers);
|
||||
});
|
||||
|
||||
it("GUN has spawned!", function(){
|
||||
// Once they are, we need to actually spin up the gun server.
|
||||
var tests = [], i = 0;
|
||||
servers.each(function(client){
|
||||
// for each server peer, tell it to run this code:
|
||||
tests.push(client.run(function(test){
|
||||
// NOTE: Despite the fact this LOOKS like we're in a closure...
|
||||
// it is not! This code is actually getting run
|
||||
// in a DIFFERENT machine or process!
|
||||
var env = test.props;
|
||||
// As a result, we have to manually pass it scope.
|
||||
test.async();
|
||||
//setInterval(function(){ var u, t; u = process.memoryUsage().heapUsed; t = require('os').totalmem(); console.log((u/t).toFixed(2)) }, 1000)
|
||||
// Clean up from previous test.
|
||||
try{ require('fs').unlinkSync(env.i+'data') }catch(e){ console.log("!!! WARNING !!!! MUST MANUALLY REMOVE OLD DATA!!!!, e") }
|
||||
var purl = 'https://'+env.config.IP+':'+env.config.port;
|
||||
require('gun/test/https/test')(env.config.port + env.i, env.i+'data', function(){
|
||||
// This server peer is now done with the test!
|
||||
// It has successfully launched.
|
||||
test.done();
|
||||
}, function(file){
|
||||
file = file.toString();
|
||||
if(0 >= file.indexOf('<script src="/gun.js"></script>')){ return }
|
||||
file = file.replace('<script src="/gun.js"></script>',
|
||||
"<script src='"+purl+"/panic.js'></script><script>panic.server('"+purl+"')</script><script src='/gun.js'></script><script>localStorage.clear();sessionStorage.clear();</script>");
|
||||
return file;
|
||||
});
|
||||
}, {i: i += 1, config: config}));
|
||||
});
|
||||
// NOW, this is very important:
|
||||
// Do not proceed to the next test until
|
||||
// every single server (in different machines/processes)
|
||||
// have ALL successfully launched.
|
||||
return Promise.all(tests);
|
||||
});
|
||||
|
||||
it(config.browsers +" browser(s) have joined!", function(){
|
||||
console.log("PLEASE OPEN https://"+ config.IP +":"+ (config.port) +" IN "+ config.browsers +" BROWSER(S)!");
|
||||
return browsers.atLeast(config.browsers);
|
||||
});
|
||||
|
||||
it("Browsers load SEA!", function(){
|
||||
var tests = [], i = 0;
|
||||
browsers.each(function(client, id){
|
||||
tests.push(client.run(function(test){
|
||||
test.async();
|
||||
//console.log("load?");
|
||||
function load(src, cb){
|
||||
var script = document.createElement('script');
|
||||
script.onload = cb; script.src = src;
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
load('sea.js', function(){
|
||||
test.done();
|
||||
});
|
||||
}, {i: i += 1, config: config}));
|
||||
});
|
||||
return Promise.all(tests);
|
||||
});
|
||||
|
||||
it("Browsers initialized gun!", function(){
|
||||
var tests = [], ids = {}, i = 0;
|
||||
// Let us create a list of all the browsers IDs connected.
|
||||
// This will later let each browser check against every other browser.
|
||||
browsers.each(function(client, id){
|
||||
ids[id] = 1;
|
||||
});
|
||||
browsers.each(function(client, id){
|
||||
tests.push(client.run(function(test){
|
||||
localStorage.clear();
|
||||
var env = window.env = test.props;
|
||||
var peers = [], i = env.config.servers;
|
||||
while(i--){
|
||||
// For the total number of servers listed in the configuration
|
||||
// Add their URL into an array.
|
||||
peers.push('https://'+ env.config.IP + ':' + (env.config.port + (i + 1)) + '/gun');
|
||||
}
|
||||
var gun = window.gun = Gun(peers);
|
||||
var user = window.user = gun.user();
|
||||
var go = window.go = {num: 0, total: 0, users: {}, pub: {}};
|
||||
window.ID = env.id;
|
||||
go.check = Gun.obj.map(env.ids, function(v,id,t){
|
||||
// for each browser ID
|
||||
// they will be saving X number of messages each.
|
||||
go.users[id] = true; // set an outstanding flag to check against.
|
||||
var i = env.config.each;
|
||||
while(i--){
|
||||
// So add a deterministic key we can check against.
|
||||
t(id + (i + 1), 1);
|
||||
// And count up the total number of messages we expect for all.
|
||||
go.total += 1;
|
||||
}
|
||||
});
|
||||
|
||||
console.log(peers, go);
|
||||
}, {i: i += 1, id: id, ids: ids, config: config}));
|
||||
});
|
||||
return Promise.all(tests);
|
||||
});
|
||||
|
||||
it("All users created!", function(){
|
||||
var tests = [], ids = {}, i = 0;
|
||||
browsers.each(function(client, id){
|
||||
ids[id] = 1;
|
||||
});
|
||||
browsers.each(function(client, id){
|
||||
tests.push(client.run(function(test){
|
||||
test.async();
|
||||
|
||||
gun.on('secure', function(at){
|
||||
/* enforce some rules about shared app level data */
|
||||
if(!at.put || !at.put.users){ return }
|
||||
var no;
|
||||
Gun.node.is(at.put.users, function(val, key){
|
||||
Gun.SEA.read(val, false, function(val){
|
||||
if('alias/'+key === Gun.val.rel.is(val)){ return }
|
||||
no = true;
|
||||
})
|
||||
if(no){ return no }
|
||||
});
|
||||
if(no){ return }
|
||||
this.to.next(at);
|
||||
});
|
||||
|
||||
var unsafepassword = 'asdf'+ID;
|
||||
console.log("sign in and up:", ID);
|
||||
window.user.create(ID, unsafepassword, function(ack){
|
||||
if(ack.err || !ack.pub){ return }
|
||||
window.pub = ack.pub;
|
||||
gun.get('users').get(ID).put(gun.get('alias/'+ID));
|
||||
console.log("signed up", ack.pub);
|
||||
console.debug.j = 1;
|
||||
window.user.auth(ID, unsafepassword, function(ack){
|
||||
console.debug.j = 0;
|
||||
console.log("signed in", ack);
|
||||
if(ack.err || !ack.pub){ return }
|
||||
test.done();
|
||||
});
|
||||
});
|
||||
|
||||
}, {i: i += 1, id: id, ids: ids, config: config}));
|
||||
});
|
||||
return Promise.all(tests);
|
||||
});
|
||||
|
||||
it("Start reading and sending messages!", function(){
|
||||
var tests = [], ids = {}, i = 0;
|
||||
browsers.each(function(client, id){
|
||||
ids[id] = 1;
|
||||
});
|
||||
browsers.each(function(client, id){
|
||||
tests.push(client.run(function(test){
|
||||
test.async();
|
||||
|
||||
gun.get('users').map().map()
|
||||
.get('who').get('said').map().on(function(msg){
|
||||
check(msg);
|
||||
});
|
||||
|
||||
var said = user.get('who').get('said');
|
||||
|
||||
function run(i){
|
||||
|
||||
var what = i +"|||"+ "Hello world!" +"|||"+ pub +"|||"+ ID;
|
||||
said.set({
|
||||
what: what
|
||||
});/*, function(ack){
|
||||
if(ack.err){ return }
|
||||
test.done();
|
||||
});*/
|
||||
|
||||
}
|
||||
/* TODO: sometimes sign in hangs */
|
||||
console.log("<<<<< START >>>>>");
|
||||
var i = 0, to = setInterval(function frame(a, b){
|
||||
if(!b && 2 <= (b = env.config.burst)){
|
||||
while(--b){
|
||||
frame(i, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(env.config.each <= i){
|
||||
clearTimeout(to);
|
||||
return;
|
||||
}
|
||||
run(i += 1);
|
||||
}, env.config.wait || 1);
|
||||
|
||||
|
||||
var col = $("<div>").css({width: 250, position: 'relative', float: 'left', border: 'solid 1px black'}), cols = {};
|
||||
var report = $("<div>").css({position: 'fixed', top: 0, right: 0, background: 'white', padding: 10}).text(" / "+ go.total +" Verified").prependTo('body');
|
||||
var reportc = $('<span>').text(0).prependTo(report);
|
||||
var last = $("<div>").text("Processing: ").css({border: "solid 1px black"}).appendTo("body");
|
||||
last = $("<span>").text(" ").appendTo(last);
|
||||
|
||||
function check(data){
|
||||
data = data.what.split("|||");
|
||||
var msg = {num: data[0], what: data[0] +' '+ data[1], who: data[2], id: data[3]};
|
||||
var who;
|
||||
if(!go.pub[msg.who]){
|
||||
go.pub[msg.who] = msg.id;
|
||||
go.users[msg.id] = false;
|
||||
//who = cols[msg.id] = col.clone(true).appendTo('body');
|
||||
//who.prepend("<input value='"+ msg.who +"'>");
|
||||
//who.prepend("<input value='"+ msg.id +"'>");
|
||||
}
|
||||
if(!go.check[msg.id + msg.num]){
|
||||
return;
|
||||
}
|
||||
go.check[msg.id + msg.num] = false;
|
||||
clearTimeout(end.to); end.to = setTimeout(end, 9);
|
||||
reportc.text(++go.num);
|
||||
last.text(msg.what);
|
||||
//who = cols[msg.id];
|
||||
//$("<div>").css({border: 'solid 1px blue'}).text(msg.what).appendTo(who);
|
||||
}
|
||||
|
||||
function end(){
|
||||
var wait = Gun.obj.map(go.users, function(v){ if(v){ return true }});
|
||||
if(wait){ return }
|
||||
var more = Gun.obj.map(go.check, function(v){ if(v){ return true }});
|
||||
if(more){ return }
|
||||
test.done();
|
||||
}
|
||||
|
||||
}, {i: i += 1, id: id, ids: ids, config: config}));
|
||||
});
|
||||
return Promise.all(tests);
|
||||
});
|
||||
|
||||
/* MODEL TEST
|
||||
it("Browsers initialized gun!", function(){
|
||||
var tests = [], ids = {}, i = 0;
|
||||
browsers.each(function(client, id){
|
||||
ids[id] = 1;
|
||||
});
|
||||
browsers.each(function(client, id){
|
||||
tests.push(client.run(function(test){
|
||||
// code here
|
||||
}, {i: i += 1, id: id, ids: ids, config: config}));
|
||||
});
|
||||
return Promise.all(tests);
|
||||
});
|
||||
*/
|
||||
|
||||
it("All finished!", function(done){
|
||||
console.log("Done! Cleaning things up...");
|
||||
setTimeout(function(){
|
||||
done();
|
||||
}, 2000);
|
||||
});
|
||||
|
||||
after("Everything shut down.", function(){
|
||||
browsers.run(function(){
|
||||
//location.reload();
|
||||
//setTimeout(function(){
|
||||
//}, 15 * 1000);
|
||||
});
|
||||
return servers.run(function(){
|
||||
process.exit();
|
||||
});
|
||||
});
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user