diff --git a/README.md b/README.md
index d4a27dd7..510707bc 100644
--- a/README.md
+++ b/README.md
@@ -12,8 +12,8 @@
GUN is a realtime, distributed, offline-first, graph database engine. Lightweight and powerful, at just **~9KB** gzipped.
-
-[](https://youtu.be/-i-11T5ZI9o)
+
+
## Why?
@@ -89,7 +89,7 @@ Designed with ♥ by Mark Nadal, the gun team, and many amazing contributors. L
Thanks to the following people who have contributed to GUN, via code, issues, or conversation (this list has quickly become tremendously behind! We'll probably turn this into a dedicated wiki page so you can add yourself):
-[agborkowski](https://github.com/agborkowski); [alexlafroscia](https://github.com/alexlafroscia); [anubiann00b](https://github.com/anubiann00b); [bromagosa](https://github.com/bromagosa); [coolaj86](https://github.com/coolaj86); [d-oliveros](https://github.com/d-oliveros), [danscan](https://github.com/danscan); **[forrestjt](https://github.com/forrestjt) ([file.js](https://github.com/amark/gun/blob/master/lib/file.js))**; [gedw99](https://github.com/gedw99); [HelloCodeMing](https://github.com/HelloCodeMing); **[JosePedroDias](https://github.com/josepedrodias) ([graph visualizer](http://acor.sl.pt:9966))**; **[jveres](https://github.com/jveres) ([todoMVC](https://github.com/jveres/todomvc) [live demo](http://todos.loqali.com/))**; [ndarilek](https://github.com/ndarilek); [onetom](https://github.com/onetom); [phpnode](https://github.com/phpnode); [PsychoLlama](https://github.com/PsychoLlama); **[RangerMauve](https://github.com/RangerMauve) ([schema](https://github.com/gundb/gun-schema))**; [riston](https://github.com/riston); [rootsical](https://github.com/rootsical); [rrrene](https://github.com/rrrene); [sbeleidy](https://github.com/sbeleidy) [ssr1ram](https://github.com/ssr1ram); [Xe](https://github.com/Xe); [zot](https://github.com/zot);
+[agborkowski](https://github.com/agborkowski); [alexlafroscia](https://github.com/alexlafroscia); [anubiann00b](https://github.com/anubiann00b); [bromagosa](https://github.com/bromagosa); [coolaj86](https://github.com/coolaj86); [d-oliveros](https://github.com/d-oliveros), [danscan](https://github.com/danscan); **[forrestjt](https://github.com/forrestjt) ([file.js](https://github.com/amark/gun/blob/master/lib/file.js))**; [gedw99](https://github.com/gedw99); [HelloCodeMing](https://github.com/HelloCodeMing); **[JosePedroDias](https://github.com/josepedrodias) ([graph visualizer](http://acor.sl.pt:9966))**; **[jveres](https://github.com/jveres) ([todoMVC](https://github.com/jveres/todomvc))**; [ndarilek](https://github.com/ndarilek); [onetom](https://github.com/onetom); [phpnode](https://github.com/phpnode); [PsychoLlama](https://github.com/PsychoLlama); **[RangerMauve](https://github.com/RangerMauve) ([schema](https://github.com/gundb/gun-schema))**; [riston](https://github.com/riston); [rootsical](https://github.com/rootsical); [rrrene](https://github.com/rrrene); [sbeleidy](https://github.com/sbeleidy) [ssr1ram](https://github.com/ssr1ram); **[Stefdv](https://github.com/stefdv) ([Polymer/web components](http://stefdv.github.io/gun-collection/components/gun-collection/))**; [Xe](https://github.com/Xe); [zot](https://github.com/zot);
[ayurmedia](https://github.com/ayurmedia);
This list of contributors was manually compiled and alphabetically sorted. If we missed you, please submit an issue so we can get you added!
diff --git a/examples/express-auth.js b/examples/express-auth.js
new file mode 100644
index 00000000..c48061ac
--- /dev/null
+++ b/examples/express-auth.js
@@ -0,0 +1,30 @@
+console.log("If modules not found, run `npm install` in /example folder!"); // git subtree push -P examples heroku master // OR // git subtree split -P examples master && git push heroku [['HASH']]:master --force
+var port = process.env.OPENSHIFT_NODEJS_PORT || process.env.VCAP_APP_PORT || process.env.PORT || process.argv[2] || 80;
+
+var express = require('express');
+var app = express();
+
+var Gun = require('gun');
+var gun = Gun({
+ file: 'data.json',
+ s3: {
+ key: '', // AWS Access Key
+ secret: '', // AWS Secret Token
+ bucket: '' // The bucket you want to save into
+ }
+});
+
+gun.wsp(app/*, function(req, res, next){
+ console.log("auth!", req, req.body['#']);
+ if('get' === req.method){
+ if('example/todo/data' === req.body['#']){
+ next(req, res);
+ }
+ }
+ if('put' === req.method){
+ res({body: {err: "Permission denied!"}});
+ }
+}*/);
+app.use(express.static(__dirname)).listen(port);
+
+console.log('Server started on port ' + port + ' with /gun');
\ No newline at end of file
diff --git a/gun.js b/gun.js
index 5fc45ec2..618064ff 100644
--- a/gun.js
+++ b/gun.js
@@ -127,9 +127,17 @@
}
Type.time = {};
Type.time.is = function(t){ return t? t instanceof Date : (+new Date().getTime()) }
- Type.time.now = function(t){
- return ((t=t||Type.time.is()) > (Type.time.now.last || -Infinity)? (Type.time.now.last = t) : Type.time.now(t + 1)) + (Type.time.now.drift || 0); // TODO: BUG? Should this go on the inside?
- };
+ Type.time.now = (function(){
+ var time = Type.time.is, last = -Infinity, n = 0, d = 1000;
+ return function(){
+ var t = time();
+ if(last < t){
+ n = 0;
+ return last = t;
+ }
+ return last = t + ((n += 1) / d);
+ }
+ }());
}(Util));
;(function(exports){ // On event emitter generic javascript utility.
function On(){};
@@ -530,13 +538,15 @@
var gun = this, root = (gun.__ && gun.__.gun)? gun.__.gun : (gun._ = gun.__ = {gun: gun}).gun.chain(); // if root does not exist, then create a root chain.
root.__.by = root.__.by || function(f){ return gun.__.by[f] = gun.__.by[f] || {} };
root.__.graph = root.__.graph || {};
- root.__.opt = root.__.opt || {};
+ root.__.opt = root.__.opt || {peers: {}};
root.__.opt.wire = root.__.opt.wire || {};
if(Gun.text.is(opt)){ opt = {peers: opt} }
if(Gun.list.is(opt)){ opt = {peers: opt} }
if(Gun.text.is(opt.peers)){ opt.peers = [opt.peers] }
if(Gun.list.is(opt.peers)){ opt.peers = Gun.obj.map(opt.peers, function(n,f,m){ m(n,{}) }) }
- root.__.opt.peers = opt.peers || gun.__.opt.peers || {};
+ Gun.obj.map(opt.peers, function(v, f){
+ root.__.opt.peers[f] = v;
+ });
Gun.obj.map(opt.wire, function(h, f){
if(!Gun.fns.is(h)){ return }
root.__.opt.wire[f] = h;
@@ -908,6 +918,11 @@
}
function each(val, field){
//if(!Gun.is.rel(val)){ path.call(this.gun, null, val, field);return;}
+ if(opt.node){
+ if(!Gun.is.rel(val)){
+ return;
+ }
+ }
cb.hash[this.soul + field] = cb.hash[this.soul + field] || this.gun.path(field, path, {chain: chain, via: 'map'}); // TODO: path should reuse itself! We shouldn't have to do it ourselves.
// TODO:
// 1. Ability to turn off an event. // automatically happens within path since reusing is manual?
@@ -1132,7 +1147,7 @@
}(Gun));
var root = this || {}; // safe for window, global, root, and 'use strict'.
- if(root.window){ (root = window).Gun = Gun }
+ if(typeof window !== "undefined"){ (root = window).Gun = Gun }
if(typeof module !== "undefined" && module.exports){ module.exports = Gun }
if(typeof global !== "undefined"){ root = global; }
root.console = root.console || {log: function(s){ return s }}; // safe for old browsers
@@ -1163,7 +1178,8 @@
opt = opt || {};
var tab = gun.tab = gun.tab || {};
tab.store = tab.store || Tab.store;
- tab.request = tab.request || request;
+ tab.request = tab.request || Gun.request;
+ if(!tab.request){ throw new Error("Default GUN driver could not find default network abstraction.") }
tab.request.s = tab.request.s || {};
tab.headers = opt.headers || {};
tab.headers['gun-sid'] = tab.headers['gun-sid'] || Gun.text.random(); // stream id
@@ -1173,7 +1189,8 @@
var soul = lex[Gun._.soul];
if(!soul){ return }
cb = cb || function(){};
- (opt.headers = Gun.obj.copy(tab.headers)).id = tab.msg();
+ var ropt = {};
+ (ropt.headers = Gun.obj.copy(tab.headers)).id = tab.msg();
(function local(soul, cb){
tab.store.get(tab.prefix + soul, function(err, data){
if(!data){ return } // let the peers handle no data.
@@ -1184,11 +1201,11 @@
});
}(soul, cb));
if(!(cb.local = opt.local)){
- tab.request.s[opt.headers.id] = tab.error(cb, "Error: Get failed!", function(reply){
+ tab.request.s[ropt.headers.id] = tab.error(cb, "Error: Get failed!", function(reply){
setTimeout(function(){ tab.put(Gun.is.graph.ify(reply.body), function(){}, {local: true, peers: {}}) },1); // and flush the in memory nodes of this graph to localStorage after we've had a chance to union on it.
});
Gun.obj.map(opt.peers || gun.__.opt.peers, function(peer, url){ var p = {};
- tab.request(url, lex, tab.request.s[opt.headers.id], opt);
+ tab.request(url, lex, tab.request.s[ropt.headers.id], ropt);
cb.peers = true;
});
var node = gun.__.graph[soul];
@@ -1198,18 +1215,18 @@
} tab.peers(cb);
}
tab.put = tab.put || function(graph, cb, opt){
- //console.log("SAVE", graph);
cb = cb || function(){};
opt = opt || {};
- (opt.headers = Gun.obj.copy(tab.headers)).id = tab.msg();
+ var ropt = {};
+ (ropt.headers = Gun.obj.copy(tab.headers)).id = tab.msg();
Gun.is.graph(graph, function(node, soul){
if(!gun.__.graph[soul]){ return }
tab.store.put(tab.prefix + soul, gun.__.graph[soul], function(err){if(err){ cb({err: err}) }});
});
if(!(cb.local = opt.local)){
- tab.request.s[opt.headers.id] = tab.error(cb, "Error: Put failed!");
+ tab.request.s[ropt.headers.id] = tab.error(cb, "Error: Put failed!");
Gun.obj.map(opt.peers || gun.__.opt.peers, function(peer, url){
- tab.request(url, graph, tab.request.s[opt.headers.id], opt);
+ tab.request(url, graph, tab.request.s[ropt.headers.id], ropt);
cb.peers = true;
});
} tab.peers(cb);
@@ -1287,16 +1304,25 @@
gun.__.opt.wire.get = gun.__.opt.wire.get || tab.get;
gun.__.opt.wire.put = gun.__.opt.wire.put || tab.put;
gun.__.opt.wire.key = gun.__.opt.wire.key || tab.key;
+
+ Tab.request = tab.request;
+ Gun.Tab = Tab;
});
+}.bind(this || module)({}));
+
+
+;(function(Tab){
var request = (function(){
- function r(base, body, cb, opt){
- opt = opt || (base.length? {base: base} : base);
- opt.base = opt.base || base;
- opt.body = opt.body || body;
+ function r(base, body, cb, opt){ opt = opt || {};
+ var o = base.length? {base: base} : {};
+ o.base = opt.base || base;
+ o.body = opt.body || body;
+ o.headers = opt.headers;
+ o.url = opt.url;
cb = cb || function(){};
- if(!opt.base){ return }
- r.transport(opt, cb);
+ if(!o.base){ return }
+ r.transport(o, cb);
}
r.createServer = function(fn){ r.createServer.s.push(fn) }
r.createServer.ing = function(req, cb){
@@ -1311,7 +1337,7 @@
r.jsonp(opt, cb);
}
r.ws = function(opt, cb){
- var ws, WS = window.WebSocket || window.mozWebSocket || window.webkitWebSocket;
+ var ws, WS = r.WebSocket || window.WebSocket || window.mozWebSocket || window.webkitWebSocket;
if(!WS){ return }
if(ws = r.ws.peers[opt.base]){
if(!ws.readyState){ return setTimeout(function(){ r.ws(opt, cb) },10), true }
@@ -1328,9 +1354,10 @@
return true;
}
if(ws === false){ return }
- ws = r.ws.peers[opt.base] = new WS(opt.base.replace('http','ws'));
+ try{ws = r.ws.peers[opt.base] = new WS(opt.base.replace('http','ws'));
+ }catch(e){}
ws.onopen = function(o){ r.back = 2; r.ws(opt, cb) };
- ws.onclose = window.onbeforeunload = function(c){
+ ws.onclose = function(c){
if(!c){ return }
if(ws && ws.close instanceof Function){ ws.close() }
if(1006 === c.code){ // websockets cannot be used
@@ -1343,6 +1370,7 @@
r.ws(opt, function(){}); // opt here is a race condition, is it not? Does this matter?
}, r.back *= r.backoff);
};
+ if(typeof window !== "undefined"){ window.onbeforeunload = ws.onclose; }
ws.onmessage = function(m){
if(!m || !m.data){ return }
var res;
@@ -1351,15 +1379,17 @@
if(!res){ return }
res.headers = res.headers || {};
if(res.headers['ws-rid']){ return (r.ws.cbs[res.headers['ws-rid']]||function(){})(null, res) }
- //Gun.log("We have a pushed message!", res);
if(res.body){ r.createServer.ing(res, function(res){ r(opt.base, null, null, res)}) } // emit extra events.
};
- ws.onerror = function(e){ Gun.log(e); };
+ ws.onerror = function(e){ console.log(e); };
return true;
}
r.ws.peers = {};
r.ws.cbs = {};
r.jsonp = function(opt, cb){
+ if(typeof window === "undefined"){
+ return cb("JSONP is currently browser only.");
+ }
//Gun.log("jsonp send", opt);
r.jsonp.ify(opt, function(url){
//Gun.log(url);
@@ -1442,4 +1472,6 @@
}
return r;
}());
+ if(typeof window !== "undefined"){ Gun.request = request }
+ if(typeof module !== "undefined" && module.exports){ module.exports.request = request }
}.bind(this || module)({}));
\ No newline at end of file
diff --git a/lib/file.js b/lib/file.js
index d49ababe..5515dc5e 100644
--- a/lib/file.js
+++ b/lib/file.js
@@ -40,12 +40,14 @@ Gun.on('opt').event(function(gun, opts) {
gun.opt({wire: {
get: function get(lex, cb, o){
var node, soul = lex[Gun._.soul];
+ setImmediate(function(){
node = all.nodes[soul];
if(!node){ return cb(null) }
cb(null, node);
node = Gun.is.node.soul.ify({}, soul);
cb(null, node); // end.
cb(null, {}); // done.
+ });
},
put: function(graph, cb, o){
for (key in gun.__.graph) all.nodes[key]=gun.__.graph[key]||graph[key];
diff --git a/lib/server.js b/lib/server.js
index 25e8ac91..9ee1cb79 100644
--- a/lib/server.js
+++ b/lib/server.js
@@ -2,7 +2,7 @@
console.log("Hello wonderful person! :) I'm mark@gunDB.io, message me for help or with hatemail. I want to hear from you! <3");
var Gun = require('../gun');
require('./s3');
- require('./wsp');
require('./file');
+ require('./wsp');
module.exports = Gun;
}());
diff --git a/lib/wsp.js b/lib/wsp.js
index 46343fda..339d673b 100644
--- a/lib/wsp.js
+++ b/lib/wsp.js
@@ -1,5 +1,5 @@
;(function(wsp){
- var Gun = require('../gun')
+ var Gun = require('../gun')
, ws = require('ws').Server
, http = require('./http')
, url = require('url');
@@ -10,10 +10,10 @@
server = gun.__.opt.ws.server = gun.__.opt.ws.server || opt.ws.server || 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'];
+ 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 || (ws.sid && 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));
@@ -23,7 +23,8 @@
});
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, auth){
+ gun.wsp.auth = auth;
if(!server){ return gun }
if(Gun.fns.is(server.address)){
if(server.address()){
@@ -112,15 +113,24 @@
// 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.
// all states, implemented with GET, are replied to the source that asked for it.
- function tran(req, res){
- if(!req || !res || !req.body || !req.headers || !req.headers.id){ return }
- if(gun.wsp.msg(req.headers.id)){ return }
- req.method = req.body? 'put' : 'get';
+ function flow(req, res){
gun.wsp.on('network').emit(Gun.obj.copy(req));
if(req.headers.rid){ return } // no need to process.
if(Gun.is.lex(req.body)){ return tran.get(req, res) }
else { return tran.put(req, res) }
- cb({body: {hello: 'world'}});
+ }
+ function tran(req, res){
+ if(!req || !res || !req.body || !req.headers || !req.headers.id){ return }
+ if(gun.wsp.msg(req.headers.id)){ return }
+ req.method = (req.body && !Gun.is.lex(req.body))? 'put' : 'get';
+ if(gun.wsp.auth){ return gun.wsp.auth(req, function(reply){
+ if(!reply.headers){ reply.headers = {} }
+ if(!reply.headers['Content-Type']){ reply.headers['Content-Type'] = tran.json }
+ if(!reply.rid){ reply.headers.rid = req.headers.id }
+ if(!reply.id){ reply.headers.id = gun.wsp.msg() }
+ res(reply);
+ }, flow) }
+ else { return flow(req, res) }
}
tran.get = function(req, cb){
var key = req.url.key
@@ -140,7 +150,7 @@
//Gun.log("GET!", req);
key = req.body;
//Gun.log("tran.get", key);
- var opt = {key: false};
+ var opt = {key: false, local: true};
//gun.get(key, function(err, node){
(gun.__.opt.wire.get||function(key, cb){cb(null,null)})(key, function(err, node){
//Gun.log("tran.get", key, "<---", err, node);
@@ -193,7 +203,7 @@
if(err){ return cb({headers: reply.headers, body: {err: err || "Failed."}}) } // TODO: err should already be an error object?
cb({headers: reply.headers, body: {ok: ok || "Persisted."}});
//Gun.log("tran.put <------------------------", ok);
- });
+ }, {local: true});
}).err){ cb({headers: reply.headers, body: {err: req.err || "Union failed."}}) }
} else {
cb({headers: reply.headers, body: {err: "Not a valid graph!"}});
@@ -209,22 +219,55 @@
wsp(opt.server);
}
- setTimeout(function(){ // hack it in :( for now, since 0.4.x will allow us to have multiple drivers.
- var proxy = gun.__.opt.wire;
- var driver = {
- put: function(graph, cb, opt){
- proxy.put(graph, cb, opt);
- var msg = {
- headers: {'Content-Type': 'application/json', id: gun.wsp.msg()},
- body: graph
- };
- gun.wsp.on('network').emit(msg);
- },
- get: proxy.get
+ if(gun.wsp.driver){ return }
+ var driver = gun.wsp.driver = {};
+ var noop = function(){};
+ var get = gun.__.opt.wire.get || noop;
+ var put = gun.__.opt.wire.put || noop;
+ var driver = {
+ put: function(graph, cb, opt){
+ put(graph, cb, opt);
+ opt = opt || {};
+ if(opt.local){ return }
+ var id = gun.wsp.msg();
+ gun.wsp.on('network').emit({ // sent to dynamic peers!
+ headers: {'Content-Type': 'application/json', id: id},
+ body: graph
+ });
+ var ropt = {headers:{}, WebSocket: WebSocket};
+ ropt.headers.id = id;
+ Gun.obj.map(opt.peers || gun.__.opt.peers, function(peer, url){
+ Gun.request(url, graph, function(err, reply){
+ reply.body = reply.body || reply.chunk || reply.end || reply.write;
+ if(err || !reply || (err = reply.body && reply.body.err)){
+ return cb({err: Gun.log(err || "Put failed.") });
+ }
+ cb(null, reply.body);
+ }, ropt);
+ });
+ },
+ get: function(lex, cb, opt){
+ get(lex, cb, opt);
+ opt = opt || {};
+ if(opt.local){ return }
+ if(!Gun.request){ return console.log("Server could not find default network abstraction.") }
+ var ropt = {headers:{}};
+ ropt.headers.id = gun.wsp.msg();
+ Gun.obj.map(opt.peers || gun.__.opt.peers, function(peer, url){
+ Gun.request(url, lex, function(err, reply){
+ reply.body = reply.body || reply.chunk || reply.end || reply.write;
+ if(err || !reply || (err = reply.body && reply.body.err)){
+ return cb({err: Gun.log(err || "Get failed.") });
+ }
+ cb(null, reply.body);
+ }, ropt);
+ });
}
- gun.__.opt.wire = driver;
- gun.opt({wire: driver}, true);
- },1);
-
+ }
+ var WebSocket = require('ws');
+ Gun.request.WebSocket = WebSocket;
+ Gun.request.createServer(gun.wsp.wire);
+ gun.__.opt.wire = driver;
+ gun.opt({wire: driver}, true);
});
}({}));
\ No newline at end of file
diff --git a/package.json b/package.json
index 57caac27..089150b2 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "gun",
- "version": "0.3.92",
+ "version": "0.3.991",
"description": "Graph engine",
"main": "index.js",
"scripts": {
diff --git a/test/common.js b/test/common.js
index c934c4ba..ef9ae2e7 100644
--- a/test/common.js
+++ b/test/common.js
@@ -3799,7 +3799,7 @@ describe('Gun', function(){
});
it("get context", function(done){ // TODO: HUH?????? This was randomly causing errors?
- var gun = Gun();
+ var gun = Gun();
var ref = gun.get('ctx/lol').get('ctx/foo').put({hello: 'world'});
gun.get('ctx/lol').val(function(implicit){
done.fail = true;
@@ -3975,29 +3975,31 @@ describe('Gun', function(){
it("Don't put on parents", function(done){ // TODO: ADD TO 0.5 BRANCH! // Another Stefdv find.
var test = gun.get('test');
- test.path('try.this.at.lvl4').put({msg:'hoi'})
- test.val(function(node,b){
- delete node._;
- expect(Gun.obj.empty(node, 'try')).to.be.ok();
- node = Gun.obj.copy(gun.__.graph[Gun.is.rel(node.try)]);
+ test.path('try.this.at.lvl4').put({msg:'hoi'});
+ setTimeout(function(){ // TODO: Is this cheating??
+ test.val(function(node,b){
+ delete node._;
+ expect(Gun.obj.empty(node, 'try')).to.be.ok();
+ node = Gun.obj.copy(gun.__.graph[Gun.is.rel(node.try)]);
- delete node._;
- expect(Gun.obj.empty(node, 'this')).to.be.ok();
- node = Gun.obj.copy(gun.__.graph[Gun.is.rel(node.this)]);
+ delete node._;
+ expect(Gun.obj.empty(node, 'this')).to.be.ok();
+ node = Gun.obj.copy(gun.__.graph[Gun.is.rel(node.this)]);
+
+ delete node._;
+ expect(Gun.obj.empty(node, 'at')).to.be.ok();
+ node = Gun.obj.copy(gun.__.graph[Gun.is.rel(node.at)]);
- delete node._;
- expect(Gun.obj.empty(node, 'at')).to.be.ok();
- node = Gun.obj.copy(gun.__.graph[Gun.is.rel(node.at)]);
+ delete node._;
+ expect(Gun.obj.empty(node, 'lvl4')).to.be.ok();
+ node = Gun.obj.copy(gun.__.graph[Gun.is.rel(node.lvl4)]);
- delete node._;
- expect(Gun.obj.empty(node, 'lvl4')).to.be.ok();
- node = Gun.obj.copy(gun.__.graph[Gun.is.rel(node.lvl4)]);
-
- delete node._;
- expect(Gun.obj.empty(node, 'msg')).to.be.ok();
- expect(node.msg).to.be('hoi');
- done();
- });
+ delete node._;
+ expect(Gun.obj.empty(node, 'msg')).to.be.ok();
+ expect(node.msg).to.be('hoi');
+ done();
+ });
+ },100);
});
});
diff --git a/test/server/http.js b/test/server/http.js
new file mode 100644
index 00000000..891cbfe0
--- /dev/null
+++ b/test/server/http.js
@@ -0,0 +1,15 @@
+//client.js writes data up to a listening hub.js, which relays to a server.js that reads the data.
+
+var http = require('http');
+
+var Gun = require('../../index');
+var gun = Gun({
+ file: 'http.json'
+});
+
+
+var server = http.createServer(function(req, res){});
+gun.wsp(server);
+server.listen(8080);
+
+console.log('Server started on port ' + 8080 + ' with /gun');
\ No newline at end of file
diff --git a/test/server/node-client.js b/test/server/node-client.js
new file mode 100644
index 00000000..ec423e5d
--- /dev/null
+++ b/test/server/node-client.js
@@ -0,0 +1,9 @@
+var Gun = require('../../index');
+
+var location = {host:"localhost"};
+
+var gun = Gun( { file: 'read.json', peers: ['http://' + location.host + ':8080/gun'] });
+
+gun.get( 'data' ).path('stuff').map(function(val,field){ console.log( field, "=", val ); } );
+
+console.log( "done... wait forever?" );
\ No newline at end of file
diff --git a/test/server/node-write.js b/test/server/node-write.js
new file mode 100644
index 00000000..ce0aaf49
--- /dev/null
+++ b/test/server/node-write.js
@@ -0,0 +1,7 @@
+var Gun = require('../../index');
+
+var location = {host:"localhost"};
+
+var gun = Gun( { file: 'write.json', peers: ['http://' + location.host + ':8080/gun'] });
+
+gun.get( 'data' ).path('stuff').put({a: {data: 1}, b: {data: 2}});
\ No newline at end of file