Merge branch '0.5' of https://github.com/amark/gun into 0.5

This commit is contained in:
Mark Nadal 2016-12-30 19:23:20 -08:00
commit de9c6ce1ae
5 changed files with 144 additions and 62 deletions

View File

@ -0,0 +1,60 @@
var port = process.env.OPENSHIFT_NODEJS_PORT || process.env.VCAP_APP_PORT || process.env.PORT || process.argv[2] || 8080;
var Gun = require('../');
var gun = Gun({
file: 'data.json',
s3: {
key: '', // AWS Access Key
secret: '', // AWS Secret Token
bucket: '' // The bucket you want to save into
}
});
var server = require('http').createServer(function(req, res){
if(gun.wsp.server(req, res)){
return; // filters gun requests!
}
require('fs').createReadStream(require('path').join(__dirname, req.url)).on('error',function(){ // static files!
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(require('fs').readFileSync(require('path').join(__dirname, 'index.html'))); // or default to index
}).pipe(res); // stream
});
// do not do this to attach server... instead pull websocket provider and use that.
// gun.wsp(server);
var ws = require( 'ws' ); // default websocket provider gun used...
var WebSocketServer = ws.server;
var wss = new WebSocketServer( {
server: server, // 'ws' npm
autoAcceptConnections : false // want to handle the request (websocket npm?)
}
wss.on('connection',acceptConnection )
var gunPeers = []; // used as a list of connected clients.
Gun.on('out', function(msg){
msg = JSON.stringify({headers:{},body:msg});
gunPeers.forEach( function(peer){ peer.send( msg ) })
})
function acceptConnection( connection ) {
// connection.upgradeReq.headers['sec-websocket-protocol'] === (if present) protocol requested by client
// connection.upgradeReq.url === url request
console.log( "connect?", req.upgradeReq.headers, req.upgradeReq.url )
gunPeers.push( connection );
connection.on( 'error',function(error){console.log( "WebSocket Error:", error } );
connection.on( 'message',function(msg){gun.on('in',JSON.parse( msg.utf8Data).body)})
connection.on( 'close', function(reason,desc){
// gunpeers gone.
var i = peers.findIndex( function(p){return p===connection} );
if( i >= 0 )
gunPeers.splice( i, 1 );
})
}
server.listen(port);
console.log('Server started on port ' + port + ' with ');

13
gun.js
View File

@ -2202,9 +2202,9 @@
);
}
function Client (url, options) {
function Client (url, options, wscOptions ) {
if (!(this instanceof Client)) {
return new Client(url, options);
return new Client(url, options, wscOptions);
}
this.url = Client.formatURL(url);
@ -2215,6 +2215,7 @@
this.on = Gun.on;
this.options = options || {};
this.options.wsc = wscOptions;
this.resetBackoff();
}
@ -2238,7 +2239,7 @@
connect: function () {
var client = this;
var socket = new Client.WebSocket(this.url);
var socket = new Client.WebSocket(this.url, this.options.wsc.protocols, this.options.wsc );
this.socket = socket;
// Forward messages into the emitter.
@ -2355,7 +2356,9 @@
null;
}
Client.isSupported = Client.WebSocket !== null;
Client.isSupported = !!Client.WebSocket;
if(!Client.isSupported){ return } // TODO: For now, don't do anything in browsers/servers that don't work. Later, use JSONP fallback and merge with server code?
// Ensure the protocol is correct.
Client.formatURL = function (url) {
@ -2418,7 +2421,7 @@
return;
}
var client = new Client(url, options.backoff);
var client = new Client(url, options.backoff, gun.Back('opt.wsc') || {protocols:null});
// Add it to the pool.
Client.pool[url] = client;

View File

@ -6,73 +6,91 @@ var Gun = require('../gun'),
fs = require('fs'),
file = {};
function isUsingFileJS (context) {
// Options passed via .get or .put.
var methodOptions = context.opt || {};
// Options set on the gun chain.
var chainOption = context.gun.Back('opt.file');
// Favor method options over chain options.
var file = methodOptions.hasOwnProperty('file')
? methodOptions.file
: chainOption;
// Return whether the module is disabled.
return file !== false;
}
// queue writes, adapted from https://github.com/toolness/jsondown/blob/master/jsondown.js
var isWriting = false, queuedWrites = [];
function writeFile(path, disk, at){
if(isWriting) return queuedWrites.push(at);
isWriting = true;
var contents = JSON.stringify(disk, null, 2);
fs.writeFile(String(path), contents, function(err) {
var batch = queuedWrites.splice(0);
isWriting = false;
at.gun.Back(-1).on('in', {'@': at['#'], err: err, ok: err? false : 1});
if(!batch.length){ return }
batch.forEach(function(at){
at.gun.Back(-1).on('in', {'@': at['#'], err: err, ok: err? false : 1});
Gun.on('put', function(at){
if(!file.use){ return }
var graph = at.put, Graph = file.gun._.graph, opt = at.opt || {};
Gun.obj.map(graph, function(node, soul){
file.disk.graph[soul] = Graph[soul] || graph[soul];
});
graph = JSON.stringify(file.disk, null, 2);
// TODO: Allow for a `fs.writeFile` compatible module, that is more reliable/safe, to be passed in through the options.
fs.writeFile(opt.file || file.file, graph, function(err){
file.gun.on('in', {
'@': at['#'],
ok: err? undefined : 1,
err: err
});
});
});
Gun.on('get', function(at){
if(!file.use){ return }
var soul = at.get['#'];
if(!soul){ return }
var node = file.disk.graph[soul];
if(Gun.obj.has(at.get, '.')){
node = field(node, at.get['.']);
}
file.gun.on('in', {
put: Gun.graph.node(node),
'@': at['#']
})
});
function field(node, field){
if(!node){ return }
var tmp = node[field];
node = {_: node._};
if(undefined !== tmp){
node[field] = tmp;
}
tmp = node._;
if(tmp['>']){
tmp['>'] = Gun.obj.put({}, field, tmp['>'][field]);
}
return node;
}
Gun.on('put', function(at){
if (isUsingFileJS(at) === false) {
return;
}
var gun = at.gun, graph = at.put, opt = at.opt || {};
var __ = gun._.root._;
Gun.obj.map(graph, function(node, soul){
file.disk.graph[soul] = __.graph[soul] || graph[soul];
});
writeFile(opt.file || file.file, file.disk, at);
});
Gun.on('get', function(at){
if (isUsingFileJS(at) === false) {
return;
}
var gun = at.gun, lex = at.get;
if(!lex){return}
gun.Back(-1).on('in', {'@': at['#'], put: Gun.graph.node(file.disk.graph[lex['#']])});
//at.cb(null, file.disk.graph[lex['#']]);
});
Gun.on('opt', function(at){
var gun = at.gun, opts = at.opt;
if ((opts.file === false) || (opts.s3 && opts.s3.key)) {
var gun = at.gun, opt = at.opt;
if ((opt.file === false) || (opt.s3 && opt.s3.key)) {
return; // don't use this plugin if S3 is being used.
}
Gun.log.once(
'file-warning',
'WARNING! This `file.js` module for gun is ' +
'intended only for local development testing!'
'intended for local development testing only!'
);
file.file = opts.file || file.file || 'data.json';
file.raw = file.raw || (fs.existsSync || require('path').existsSync)(opts.file) ? fs.readFileSync(opts.file).toString() : null;
file.use = true;
file.file = String(opt.file || file.file || 'data.json');
file.raw = file.raw || (fs.existsSync || require('path').existsSync)(file.file) ? fs.readFileSync(file.file).toString() : null;
file.disk = file.disk || Gun.obj.ify(file.raw || {graph: {}});
file.disk.graph = file.disk.graph || {};
file.gun = gun;
});
(function test(){
return;
try{
var graph = Gun.obj.ify(fs.readFileSync('data.json').toString()).graph;
var read;
Gun().get('test/5').path('index').val(function(data){
read = data;
});
console.log((5 === read)? "READ SUCCESS" : "FAIL");
}catch(e){
var gun = Gun(), i = 100, expect = 0;
while(--i){
expect += i;
gun.get('test/' + i).put({ index: i, test: true });
}
setTimeout(function(){
var graph = Gun.obj.ify(fs.readFileSync('data.json').toString()).graph;
var count = 0;
Gun.obj.map(graph, function(node){
count += node.index;
});
console.log((expect && expect === count)? "WRITE SUCCESS! - RUN AGAIN" : "FAIL!");
},100);
};
}());

View File

@ -134,7 +134,7 @@ API.connect = function () {
var url = this.url;
// Open a new websocket.
var socket = new WebSocket(url);
var socket = new WebSocket(url, this.options.wsc.protocols, this.options.wsc);
// Re-use the previous listeners.
socket._events = this._events;

View File

@ -74,6 +74,7 @@ Gun.on('opt', function (context) {
if (sockets[url]) {
return;
}
if (!options.wsc) options.wsc = gun.Back('opt.wsc') || { protocols:null };
var socket = Socket(url, options);
sockets.add(url, socket);