This commit is contained in:
Mark Nadal 2015-01-09 03:52:11 -07:00
parent 21875b3d81
commit 02c3425829
5 changed files with 1217 additions and 282 deletions

35
gun.js
View File

@ -17,8 +17,8 @@
Gun.is.value = function(v){ // null, binary, number (!Infinity), text, or a rel.
if(v === null){ return true } // deletes
if(v === Infinity){ return false } // we want this to be, but JSON does not support it, sad face.
if(Gun.bi.is(v)
|| Gun.num.is(v)
if(Gun.bi.is(v)
|| Gun.num.is(v)
|| Gun.text.is(v)){
return true; // simple values
}
@ -105,7 +105,7 @@
function HAM(machineState, incomingState, currentState, incomingValue, currentValue){ // TODO: Lester's comments on roll backs could be vulnerable to divergence, investigate!
if(machineState < incomingState){
// the incoming value is outside the boundary of the machine's state, it must be reprocessed in another state.
return {amnesiaQuarantine: true};
return {amnesiaQuarantine: true};
}
if(incomingState < currentState){
// the incoming value is within the boundary of the machine's state, but not within the range.
@ -239,6 +239,7 @@
var gun = this.chain();
gun.shot('done');
gun.shot.done(function(){
opt = opt || {};
cb = cb || function(){};
cb.soul = (key||{})[Gun._.soul];
if(cb.soul){
@ -247,7 +248,7 @@
gun._.key = key;
cb.node = gun.__.keys[key];
}
if(cb.node){ // set this to the current node, too!
if(!opt.force && cb.node){ // set this to the current node, too!
Gun.log.call(gun, "load via gun"); // remember to do all the same stack stuff here also!
gun._.node = cb.node;
if(Gun.fns.is(cb)){ cb.call(gun, null, Gun.obj.copy(gun._.node)) } // frozen copy
@ -284,11 +285,11 @@
cb = cb || function(){};
if(Gun.obj.is(key)){ // if key is an object then we get the soul directly from it because the node might not exist in cache.
Gun.obj.map(key, function(soul, field){ return key = field, cb.soul = soul });
cb.node = gun.__.keys[key] = gun.__.graph[cb.soul]; // if it is cached, then it is important to reference it.
} else { // else the node does exist in cache and we will get the soul from it instead, plus link the key.
cb.node = gun.__.keys[key] = gun._.node;
}
if(Gun.fns.is(gun.__.opt.hooks.key)){
console.log("UGLY UGLY UGLY UGLY", key, cb.soul, cb.node);
gun.__.opt.hooks.key(key, cb.soul || (cb.node||{_:{}})._[Gun._.soul], function(err, data){
//Gun.log.call(gun, "key made", key);
if(err){ return cb(err) }
@ -300,16 +301,16 @@
});
if(!gun.back){ gun.shot('then').fire() }
return gun;
}
}
/*
how many different ways can we get something?
Find via a singular path
Find via a singular path
.path('blah').get(blah);
Find via multiple paths with the callback getting called many times
.path('foo', 'bar').get(foorOrBar);
Find via multiple paths with the callback getting called once with matching arguments
.path('foo', 'bar').get(foo, bar)
Find via multiple paths with the result aggregated into an object of pre-given fields
Find via multiple paths with the result aggregated into an object of pre-given fields
.path('foo', 'bar').get({foo: foo, bar: bar}) || .path({a: 'foo', b: 'bar'}).get({a: foo, b: bar})
Find via multiple paths where the fields and values must match
.path({foo: val, bar: val}).get({})
@ -515,7 +516,7 @@
Util.obj.del = function(o, k){
if(!o){ return }
o[k] = null;
delete o[k];
delete o[k];
return true;
}
Util.obj.ify = function(o){
@ -609,7 +610,7 @@
return me;
}
return Chain;
}());
}());
return Flow;
}());Gun.shot.chain.chain.fire=Gun.shot.chain.chain.pipe;
;Gun.on=(function(){
@ -772,7 +773,7 @@
if(field !== Gun._.soul){
context.err = err;
return true;
}
}
if(unique[soul]){ return }
unique[soul] = 1;
map(val);
@ -873,7 +874,7 @@
}
Gun.obj.map(gun.__.opt.peers, function(peer, url){
request(url, meta, function(err, reply){
console.log("gun key done", soul, err, reply);
//console.log("gun key done", soul, err, reply);
if(err || !reply){
Gun.log.call(gun, err = err || "Error: Key failed to be made on " + url);
// tab.key(key, soul, cb); // naive implementation of retry TODO: BUG: need backoff and anti-infinite-loop!
@ -888,11 +889,11 @@
cb = cb || function(){};
// TODO: batch and throttle later.
//tab.store.set(cb.id = 'send/' + Gun.text.random(), nodes);
console.log("gun set start");
//console.log("gun set start");
Gun.obj.map(gun.__.opt.peers, function(peer, url){
request(url, nodes, function respond(err, reply, id){
console.log("gun set done", err, reply, id);
//console.log("gun set done", err, reply, id);
return;
var body = reply && reply.body;
respond.id = respond.id || cb.id;
@ -1018,7 +1019,7 @@
js.parentNode.removeChild(js);
window[cb.id] = null; // TODO! BUG: This needs to handle chunking!
try{delete window[cb.id];
}catch(e){}
}catch(e){}
}
js.async = true;
document.getElementsByTagName('head')[0].appendChild(js);
@ -1082,4 +1083,4 @@
}
return r;
}());
}({}));
}({}));

View File

@ -107,6 +107,7 @@
key = {};
key[Gun._.soul] = req.url.query[Gun._.soul];
}
console.log("transport.loading key ->", key, gun.__.graph, gun.__.keys);
gun.load(key, function(err, node){
//tran.sub.scribe(req.tab, node._[Gun._.soul]);
cb({headers: reply.headers, body: (err? (err.err? err : {err: err || "Unknown error."}) : node || null)});
@ -119,30 +120,37 @@
if(!req.body){ return cb({headers: reply.headers, body: {err: "No body"}}) }
if(tran.post.key(req, cb)){ return }
// saving
Gun.obj.map(req.body, function(node, soul){
Gun.obj.map(req.body, function(node, soul){ // iterate over every node
if(soul != Gun.is.soul.on(node)){ return this.end("No soul!") }
gun.load(node._, this.add(soul));
gun.load(node._, this.add(soul)); // and begin loading it in case it is not cached.
}, Gun.fns.sum(function(err){
if(err){ return cb({headers: reply.headers, body: {err: err}}) }
gun.union(req.body, function(err, context){
if(err || context.err || !context.nodes){ return cb({headers: reply.headers, body: {err: err || context.err || "Union failed." }}) }
if(err){ return reply.err = err }
reply.loaded = true;
}));
// could there be a timing error somewhere in here?
setImmediate(function(){ // do not do it right away because gun.load above is async, this should be cleaner.
var context = gun.union(req.body, function check(err, ctx){ // check if the body is valid, and get it into cache immediately.
context = ctx || context;
if(err || reply.err || context.err || !context.nodes){ return cb({headers: reply.headers, body: {err: err || reply.err || context.err || "Union failed." }}) }
if(!Gun.fns.is(gun.__.opt.hooks.set)){ return cb({headers: reply.headers, body: {err: "Persistence not supported." }}) }
if(!reply.loaded){ return setTimeout(check, 2) } // only persist if all nodes have been loaded into cache.
gun.__.opt.hooks.set(context.nodes, function(err, data){ // since we've already manually done the union, we can now directly call the persistence layer.
if(err){ return cb({headers: reply.headers, body: {err: err || "Persistence failed." }}) }
cb({headers: reply.headers, body: {ok: "Persisted."}});
});
});
}));
});
gun.server.on('network').emit(req);
}
tran.post.key = function(req, cb){ // key hook!
if(!req || !req.url || !req.url.key || !Gun.obj.has(req.body, Gun._.soul)){ return }
var index = {};
index[req.url.key] = req.body[Gun._.soul];
console.log("NASTY INDEX", index);
gun.key(index, function(err, reply){
if(err){ return cb({headers: {'Content-Type': tran.json}, body: {err: err}}) }
cb({headers: {'Content-Type': tran.json}, body: reply});
var load = {}, index = {}, soul;
soul = load[Gun._.soul] = index[req.url.key] = req.body[Gun._.soul];
gun.load(load, function(e,r){
gun.key(index, function(err, reply){
if(err){ return cb({headers: {'Content-Type': tran.json}, body: {err: err}}) }
cb({headers: {'Content-Type': tran.json}, body: reply});
});
});
return true;
}

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 69 KiB

47
web/img/stand.svg Normal file
View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="104.80719"
height="52.775127"
id="svg7584">
<defs
id="defs7586" />
<metadata
id="metadata7589">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(-304.73926,-448.83176)"
id="layer1">
<g
transform="translate(176.16559,-378.81147)"
id="g7567">
<path
d="m 151.79064,827.64323 58.37326,0 6.88337,46.98126 -72.14001,0 z"
id="rect3979"
style="fill:#868686;fill-opacity:1" />
<rect
width="104.80719"
height="7.1926503"
x="128.57367"
y="873.22571"
id="rect3982"
style="fill:#868686;fill-opacity:1" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -27,7 +27,7 @@
font-family: 'Oxygen', Candara, Calibri, Segoe, "Segoe UI", Optima, Arial, sans-serif;
}
pre {
background-color: black;
background-color: black;
border: 1px dashed white;
color: white;
line-height: 1.5em;
@ -64,7 +64,26 @@
width: 30%;
padding: 2em;
}
.svg {
background: white url('./img/devices.svg') no-repeat 50% 50%;
height: 40em;
}
</style>
<div class="html" style="width: 100%; height: 40em; margin:0;padding:0;">
<div class="desktop" style="height: 10em; width: 17em; position: absolute; top: 40%; left: 20%;">
<div class="monitor" style="height: 100%; width: 100%; background: #222; padding: .75em; margin-left: -.75em; border-radius: 1em;">
<div class="monitor" style="height: 100%; width: 100%; background: #999;">
</div>
</div>
<center><img src="./img/stand.svg" style="margin-top: 1px;"></img></center>
</div>
</div>
<div class="svg">
AWESOME SAUCE COLOR SYNCING
</div>
<div class="center">
<h1 class="lean">Easiest . Database . Ever</h1>
<h2 class="lean">Scale without pain, because it is decentralized.</h2>
@ -90,7 +109,7 @@ gun.set({hello: 'world'}).key('<span class="random">my/first/data</span>');</pre
</div>
-->
</div>
<div id="step2" class="step">
Let's test to see if the data got saved.
<ol>
@ -101,7 +120,7 @@ gun.set({hello: 'world'}).key('<span class="random">my/first/data</span>');</pre
<textarea style="width: 100%; height: 100px;">// Your data will log here!</textarea>
The next level will be unlocked when you complete the realtime sync between tabs.
</div>
<div id="step3" class="step">
<pre>var gun = Gun('http://localhost:8888/gun');
gun.load('<span class="random">my/first/data</span>', function(err, data){
@ -112,7 +131,7 @@ gun.load('<span class="random">my/first/data</span>', function(err, data){
</button></a> Does the key match from the previous tab?
<textarea style="width: 100%; height: 100px;">// Your data will log here!</textarea>
</div>
<div id="step4" class="step">
Now let's listen to realtime updates, and change the value on the 'hello' field.
<pre>gun.load('<span class="random">my/first/data</span>')
@ -124,10 +143,10 @@ gun.load('<span class="random">my/first/data</span>', function(err, data){
</button></a>
<textarea style="width: 100%; height: 100px;">// Your data will log here!</textarea>
</div>
</div>
<div class="grid">
<div class="learn unit center">
<h1 class="lean">Did you know?</h1>
@ -176,7 +195,7 @@ gun.load('<span class="random">my/first/data</span>', function(err, data){
demo.step1 = function(){
demo.step0();
gun.set({hello: 'world'}).key(demo.random);
// and also do this, so we can unlock!
gun.load(demo.random)
.on(function(updates){
@ -207,4 +226,4 @@ gun.load('<span class="random">my/first/data</span>', function(err, data){
</script>
<a href="https://github.com/amark/gun"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/38ef81f8aca64bb9a64448d0d70f1308ef5341ab/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6461726b626c75655f3132313632312e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png"></a>
</body>
</html>
</html>