server updated

This commit is contained in:
Mark Nadal 2015-12-26 21:14:14 -08:00
parent ab138b5350
commit 8c0dae0176
6 changed files with 110 additions and 206 deletions

View File

@ -24,8 +24,8 @@
<button>send</button> <button>send</button>
</form> </form>
<script> <script>
var chat = Gun(location.origin + '/gun').get('example/chat/data').not(function(){ var chat = Gun(location.origin + '/gun').get('example/chat/data').not(function(key){
return this.put({1: {who: 'Welcome', what: "to the chat app!", when: 1}}).key('example/chat/data'); return this.put({1: {who: 'Welcome', what: "to the chat app!", when: 1}}).key(key);
}); });
chat.map().val(function(msg, field){ chat.map().val(function(msg, field){
var $ul = $('ul'), $last = $.sort(field, $ul.lastChild), $msg; var $ul = $('ul'), $last = $.sort(field, $ul.lastChild), $msg;

View File

@ -11,7 +11,7 @@ var gun = Gun({
}); });
var server = require('http').createServer(function(req, res){ var server = require('http').createServer(function(req, res){
if(gun.server(req, res)){ if(gun.wsp.server(req, res)){
return; // filters gun requests! return; // filters gun requests!
} }
require('fs').createReadStream(require('path').join(__dirname, req.url)).on('error',function(){ // static files! require('fs').createReadStream(require('path').join(__dirname, req.url)).on('error',function(){ // static files!
@ -19,7 +19,7 @@ var server = require('http').createServer(function(req, res){
res.end(require('fs').readFileSync(require('path').join(__dirname, 'index.html'))); // or default to index res.end(require('fs').readFileSync(require('path').join(__dirname, 'index.html'))); // or default to index
}).pipe(res); // stream }).pipe(res); // stream
}); });
gun.attach(server); gun.wsp(server);
server.listen(port); server.listen(port);
console.log('Server started on port ' + port + ' with /gun'); console.log('Server started on port ' + port + ' with /gun');

90
gun.js
View File

@ -562,6 +562,8 @@
} }
} }
Gun.is.node.HAM = function(n, f){ return (f && n && n._ && n._[Gun._.HAM] && n._[Gun._.HAM][f]) || false }
Gun.HAM = function(machineState, incomingState, currentState, incomingValue, currentValue){ // TODO: Lester's comments on roll backs could be vulnerable to divergence, investigate! Gun.HAM = function(machineState, incomingState, currentState, incomingValue, currentValue){ // TODO: Lester's comments on roll backs could be vulnerable to divergence, investigate!
if(machineState < incomingState){ if(machineState < incomingState){
// the incoming value is outside the boundary of the machine's state, it must be reprocessed in another state. // the incoming value is outside the boundary of the machine's state, it must be reprocessed in another state.
@ -930,6 +932,35 @@
if(at.obj === has.obj){ return has } if(at.obj === has.obj){ return has }
}) || (ctx.seen.push(at) && false); }) || (ctx.seen.push(at) && false);
} }
ify.wire = function(n, cb, opt){ return Gun.text.is(n)? ify.wire.from(n, cb, opt) : ify.wire.to(n, cb, opt) }
ify.wire.to = function(n, cb, opt){ var t, b;
if(!n || !(t = Gun.is.node.soul(n))){ return null }
cb = cb || function(){};
t = (b = "#'" + JSON.stringify(t) + "'");
Gun.obj.map(n, function(v,f){
if(Gun._.meta === f){ return }
var w = '', s = Gun.is.node.HAM(n,f);
if(!s){ return }
w += ".'" + JSON.stringify(f) + "'";
w += "='" + JSON.stringify(v) + "'";
w += ">'" + JSON.stringify(s) + "'";
t += w;
w = b + w;
cb(null, w);
});
return t;
}
ify.wire.from = function(n, cb, opt){
if(!n){ return null }
var a = [], s = -1, e = 0, end = 1;
while((e = n.indexOf("'", s + 1)) >= 0){
if(s === e || '\\' === n.charAt(e-1)){}else{
a.push(n.slice(s + 1,e));
s = e;
}
}
return a;
}
Gun.ify = ify; Gun.ify = ify;
}(Gun)); }(Gun));
@ -951,7 +982,7 @@
;(function(Tab){ ;(function(Tab){
return;
if(!this.Gun){ return } if(!this.Gun){ return }
if(!window.JSON){ throw new Error("Include JSON first: ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js") } // for old IE use if(!window.JSON){ throw new Error("Include JSON first: ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js") } // for old IE use
@ -1016,12 +1047,6 @@
}); });
} tab.peers(cb); } tab.peers(cb);
} }
tab.com(function(msg, reply){
});
tab.com.to(msg, function(reply){
}, opt);
tab.error = function(cb, error, fn){ tab.error = function(cb, error, fn){
return function(err, reply){ return function(err, reply){
reply.body = reply.body || reply.chunk || reply.end || reply.write; reply.body = reply.body || reply.chunk || reply.end || reply.write;
@ -1055,31 +1080,15 @@
var reply = {headers: {'Content-Type': tab.server.json}}; var reply = {headers: {'Content-Type': tab.server.json}};
if(!req.body){ return cb({headers: reply.headers, body: {err: "No body"}}) } if(!req.body){ return cb({headers: reply.headers, body: {err: "No body"}}) }
// TODO: Re-emit message to other peers if we have any non-overlaping ones. // TODO: Re-emit message to other peers if we have any non-overlaping ones.
if(tab.server.put.key(req, cb)){ return } if(req.err = Gun.union(gun, req.body, function(err, ctx){
if(Gun.is.node(req.body) || Gun.is.graph(req.body, function(node, soul){ if(err){ return cb({headers: reply.headers, body: {err: err || "Union failed."}}) }
gun.__.flag.end[soul] = true; // TODO: Put this in CORE not in TAB driver? var ctx = ctx || {}; ctx.graph = {};
})){ Gun.is.graph(req.body, function(node, soul){ ctx.graph[soul] = gun.__.graph[soul] });
//console.log("tran.put", req.body); gun.__.opt.wire.put(ctx.graph, function(err, ok){
if(req.err = Gun.union(gun, req.body, function(err, ctx){ if(err){ return cb({headers: reply.headers, body: {err: err || "Failed."}}) }
if(err){ return cb({headers: reply.headers, body: {err: err || "Union failed."}}) } cb({headers: reply.headers, body: {ok: ok || "Persisted."}});
var ctx = ctx || {}; ctx.graph = {}; }, {local: true});
Gun.is.graph(req.body, function(node, soul){ ctx.graph[soul] = gun.__.graph[soul] }); }).err){ cb({headers: reply.headers, body: {err: req.err || "Union failed."}}) }
gun.__.opt.hooks.put(ctx.graph, function(err, ok){
if(err){ return cb({headers: reply.headers, body: {err: err || "Failed."}}) }
cb({headers: reply.headers, body: {ok: ok || "Persisted."}});
}, {local: true});
}).err){ cb({headers: reply.headers, body: {err: req.err || "Union failed."}}) }
}
}
tab.server.put.key = function(req, cb){
if(!req || !req.url || !req.url.key || !Gun.obj.has(req.body, Gun._.soul)){ return }
var index = req.url.key, soul = Gun.is.soul(req.body);
//console.log("tran.key", index, req.body);
gun.key(index, function(err, reply){
if(err){ return cb({headers: {'Content-Type': tab.server.json}, body: {err: err}}) }
cb({headers: {'Content-Type': tab.server.json}, body: reply}); // TODO: Fix so we know what the reply is.
}, soul);
return true;
} }
Gun.obj.map(gun.__.opt.peers, function(){ // only create server if peers and do it once by returning immediately. Gun.obj.map(gun.__.opt.peers, function(){ // only create server if peers and do it once by returning immediately.
return (tab.server.able = tab.server.able || tab.request.createServer(tab.server) || true); return (tab.server.able = tab.server.able || tab.request.createServer(tab.server) || true);
@ -1089,13 +1098,6 @@
gun.__.opt.wire.key = gun.__.opt.wire.key || tab.key; gun.__.opt.wire.key = gun.__.opt.wire.key || tab.key;
}); });
;(function(exports){
exports.com = function(){
};
com.to = function(){};
}(Tab));
var request = (function(){ var request = (function(){
function r(base, body, cb, opt){ function r(base, body, cb, opt){
opt = opt || (base.length? {base: base} : base); opt = opt || (base.length? {base: base} : base);
@ -1110,6 +1112,7 @@
while(i--){ (r.createServer.s[i] || function(){})(req, cb) } while(i--){ (r.createServer.s[i] || function(){})(req, cb) }
} }
r.createServer.s = []; r.createServer.s = [];
r.back = 2; r.backoff = 2;
r.transport = function(opt, cb){ r.transport = function(opt, cb){
//Gun.log("TRANSPORT:", opt); //Gun.log("TRANSPORT:", opt);
if(r.ws(opt, cb)){ return } if(r.ws(opt, cb)){ return }
@ -1134,7 +1137,7 @@
} }
if(ws === false){ return } if(ws === false){ return }
ws = r.ws.peers[opt.base] = new WS(opt.base.replace('http','ws')); ws = r.ws.peers[opt.base] = new WS(opt.base.replace('http','ws'));
ws.onopen = function(o){ r.ws(opt, cb) }; ws.onopen = function(o){ r.back = 2; r.ws(opt, cb) };
ws.onclose = window.onbeforeunload = function(c){ ws.onclose = window.onbeforeunload = function(c){
if(!c){ return } if(!c){ return }
if(ws && ws.close instanceof Function){ ws.close() } if(ws && ws.close instanceof Function){ ws.close() }
@ -1145,9 +1148,8 @@
} }
ws = r.ws.peers[opt.base] = null; // this will make the next request try to reconnect ws = r.ws.peers[opt.base] = null; // this will make the next request try to reconnect
setTimeout(function(){ setTimeout(function(){
console.log("!!!!! WEBSOCKET DICONNECTED !!!!!! ATTEMPTING INFINITE RETRY WITH NO BACKOFF !!!!!!!");
r.ws(opt, function(){}); // opt here is a race condition, is it not? Does this matter? r.ws(opt, function(){}); // opt here is a race condition, is it not? Does this matter?
}, 50) // make this an exponential backoff. }, r.back *= r.backoff);
}; };
ws.onmessage = function(m){ ws.onmessage = function(m){
if(!m || !m.data){ return } if(!m || !m.data){ return }
@ -1157,10 +1159,10 @@
if(!res){ return } if(!res){ return }
res.headers = res.headers || {}; res.headers = res.headers || {};
if(res.headers['ws-rid']){ return (r.ws.cbs[res.headers['ws-rid']]||function(){})(null, res) } if(res.headers['ws-rid']){ return (r.ws.cbs[res.headers['ws-rid']]||function(){})(null, res) }
Gun.log("We have a pushed message!", res); //Gun.log("We have a pushed message!", res);
if(res.body){ r.createServer.ing(res, function(){}) } // emit extra events. if(res.body){ r.createServer.ing(res, function(){}) } // emit extra events.
}; };
ws.onerror = function(e){ console.log("!!!! WEBSOCKET ERROR !!!!", e); Gun.log(e); }; ws.onerror = function(e){ Gun.log(e); };
return true; return true;
} }
r.ws.peers = {}; r.ws.peers = {};

View File

@ -38,19 +38,16 @@ Gun.on('opt').event(function(gun, opts) {
gun.opt({wire: { gun.opt({wire: {
get: function get(key, cb, o){ get: function get(key, cb, o){
var graph, soul = key; var node, soul = key;
(graph = {})[soul] = all.nodes[soul]; node = all.nodes[soul];
console.log("FILE NODE", graph); if(!node){ return cb(null, null) }
if(!graph[soul]){ return cb(null, null) } cb(null, node);
cb(null, graph); node = Gun.is.node.ify({}, soul);
(graph = {})[soul] = Gun.is.node.ify({}, soul); cb(null, node); // end.
console.log("END NODE", graph);
cb(null, graph); // end.
console.log("DONE", {});
cb(null, {}); // done. cb(null, {}); // done.
}, },
put: function(graph, cb, o){ put: function(graph, cb, o){
for (key in gun.__.graph) all.nodes[key]=gun.__.graph[key]; for (key in gun.__.graph) all.nodes[key]=gun.__.graph[key]||graph[key];
writeFile(cb); writeFile(cb);
}/*, }/*,
all: function(list, opt, cb) { all: function(list, opt, cb) {

View File

@ -6,26 +6,26 @@
, url = require('url'); , url = require('url');
Gun.on('opt').event(function(gun, opt){ Gun.on('opt').event(function(gun, opt){
gun.__.opt.ws = opt.ws = gun.__.opt.ws || opt.ws || {}; gun.__.opt.ws = opt.ws = gun.__.opt.ws || opt.ws || {};
function start(server, port){
gun.__.opt.ws.server = gun.__.opt.ws.server || opt.ws.server || server;
if(server.use){ server.use(gun.__.opt.ws.server) }
require('./ws')(gun.wsp.ws = gun.wsp.ws || new ws(gun.__.opt.ws), function(req, res){
var ws = this;
req.headers['gun-sid'] = ws.sid = ws.sid? ws.sid : req.headers['gun-sid'];
ws.sub = ws.sub || gun.wsp.on('network').event(function(msg){
if(!ws || !ws.send || !ws._socket || !ws._socket.writable){ return this.off() }
if(!msg || (msg.headers && msg.headers['gun-sid'] === ws.sid)){ return }
if(msg && msg.headers){ delete msg.headers['ws-rid'] }
// TODO: BUG? ^ What if other peers want to ack? Do they use the ws-rid or a gun declared id?
try{ws.send(Gun.text.ify(msg));
}catch(e){} // juuuust in case.
});
gun.wsp.wire(req, res);
});
gun.__.opt.ws.port = gun.__.opt.ws.port || opt.ws.port || port || 80;
}
var wsp = gun.wsp = gun.wsp || function(server){ var wsp = gun.wsp = gun.wsp || function(server){
if(!server){ return gun } if(!server){ return gun }
function start(port, server){
gun.__.opt.ws.server = gun.__.opt.ws.server || opt.ws.server || server;
gun.__.opt.ws.port = gun.__.opt.ws.port || opt.ws.port || port || 80;
if(server.use){ server.use(gun.__.opt.ws.server) }
require('./ws')(gun.wsp.ws = gun.wsp.ws || new ws(gun.__.opt.ws), function(req, res){
var ws = this;
req.headers['gun-sid'] = ws.sid = ws.sid? ws.sid : req.headers['gun-sid'];
ws.sub = ws.sub || gun.wsp.on('network').event(function(msg){
if(!ws || !ws.send || !ws._socket || !ws._socket.writable){ return this.off() }
if(!msg || (msg.headers && msg.headers['gun-sid'] === ws.sid)){ return }
if(msg && msg.headers){ delete msg.headers['ws-rid'] }
// TODO: BUG? ^ What if other peers want to ack? Do they use the ws-rid or a gun declared id?
try{ws.send(Gun.text.ify(msg));
}catch(e){} // juuuust in case.
});
gun.wsp.EXPLODE(req, res);
});
}
if(Gun.fns.is(server.address)){ if(Gun.fns.is(server.address)){
if(server.address()){ if(server.address()){
start(server, server.address().port); start(server, server.address().port);
@ -82,112 +82,19 @@
return stream.reply = cb; return stream.reply = cb;
} }
} }
gun.wsp.EXPLODE(req, cb); gun.wsp.wire(req, cb);
}), true; }), true;
} }
if((gun.__.opt.maxSockets = opt.maxSockets || gun.__.opt.maxSockets) !== false){ if((gun.__.opt.maxSockets = opt.maxSockets || gun.__.opt.maxSockets) !== false){
require('https').globalAgent.maxSockets = require('http').globalAgent.maxSockets = gun.__.opt.maxSockets || Infinity; require('https').globalAgent.maxSockets = require('http').globalAgent.maxSockets = gun.__.opt.maxSockets || Infinity;
} }
if(opt.server){ gun.wsp.wire = gun.wsp.wire || (function(){
wsp(opt.server);
}
return;
var wsp = gun.wsp = gun.wsp || {};
gun.attach = gun.attach || function(app){
if(app.use){
app.use(gun.server);
}
var listen = app.listen;
app.listen = function(port){
var server = listen.apply(app, arguments);
gun.__.opt.ws.server = gun.__.opt.ws.server || opt.ws.server || server;
gun.__.opt.ws.path = gun.__.opt.ws.path || opt.ws.path || '/gun';
require('./ws')(gun.server.websocket = gun.server.websocket || new ws(gun.__.opt.ws), function(req, res){
var ws = this;
req.headers['gun-sid'] = ws.sid = ws.sid? ws.sid : req.headers['gun-sid'];
ws.sub = ws.sub || gun.server.on('network').event(function(msg){
if(!ws || !ws.send || !ws._socket || !ws._socket.writable){ return this.off() }
if(!msg || (msg.headers && msg.headers['gun-sid'] === ws.sid)){ return }
if(msg && msg.headers){ delete msg.headers['ws-rid'] }
// TODO: BUG? ^ What if other peers want to ack? Do they use the ws-rid or a gun declared id?
try{ws.send(Gun.text.ify(msg));
}catch(e){} // juuuust in case.
});
gun.__.opt.wire.transport(req, res);
});
gun.__.opt.ws.port = port || opt.ws.port || gun.__.opt.ws.port || 80;
return server;
}
return gun;
}
gun.server = gun.server || function(req, res, next){ // http
//Gun.log("\n\n GUN SERVER!", req);
next = next || function(){};
if(!req || !res){ return next(), false }
if(!req.url){ return next(), false }
if(!req.method){ return next(), false }
var msg = {};
msg.url = url.parse(req.url, true);
if(!gun.server.regex.test(msg.url.pathname)){ return next(), false }
if(msg.url.pathname.replace(gun.server.regex,'').slice(0,3).toLowerCase() === '.js'){
res.writeHead(200, {'Content-Type': 'text/javascript'});
res.end(gun.server.js = gun.server.js || require('fs').readFileSync(__dirname + '/../gun.js')); // gun server is caching the gun library for the client
return true;
}
return http(req, res, function(req, res){
if(!req){ return next() }
var tab, cb = res = require('./jsonp')(req, res);
if(req.headers && (tab = req.headers['gun-sid'])){
tab = (gun.server.peers = gun.server.peers || {})[tab] = gun.server.peers[tab] || {sid: tab};
tab.sub = tab.sub || gun.server.on('network').event(function(req){
if(!tab){ return this.off() } // self cleans up after itself!
if(!req || (req.headers && req.headers['gun-sid'] === tab.sid)){ return }
(tab.queue = tab.queue || []).push(req);
tab.drain(tab.reply);
});
cb = function(r){ (r.headers||{}).poll = gun.__.opt.poll; res(r) }
tab.drain = tab.drain || function(res){
if(!res || !tab || !tab.queue || !tab.queue.length){ return }
res({headers: {'gun-sid': tab.sid}, body: tab.queue });
tab.off = setTimeout(function(){ tab = null }, gun.__.opt.pull);
tab.reply = tab.queue = null;
return true;
}
clearTimeout(tab.off);
if(req.headers.pull){
if(tab.drain(cb)){ return }
return tab.reply = cb;
}
}
gun.__.opt.wire.transport(req, cb);
}), true;
}
gun.server.on = gun.server.on || Gun.on.create();
gun.__.opt.poll = gun.__.opt.poll || opt.poll || 1;
gun.__.opt.pull = gun.__.opt.pull || opt.pull || gun.__.opt.poll * 1000;
gun.server.regex = gun.__.opt.route = gun.__.opt.route || opt.route || /^\/gun/i;
if((gun.__.opt.maxSockets = opt.maxSockets || gun.__.opt.maxSockets) !== false){
require('https').globalAgent.maxSockets = require('http').globalAgent.maxSockets = gun.__.opt.maxSockets || Infinity; // WARNING: Document this!
}
/* gun.server.xff = function(r){
if(!r){ return '' }
var req = {headers: r.headers || {}, connection: r.connection || {}, socket: r.socket || {}};
return req.headers['x-forwarded-for'] || req.connection.remoteAddress || req.socket.remoteAddress || (req.connection.socket || {}).remoteAddress || '';
} */
gun.server.transport = gun.server.transport || (function(){
// all streams, technically PATCH but implemented as PUT or POST, are forwarded to other trusted peers // all streams, technically PATCH but implemented as PUT or POST, are forwarded to other trusted peers
// except for the ones that are listed in the message as having already been sending to. // except for the ones that are listed in the message as having already been sending to.
// all states, implemented with GET, are replied to the source that asked for it. // all states, implemented with GET, are replied to the source that asked for it.
function tran(req, cb){ function tran(req, cb){
req.method = req.body? 'put' : 'get'; // put or get is based on whether there is a body or not req.method = req.body? 'put' : 'get'; // put or get is based on whether there is a body or not
req.url.key = req.url.pathname.replace(gun.server.regex,'').replace(/^\//i,'') || ''; req.url.key = req.url.pathname.replace(gun.wsp.regex,'').replace(/^\//i,'') || '';
if('get' == req.method){ return tran.get(req, cb) } if('get' == req.method){ return tran.get(req, cb) }
if('put' == req.method || 'post' == req.method){ return tran.put(req, cb) } if('put' == req.method || 'post' == req.method){ return tran.put(req, cb) }
cb({body: {hello: 'world'}}); cb({body: {hello: 'world'}});
@ -196,18 +103,18 @@
var key = req.url.key var key = req.url.key
, reply = {headers: {'Content-Type': tran.json}}; , reply = {headers: {'Content-Type': tran.json}};
//console.log(req); //console.log(req);
/* NTS HACK! SHOULD BE ITS OWN ISOLATED MODULE! */ // NTS HACK! SHOULD BE ITS OWN ISOLATED MODULE! //
if(req && req.url && req.url.pathname && req.url.pathname.indexOf('gun.nts') >= 0){ if(req && req.url && req.url.pathname && req.url.pathname.indexOf('gun.nts') >= 0){
return cb({headers: reply.headers, body: {time: Gun.time.is() }}); return cb({headers: reply.headers, body: {time: Gun.time.is() }});
} }
/* NTS END! SHOULD HAVE BEEN ITS OWN MODULE */ // NTS END! SHOULD HAVE BEEN ITS OWN MODULE //
/* ALL HACK! SHOULD BE ITS OWN MODULE OR CORE? */ // ALL HACK! SHOULD BE ITS OWN MODULE OR CORE? //
if(req && req.url && Gun.obj.has(req.url.query, '*')){ if(req && req.url && Gun.obj.has(req.url.query, '*')){
return gun.all(req.url.key + req.url.search, function(err, list){ return gun.all(req.url.key + req.url.search, function(err, list){
cb({headers: reply.headers, body: (err? (err.err? err : {err: err || "Unknown error."}) : list || null ) }) cb({headers: reply.headers, body: (err? (err.err? err : {err: err || "Unknown error."}) : list || null ) })
}); });
} }
/* END ALL HACK! */ // END ALL HACK! //
if(!key){ if(!key){
if(!Gun.obj.has(req.url.query, Gun._.soul)){ if(!Gun.obj.has(req.url.query, Gun._.soul)){
return cb({headers: reply.headers, body: {err: "No key or soul to get."}}); return cb({headers: reply.headers, body: {err: "No key or soul to get."}});
@ -216,13 +123,13 @@
key[Gun._.soul] = req.url.query[Gun._.soul]; key[Gun._.soul] = req.url.query[Gun._.soul];
} }
console.log("tran.get", key); console.log("tran.get", key);
gun.__.opt.wire.get(key, function(err, graph){ gun.__.opt.wire.get(key, function(err, node){
//tran.sub.scribe(req.tab, graph._[Gun._.soul]); //tran.sub.scribe(req.tab, graph._[Gun._.soul]);
console.log("tran.get", key, "<---", err, graph); console.log("tran.get", key, "<---", err, node);
if(err || !graph){ if(err || !node){
return cb({headers: reply.headers, body: (err? (err.err? err : {err: err || "Unknown error."}) : null)}); return cb({headers: reply.headers, body: (err? (err.err? err : {err: err || "Unknown error."}) : null)});
} }
if(Gun.obj.empty(graph)){ return cb({headers: reply.headers, body: graph}) } // we're out of stuff! if(Gun.obj.empty(node)){ return cb({headers: reply.headers, body: node}) } // we're out of stuff!
/* /*
(function(chunks){// FEATURE! Stream chunks if the nodes are large! (function(chunks){// FEATURE! Stream chunks if the nodes are large!
@ -253,7 +160,7 @@
}); });
}([])); }([]));
*/ */
cb({headers: reply.headers, chunk: graph }); // Use this if you don't want streaming chunks feature. cb({headers: reply.headers, chunk: node }); // Use this if you don't want streaming chunks feature.
}); });
} }
tran.put = function(req, cb){ tran.put = function(req, cb){
@ -261,9 +168,7 @@
// This will give you much more fine-grain control over security, transactions, and what not. // This will give you much more fine-grain control over security, transactions, and what not.
var reply = {headers: {'Content-Type': tran.json}}; var reply = {headers: {'Content-Type': tran.json}};
if(!req.body){ return cb({headers: reply.headers, body: {err: "No body"}}) } if(!req.body){ return cb({headers: reply.headers, body: {err: "No body"}}) }
gun.server.on('network').emit(Gun.obj.copy(req)); gun.wsp.on('network').emit(Gun.obj.copy(req));
//if(tran.put.key(req, cb)){ return }
// some NEW code that should get revised.
console.log("tran.put", req.body); console.log("tran.put", req.body);
if(Gun.is.graph(req.body)){ if(Gun.is.graph(req.body)){
if(req.err = Gun.union(gun, req.body, function(err, ctx){ // TODO: BUG? Probably should give me ctx.graph if(req.err = Gun.union(gun, req.body, function(err, ctx){ // TODO: BUG? Probably should give me ctx.graph
@ -281,16 +186,14 @@
cb({headers: reply.headers, body: {err: "Not a valid graph!"}}); cb({headers: reply.headers, body: {err: "Not a valid graph!"}});
} }
} }
gun.server.on('network').event(function(req){ gun.wsp.on('network').event(function(req){
// TODO: MARK! You should move the networking events to here, not in WSS only. // TODO: MARK! You should move the networking events to here, not in WSS only.
}); });
tran.json = 'application/json'; tran.json = 'application/json';
return tran; return tran;
}()); }());
if(opt.server){
opt.wire = opt.wire || {}; wsp(opt.server);
gun.opt({wire: { }
transport: opt.wire.transport || gun.server.transport
}}, true);
}); });
}({})); }({}));

View File

@ -968,7 +968,8 @@ describe('Gun', function(){
}); });
describe('API', function(){ describe('API', function(){
var gun = Gun(); var gopt = {wire:{put:function(n,cb){cb()},get:function(k,cb){cb()}}};
var gun = Gun(gopt);
it('gun chain separation', function(done){ it('gun chain separation', function(done){
var gun = Gun(); var gun = Gun();
@ -1139,12 +1140,13 @@ describe('Gun', function(){
it('put node key get', function(done){ it('put node key get', function(done){
done.keycb = false; done.keycb = false;
gun.put({hello: "key"}).key('yes/key', function(err, ok){ // DEBUG FROM HERE! gun.put({hello: "key"}).key('yes/key', function(err, ok){
done.keycb = true; done.keycb = true;
expect(err).to.not.be.ok(); expect(err).to.not.be.ok();
}).get('yes/key', function(err, node){ // CHANGELOG: API 0.3 BREAKING CHANGE FROM err, graph }).get('yes/key', function(err, node){ // CHANGELOG: API 0.3 BREAKING CHANGE FROM err, graph
expect(err).to.not.be.ok(); expect(err).to.not.be.ok();
expect(Gun.is.node.soul(node)).to.be('yes/key'); expect(Gun.is.node.soul(node)).to.be('yes/key');
console.log("wait what?", done.keycb);
expect(done.keycb).to.be.ok(); expect(done.keycb).to.be.ok();
expect(node.hello).to.be('key'); expect(node.hello).to.be('key');
if(done.c){ return } if(done.c){ return }
@ -1282,7 +1284,7 @@ describe('Gun', function(){
done(); done();
}, 500); }, 500);
}); });
it('get node put node merge conflict', function(done){ it('get node put node merge conflict', function(done){
gun.get('hello/key', function(err, node){ gun.get('hello/key', function(err, node){
if(done.soul){ return } if(done.soul){ return }
@ -1441,7 +1443,7 @@ describe('Gun', function(){
done(); done.c = 1; done(); done.c = 1;
}); });
}); });
/* // TODO: Future feature! /* // TODO: Future feature!
it('put gun node', function(done){ it('put gun node', function(done){
var mark = gun.put({age: 23, name: "Mark Nadal"}); var mark = gun.put({age: 23, name: "Mark Nadal"});
@ -1957,7 +1959,7 @@ describe('Gun', function(){
}); });
}); });
}); });
it('map', function(done){ it('map', function(done){
var c = 0, set = gun.put({a: {here: 'you'}, b: {go: 'dear'}, c: {sir: '!'} }); var c = 0, set = gun.put({a: {here: 'you'}, b: {go: 'dear'}, c: {sir: '!'} });
set.map(function(obj, field){ set.map(function(obj, field){
@ -2082,7 +2084,7 @@ describe('Gun', function(){
}); });
it('double not', function(done){ // from the thought tutorial it('double not', function(done){ // from the thought tutorial
var gun = Gun().get('thoughts').not(function(key){ var gun = Gun(gopt).get('thoughts').not(function(key){
return this.put({}).key(key); return this.put({}).key(key);
}); });
@ -2095,7 +2097,7 @@ describe('Gun', function(){
}) })
}, 10); }, 10);
}); });
it('node path node path node path', function(done){ it('node path node path node path', function(done){
var gun = Gun(); var gun = Gun();
var data = gun.get('data'); var data = gun.get('data');
@ -2368,7 +2370,7 @@ describe('Gun', function(){
done(); done();
}); });
}); });
it('get pseudo merge across peers', function(done){ it('get pseudo merge across peers', function(done){
Gun.on('opt').event(function(gun, o){ Gun.on('opt').event(function(gun, o){
if(connect){ return } if(connect){ return }
@ -2564,7 +2566,7 @@ describe('Gun', function(){
}); });
it('gun get put, sub path put, original val', function(done){ // bug from Jesse working on Trace it('gun get put, sub path put, original val', function(done){ // bug from Jesse working on Trace
var gun = Gun().get('players'); var gun = Gun(gopt).get('players');
gun.put({ gun.put({
taken: true, taken: true,
@ -2937,10 +2939,10 @@ describe('Gun', function(){
game.put({board: {11: ' ', 22: ' ', 33: 'A'}}); game.put({board: {11: ' ', 22: ' ', 33: 'A'}});
},100); },100);
}); });
it("get init put map -> put, foreach gun path map", function(done){ // replicate Jesse's Trace game bug it("get init put map -> put, foreach gun path map", function(done){ // replicate Jesse's Trace game bug
done.c = 0; done.c = 0;
gun = Gun({init: true}) gun = Gun(gopt).opt({init: true})
.get('players').init() .get('players').init()
.put({ .put({
0: { 0: {
@ -3001,7 +3003,7 @@ describe('Gun', function(){
it("gun get path empty val", function(done){ // flip flop bug it("gun get path empty val", function(done){ // flip flop bug
done.c = 0; done.c = 0;
var u; var u;
var gun = Gun(); var gun = Gun(gopt);
var game = gun.get('game1/players'); var game = gun.get('game1/players');
var me = game.path('player1').val(function(val){ var me = game.path('player1').val(function(val){
if(!done.c){ done.fail = true } if(!done.c){ done.fail = true }
@ -3021,7 +3023,7 @@ describe('Gun', function(){
it("gun get path empty on", function(done){ it("gun get path empty on", function(done){
done.c = 0; done.c = 0;
var u; var u;
var gun = Gun(); var gun = Gun(gopt);
var game = gun.get('game2/players'); var game = gun.get('game2/players');
var me = game.path('player2').on(function(val){ var me = game.path('player2').on(function(val){
if(!done.c){ done.fail = true } if(!done.c){ done.fail = true }
@ -3043,7 +3045,7 @@ describe('Gun', function(){
it("gun get path empty not", function(done){ it("gun get path empty not", function(done){
var u; var u;
var gun = Gun({init: true}); var gun = Gun(gopt).opt({init: true})
var game = gun.get('game3/players').init(); var game = gun.get('game3/players').init();
var me = game.path('player3').not(function(field){ var me = game.path('player3').not(function(field){
expect(field).to.be('player3'); expect(field).to.be('player3');
@ -3053,7 +3055,7 @@ describe('Gun', function(){
it("gun get path empty init", function(done){ it("gun get path empty init", function(done){
var u; var u;
var gun = Gun({init: true}); var gun = Gun(gopt).opt({init: true});
var game = gun.get('game4/players').init(); var game = gun.get('game4/players').init();
var me = game.path('player4').init().path('alias').init().put({oh: 'awesome'}).val(function(val, field){ var me = game.path('player4').init().path('alias').init().put({oh: 'awesome'}).val(function(val, field){
expect(val.oh).to.be('awesome'); expect(val.oh).to.be('awesome');