From 16fb144adc4c6db7e94d21c9a7dc93ba98337b09 Mon Sep 17 00:00:00 2001 From: Mark Nadal Date: Wed, 1 Jun 2016 15:01:48 -0700 Subject: [PATCH 01/13] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d4a27dd7..2827e969 100644 --- a/README.md +++ b/README.md @@ -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! From a713bb0ae78fa572fadf7dcc7ddd4d35591823f8 Mon Sep 17 00:00:00 2001 From: Mark Nadal Date: Wed, 22 Jun 2016 15:05:58 -0700 Subject: [PATCH 02/13] minimum temporary auth for server, clients still independent from auth though --- examples/express-auth.js | 30 ++++++++++++++++++++++++++++++ lib/wsp.js | 24 +++++++++++++++++------- 2 files changed, 47 insertions(+), 7 deletions(-) create mode 100644 examples/express-auth.js 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/lib/wsp.js b/lib/wsp.js index 46343fda..ead5d8e1 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'); @@ -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 From a83ff0c114dbb41a3b1918aced49653b08281cae Mon Sep 17 00:00:00 2001 From: Mark Nadal Date: Wed, 22 Jun 2016 16:56:34 -0700 Subject: [PATCH 03/13] fix driver to actually connect to other servers --- gun.js | 33 ++++++++++++++++++++------------- package.json | 2 +- test/common.js | 44 +++++++++++++++++++++++--------------------- 3 files changed, 44 insertions(+), 35 deletions(-) diff --git a/gun.js b/gun.js index 5fc45ec2..98c3aa85 100644 --- a/gun.js +++ b/gun.js @@ -1173,7 +1173,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 +1185,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 +1199,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 +1288,21 @@ 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 = request; + Gun.Tab = 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; + 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){ @@ -1328,7 +1334,8 @@ 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){ if(!c){ return } diff --git a/package.json b/package.json index 57caac27..43dcc6fe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gun", - "version": "0.3.92", + "version": "0.3.93", "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); }); }); From af02a42e7a25c064ca46eb199b1c75033ec9c949 Mon Sep 17 00:00:00 2001 From: Mark Nadal Date: Wed, 22 Jun 2016 17:20:36 -0700 Subject: [PATCH 04/13] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2827e969..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. - -[![1 minute demo of fault tolerance](http://img.youtube.com/vi/-i-11T5ZI9o/0.jpg)](https://youtu.be/-i-11T5ZI9o) + + ## Why? From f442c9a929f3a9575d774353a1dc6dbc7b1b40b4 Mon Sep 17 00:00:00 2001 From: Mark Nadal Date: Sat, 25 Jun 2016 14:31:10 -0700 Subject: [PATCH 05/13] Jesse warned me about time and I should have listened! --- gun.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/gun.js b/gun.js index 98c3aa85..ae56ec0b 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(){}; From d20575b7a726e5d56f54e724282382bdc4d60319 Mon Sep 17 00:00:00 2001 From: Mark Nadal Date: Sat, 25 Jun 2016 14:35:59 -0700 Subject: [PATCH 06/13] forgot to version bump Jesse being right --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 43dcc6fe..2914a305 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gun", - "version": "0.3.93", + "version": "0.3.94", "description": "Graph engine", "main": "index.js", "scripts": { From 146f821e5643d049e65d53ddfb2b9e6da317158e Mon Sep 17 00:00:00 2001 From: Mark Nadal Date: Tue, 5 Jul 2016 10:30:48 -0700 Subject: [PATCH 07/13] Merge peer options --- gun.js | 6 ++++-- package.json | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/gun.js b/gun.js index ae56ec0b..fa26b88b 100644 --- a/gun.js +++ b/gun.js @@ -538,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; diff --git a/package.json b/package.json index 2914a305..5f8e0769 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gun", - "version": "0.3.94", + "version": "0.3.95", "description": "Graph engine", "main": "index.js", "scripts": { From ab60299fe064d7a6f1c3e0cacd7388f5720fbdcc Mon Sep 17 00:00:00 2001 From: Mark Nadal Date: Thu, 7 Jul 2016 09:56:31 -0700 Subject: [PATCH 08/13] fix server-to-server for @d3x0r --- gun.js | 22 +++++++++++++---- lib/server.js | 2 +- lib/wsp.js | 49 +++++++++++++++++++++++++------------- test/server/http.js | 14 +++++++++++ test/server/node-client.js | 6 +++++ 5 files changed, 71 insertions(+), 22 deletions(-) create mode 100644 test/server/http.js create mode 100644 test/server/node-client.js diff --git a/gun.js b/gun.js index fa26b88b..0709226f 100644 --- a/gun.js +++ b/gun.js @@ -1173,7 +1173,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 @@ -1299,12 +1300,16 @@ gun.__.opt.wire.put = gun.__.opt.wire.put || tab.put; gun.__.opt.wire.key = gun.__.opt.wire.key || tab.key; - Tab.request = request; + Tab.request = tab.request; Gun.Tab = Tab; }); +}.bind(this || module)({})); + + +;(function(Tab){ var request = (function(){ - function r(base, body, cb, opt){ + function r(base, body, cb, opt){ opt = opt || {}; var o = base.length? {base: base} : {}; o.base = opt.base || base; o.body = opt.body || body; @@ -1312,6 +1317,7 @@ o.url = opt.url; cb = cb || function(){}; if(!o.base){ return } + if(opt.WebSocket){ o.WebSocket = opt.WebSocket } r.transport(o, cb); } r.createServer = function(fn){ r.createServer.s.push(fn) } @@ -1327,7 +1333,7 @@ r.jsonp(opt, cb); } r.ws = function(opt, cb){ - var ws, WS = window.WebSocket || window.mozWebSocket || window.webkitWebSocket; + var ws, WS = opt.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 } @@ -1347,7 +1353,7 @@ 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 @@ -1360,6 +1366,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; @@ -1377,6 +1384,9 @@ 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); @@ -1459,4 +1469,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/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 ead5d8e1..6d9c41fb 100644 --- a/lib/wsp.js +++ b/lib/wsp.js @@ -219,22 +219,39 @@ 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); + var msg = { + headers: {'Content-Type': 'application/json', id: gun.wsp.msg()}, + body: graph + }; + gun.wsp.on('network').emit(msg); + }, + get: function(lex, cb, opt){ + get(lex, cb, opt); + if(!Gun.request){ return console.log("Server could not find default network abstraction.") } + opt = opt || {}; + var ropt = {headers:{}, WebSocket: WebSocket}; + 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.__.opt.wire = driver; + gun.opt({wire: driver}, true); }); }({})); \ No newline at end of file diff --git a/test/server/http.js b/test/server/http.js new file mode 100644 index 00000000..d1f06eb2 --- /dev/null +++ b/test/server/http.js @@ -0,0 +1,14 @@ +var http = require('http'); + +var Gun = require('../../index'); +var gun = Gun({ + file: 'data.json' +}); + + +gun.get('data').put({a: {data: 1}, b: {data: 2}}); +var server = http.createServer(function(req, res){}); +gun.wsp(server); +server.listen(8081); + +console.log('Server started on port ' + 8081 + ' 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..261309fd --- /dev/null +++ b/test/server/node-client.js @@ -0,0 +1,6 @@ +var Gun = require('../../index'); +var location = {host:"localhost"}; +var gun = Gun( 'ws://' + location.host + ':8081/gun'); +var gdb = gun.get( 'data' ); +gdb.map(function(val,field){ console.log( field, "=", val ); } ); +console.log( "done... wait forever?" ); \ No newline at end of file From 8160ae0c4a34d96377159ab66261555cdb933e6e Mon Sep 17 00:00:00 2001 From: Mark Nadal Date: Thu, 7 Jul 2016 09:57:34 -0700 Subject: [PATCH 09/13] fix server-to-server for @d3x0r --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5f8e0769..7813e08d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gun", - "version": "0.3.95", + "version": "0.3.96", "description": "Graph engine", "main": "index.js", "scripts": { From 590b52d92be32264de877da86c872f9f01c7e130 Mon Sep 17 00:00:00 2001 From: Mark Nadal Date: Thu, 7 Jul 2016 12:54:19 -0700 Subject: [PATCH 10/13] fixed server-to-server for @d3x0r --- gun.js | 6 ++---- lib/wsp.js | 36 ++++++++++++++++++++++++++---------- package.json | 2 +- test/server/http.js | 9 +++++---- test/server/node-client.js | 9 ++++++--- test/server/node-write.js | 7 +++++++ 6 files changed, 47 insertions(+), 22 deletions(-) create mode 100644 test/server/node-write.js diff --git a/gun.js b/gun.js index 0709226f..265ac557 100644 --- a/gun.js +++ b/gun.js @@ -1317,7 +1317,6 @@ o.url = opt.url; cb = cb || function(){}; if(!o.base){ return } - if(opt.WebSocket){ o.WebSocket = opt.WebSocket } r.transport(o, cb); } r.createServer = function(fn){ r.createServer.s.push(fn) } @@ -1333,7 +1332,7 @@ r.jsonp(opt, cb); } r.ws = function(opt, cb){ - var ws, WS = opt.WebSocket || 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 } @@ -1375,10 +1374,9 @@ 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 = {}; diff --git a/lib/wsp.js b/lib/wsp.js index 6d9c41fb..339d673b 100644 --- a/lib/wsp.js +++ b/lib/wsp.js @@ -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)); @@ -150,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); @@ -203,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!"}}); @@ -227,17 +227,31 @@ var driver = { put: function(graph, cb, opt){ put(graph, cb, opt); - var msg = { - headers: {'Content-Type': 'application/json', id: gun.wsp.msg()}, + 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 - }; - gun.wsp.on('network').emit(msg); + }); + 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); - if(!Gun.request){ return console.log("Server could not find default network abstraction.") } opt = opt || {}; - var ropt = {headers:{}, WebSocket: WebSocket}; + 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){ @@ -251,6 +265,8 @@ } } var WebSocket = require('ws'); + Gun.request.WebSocket = WebSocket; + Gun.request.createServer(gun.wsp.wire); gun.__.opt.wire = driver; gun.opt({wire: driver}, true); }); diff --git a/package.json b/package.json index 7813e08d..0e6a12a3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gun", - "version": "0.3.96", + "version": "0.3.97", "description": "Graph engine", "main": "index.js", "scripts": { diff --git a/test/server/http.js b/test/server/http.js index d1f06eb2..891cbfe0 100644 --- a/test/server/http.js +++ b/test/server/http.js @@ -1,14 +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: 'data.json' + file: 'http.json' }); -gun.get('data').put({a: {data: 1}, b: {data: 2}}); var server = http.createServer(function(req, res){}); gun.wsp(server); -server.listen(8081); +server.listen(8080); -console.log('Server started on port ' + 8081 + ' with /gun'); \ No newline at end of file +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 index 261309fd..ec423e5d 100644 --- a/test/server/node-client.js +++ b/test/server/node-client.js @@ -1,6 +1,9 @@ var Gun = require('../../index'); + var location = {host:"localhost"}; -var gun = Gun( 'ws://' + location.host + ':8081/gun'); -var gdb = gun.get( 'data' ); -gdb.map(function(val,field){ console.log( field, "=", val ); } ); + +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 From 7fde5eb8362ae2eea4bfb2435a55e556b5091156 Mon Sep 17 00:00:00 2001 From: Mark Nadal Date: Mon, 11 Jul 2016 16:08:54 -0700 Subject: [PATCH 11/13] fix/mask @d3x0r 's #203 --- lib/file.js | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) 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/package.json b/package.json index 0e6a12a3..5c0a734e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gun", - "version": "0.3.97", + "version": "0.3.98", "description": "Graph engine", "main": "index.js", "scripts": { From 5e30de8acde44c0ad15cdf93858909da8bccd497 Mon Sep 17 00:00:00 2001 From: Mark Nadal Date: Tue, 26 Jul 2016 22:49:54 -0700 Subject: [PATCH 12/13] fix ? env ? --- gun.js | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gun.js b/gun.js index 265ac557..9611e229 100644 --- a/gun.js +++ b/gun.js @@ -1142,7 +1142,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 diff --git a/package.json b/package.json index 5c0a734e..e844e0c1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gun", - "version": "0.3.98", + "version": "0.3.99", "description": "Graph engine", "main": "index.js", "scripts": { From 8cea0bc5f86ce9a620a0ee703d836e97e333abfd Mon Sep 17 00:00:00 2001 From: Mark Nadal Date: Wed, 3 Aug 2016 17:11:49 -0700 Subject: [PATCH 13/13] add node filter for map --- gun.js | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/gun.js b/gun.js index 9611e229..618064ff 100644 --- a/gun.js +++ b/gun.js @@ -918,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? diff --git a/package.json b/package.json index e844e0c1..089150b2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gun", - "version": "0.3.99", + "version": "0.3.991", "description": "Graph engine", "main": "index.js", "scripts": {