mirror of
https://github.com/amark/gun.git
synced 2026-03-07 17:41:45 +00:00
get example on heroku
This commit is contained in:
25
examples/admin/app.js
Normal file
25
examples/admin/app.js
Normal file
@@ -0,0 +1,25 @@
|
||||
console.log("If modules not found, run `npm install` in example/admin folder!");
|
||||
var port = process.env.OPENSHIFT_NODEJS_PORT || process.env.VCAP_APP_PORT || process.env.PORT || 8888;
|
||||
var express = require('express');
|
||||
var bodyParser = require('body-parser');
|
||||
var app = express();
|
||||
var Gun = require('gun');
|
||||
|
||||
var gun = Gun({
|
||||
peers: 'http://localhost:' + port + '/gun'
|
||||
,s3: require('../../test/shotgun') // replace this with your own keys!
|
||||
});
|
||||
|
||||
app.use(express.static(__dirname))
|
||||
.use(bodyParser.json())
|
||||
.use(gun.server);
|
||||
|
||||
app.listen(port);
|
||||
console.log('Express started on port ' + port + ' with /gun');
|
||||
|
||||
gun.load('blob/data', function(){ // ugly little idempotent initializer, in case no data is set
|
||||
gun.set({_:{'#': "yVbyf7BqlXVQQUOE5cw9rf8h",'>':{hello: 1407328713707,from: 1407328713707}}, // this is an actual gun object, this won't overwrite any new changes
|
||||
hello: "world",
|
||||
from: "Mark Nadal"
|
||||
}).key('blob/data');
|
||||
});
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"_":{
|
||||
"#":"yVbyf7BqlXVQQUOE5cw9rf8h",
|
||||
">":{
|
||||
"hello":1407328713707,
|
||||
"from":1407328713707
|
||||
}
|
||||
},
|
||||
"hello":"world",
|
||||
"from":"Mark Nadal"
|
||||
}
|
||||
@@ -3,9 +3,6 @@
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.js"></script>
|
||||
<!--
|
||||
<script src="https://ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js"></script>
|
||||
-->
|
||||
<script src="../../gun.js"></script>
|
||||
</head>
|
||||
<body ng-controller="editor">
|
||||
@@ -37,9 +34,6 @@
|
||||
<div ng-if="key != '_'">
|
||||
<b>{{key}}</b>:
|
||||
<span contenteditable="true" gun>{{val}}</span>
|
||||
<!--
|
||||
<br>{{key}}: {{val}}
|
||||
-->
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
@@ -53,31 +47,32 @@
|
||||
</li>
|
||||
</ul>
|
||||
<script>
|
||||
gun = Gun('http://localhost:8888/gun');
|
||||
angular.module('admin', [
|
||||
|
||||
]).controller('editor', function($scope){
|
||||
$scope.data = {};
|
||||
$scope.$data = gun.load('blob/data', function(data){
|
||||
console.log("got it", data);
|
||||
$scope.data = data;
|
||||
$scope.$apply();
|
||||
});
|
||||
$scope.add = function(a,b,c){
|
||||
$scope.$data.path($scope.field).set(
|
||||
$scope.data[$scope.field] = 'value'
|
||||
);
|
||||
$scope.field = '';
|
||||
};
|
||||
window.$data = $scope.$data;
|
||||
}).directive('gun', function(){
|
||||
return function(scope, elem){
|
||||
elem.on('keyup', function(){
|
||||
scope.data[scope.key] = elem.text();
|
||||
scope.$apply();
|
||||
gun = Gun(['http://localhost:8888/gun', 'http://gunjs.herokuapp.com/gun']);
|
||||
angular.module('admin', [
|
||||
|
||||
]).controller('editor', function($scope){
|
||||
$scope.data = {};
|
||||
$scope.$data = gun.load('blob/data', function(data){
|
||||
$scope.data = data;
|
||||
$scope.$apply();
|
||||
});
|
||||
};
|
||||
});
|
||||
$scope.add = function(a,b,c){
|
||||
$scope.$data.path($scope.field).set(
|
||||
$scope.data[$scope.field] = 'value'
|
||||
);
|
||||
$scope.field = '';
|
||||
};
|
||||
window.$data = $scope.$data;
|
||||
}).directive('gun', function(){
|
||||
return function(scope, elem){
|
||||
elem.on('keyup', function(){
|
||||
scope.$data.path(scope.key).set(
|
||||
scope.data[scope.key] = elem.text()
|
||||
);
|
||||
scope.$apply();
|
||||
});
|
||||
};
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
9
examples/admin/package.json
Normal file
9
examples/admin/package.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "admin",
|
||||
"main": "app.js",
|
||||
"dependencies": {
|
||||
"express": "~>4.9.0",
|
||||
"body-parser": "~>1.8.1",
|
||||
"gun": "~>0.0.2b"
|
||||
}
|
||||
}
|
||||
1
examples/node_modules/gun/index.js
generated
vendored
Normal file
1
examples/node_modules/gun/index.js
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
module.exports = require('../../shots');
|
||||
@@ -1,7 +1,11 @@
|
||||
var fs = require('fs');
|
||||
var http = require('http');
|
||||
var qs = require('querystring');
|
||||
var gun = require('../../test/shotgun');
|
||||
var Gun = require('gun');
|
||||
var gun = Gun({
|
||||
peers: 'http://localhost:8888/gun'
|
||||
,s3: require('../../test/shotgun') // replace this with your own keys!
|
||||
});
|
||||
|
||||
http.route = function(url){
|
||||
console.log(url);
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
var sign = {};
|
||||
var gun = require('../../test/shotgun');
|
||||
var Gun = require('gun');
|
||||
var gun = Gun({
|
||||
peers: 'http://localhost:8888/gun'
|
||||
,s3: require('../../test/shotgun') // replace this with your own keys!
|
||||
});
|
||||
|
||||
sign.user = {}
|
||||
sign.user.create = function(form, cb, shell){ // TODO: REDO THIS TO MATCH GUN
|
||||
sign.user.create = function(form, cb, shell){
|
||||
sign.crypto(form, function(err, user){
|
||||
if(err || !user){ return cb(err) }
|
||||
user = {key: user.key, salt: user.salt};
|
||||
@@ -11,28 +15,9 @@ sign.user.create = function(form, cb, shell){ // TODO: REDO THIS TO MATCH GUN
|
||||
cb(null, user);
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
gun.load('email/mark@accelsor.com')
|
||||
.path('friends')
|
||||
.match({name: "David Oliveros"})
|
||||
.path('friends')
|
||||
.match({activity: 'surfer'})
|
||||
.get(function(surfer){
|
||||
sendEmail("Mark wants to leanr how ot surf, and you are a friend of a friend");
|
||||
});
|
||||
*/
|
||||
|
||||
sign.server = function(req, res){
|
||||
console.log("sign.server", req.headers, req.body);
|
||||
/*res.emit('data', {ok: 1});
|
||||
res.emit('data', {ok: 2});
|
||||
res.emit('data', {ok: 3});
|
||||
res.emit('data', {ok: 4});
|
||||
setTimeout(function(){
|
||||
res.emit('end', {ok: 5});
|
||||
}, 5000);
|
||||
return;*/
|
||||
if(!req.body || !req.body.email){ return res.emit('end', {err: "That email does not exist."}) }
|
||||
var user = gun.load('email/' + req.body.email, function(data){ // this callback is called the magazine, since it holds the clip
|
||||
console.log("data from key", data);
|
||||
|
||||
@@ -33,7 +33,9 @@ b.forEach(function (user, i) {
|
||||
user.friends = chance.shuffle(users).slice(chance.integer({ min: 20, max: (num < 120)? num : 120 }));
|
||||
});
|
||||
|
||||
var gun = require('../test/shotgun');
|
||||
var gun = require('gun')({
|
||||
s3: require('../test/shotgun') // replace this with your own keys!
|
||||
});
|
||||
|
||||
gun.set(b[0]);
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
s.batch = s.batch || {};
|
||||
if(s.batch[id]){ return s }
|
||||
s.batch[id] = (s.batch[id] || 0) + 1;
|
||||
console.log("no batch!", id);
|
||||
console.log("no batch!");
|
||||
s.S3().getObject(m, function(e,r){
|
||||
var d, t, m, r = r || (this && this.httpResponse);
|
||||
if(e || !r){ return s.own.on(id).emit(e) }
|
||||
|
||||
64
gate/s3pricing.html
Normal file
64
gate/s3pricing.html
Normal file
@@ -0,0 +1,64 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<style>
|
||||
.table li {
|
||||
float: left;
|
||||
min-width: 200px;
|
||||
max-width: 400px;
|
||||
}
|
||||
ul, li {
|
||||
list-style: none;
|
||||
}
|
||||
.clear {
|
||||
clear: both;
|
||||
}
|
||||
.none {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
<ul>
|
||||
<li><ul class="table none">
|
||||
<li>Seconds in month:</li>
|
||||
<li><input type="number" value="2629743.83" id="sim"></li>
|
||||
</ul></li>
|
||||
<li class="clear"></li>
|
||||
<li><ul class="table">
|
||||
<li>Persist every seconds:</li>
|
||||
<li><input type="number" value="15" id="se"></li>
|
||||
</ul></li>
|
||||
<li class="clear"></li>
|
||||
<li><ul class="table">
|
||||
<li>Over how many objects:</li>
|
||||
<li><input type="number" value="100" id="o"></li>
|
||||
</ul></li>
|
||||
<li class="clear"></li>
|
||||
<li><ul class="table">
|
||||
<li>Cost $:</li>
|
||||
<li><input type="number" value="" readonly id="r"></li>
|
||||
</ul></li>
|
||||
</ul>
|
||||
<br>
|
||||
<p>
|
||||
This page is for throughput calculation, it assumes continuous load non-stop.
|
||||
</p>
|
||||
<script>
|
||||
$(function(){
|
||||
var sim = $('#sim')
|
||||
, se = $('#se')
|
||||
, o = $('#o')
|
||||
, r = $('#r')
|
||||
, n = function(n){ return parseFloat(n) }
|
||||
$(document).on('keyup', function(){
|
||||
r.val(
|
||||
(( n(sim.val()) / n(se.val()) ) * n(o.val()) / 1000 * 0.005 ).toFixed(2)
|
||||
);
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
162
gun.js
162
gun.js
@@ -9,53 +9,64 @@
|
||||
Gun.is = function(gun){ return (gun instanceof Gun)? true : false }
|
||||
Gun._ = {};
|
||||
Gun.chain = Gun.prototype;
|
||||
Gun.chain._ = {};
|
||||
Gun.chain._.opt = {};
|
||||
Gun.chain._.nodes = {};
|
||||
Gun.chain._.chain = {};
|
||||
Gun.chain._.trace = [];
|
||||
Gun.chain._.keys = {};
|
||||
Gun.chain.init = function(opt, stun){ // idempotently update or set options
|
||||
var gun = this;
|
||||
gun._.events = gun._.events || Gun.on.split(); // we may not want it global for each gun instance?
|
||||
gun._.events.trace = gun._.events.trace || 0;
|
||||
gun._.events.at = gun._.events.at || 0;
|
||||
gun._ = gun._ || {};
|
||||
gun.__ = gun.__ || {};
|
||||
if(!opt){ return gun }
|
||||
gun.__.opt = gun.__.opt || {};
|
||||
gun.__.keys = gun.__.keys || {};
|
||||
gun.__.nodes = gun.__.nodes || {};
|
||||
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,{}) }) }
|
||||
gun._.opt.peers = opt.peers || gun._.opt.peers || {};
|
||||
gun._.opt.uuid = opt.uuid || gun._.opt.uuid || {};
|
||||
gun._.opt.hook = gun._.opt.hook || {};
|
||||
gun.__.opt.peers = opt.peers || gun.__.opt.peers || {};
|
||||
gun.__.opt.uuid = opt.uuid || gun.__.opt.uuid || {};
|
||||
gun.__.opt.hook = gun.__.opt.hook || {};
|
||||
Gun.obj.map(opt.hook, function(h, f){
|
||||
if(!Gun.fns.is(h)){ return }
|
||||
gun._.opt.hook[f] = h;
|
||||
gun.__.opt.hook[f] = h;
|
||||
});
|
||||
if(!stun){ Gun.on('init').emit(gun, opt) }
|
||||
return gun;
|
||||
}
|
||||
Gun.chain.chain = function(from){
|
||||
var gun = Gun();
|
||||
from = from || this;
|
||||
gun.__ = from.__;
|
||||
gun._ = {};
|
||||
Gun.obj.map(from._, function(val, field){
|
||||
gun._[field] = val;
|
||||
});
|
||||
gun._.events = Gun.on.split(); // we want events per chain
|
||||
gun._.events.trace = gun._.events.trace || 0;
|
||||
gun._.events.at = gun._.events.at || 0;
|
||||
return gun;
|
||||
}
|
||||
Gun.chain.load = function(key, cb, opt){
|
||||
var gun = this;
|
||||
var gun = this.chain();
|
||||
cb = cb || function(){};
|
||||
if(cb.node = gun._.keys[key]){ // set this to the current node, too!
|
||||
if(cb.node = gun.__.keys[key]){ // set this to the current node, too!
|
||||
Gun.log("from gun"); // remember to do all the same stack stuff here also!
|
||||
return cb(Gun.obj.copy(gun._.node = cb.node)), gun; // TODO: BUG: This needs to be frozen/copied, and react the same as below!
|
||||
}
|
||||
cb.fn = function(){}
|
||||
gun._.key = key;
|
||||
// missing: hear shots!
|
||||
if(Gun.fns.is(gun._.opt.hook.load)){
|
||||
gun._.opt.hook.load(key, function(err, data){
|
||||
if(Gun.fns.is(gun.__.opt.hook.load)){
|
||||
gun.__.opt.hook.load(key, function(err, data){
|
||||
gun._.loaded = (gun._.loaded || 0) + 1; // TODO: loading should be idempotent even if we got an err or no data
|
||||
if(err){ return (gun._.chain.dud||cb.fn)(err) }
|
||||
if(!data){ return (gun._.chain.blank||cb.fn)() }
|
||||
var nodes = {}, node;
|
||||
nodes[data._[own.sym.id]] = data;// missing: transform data, merging it! NO, THIS IS DONE WRONG, do a real check.
|
||||
Gun.union(gun._.nodes, nodes);
|
||||
node = gun._.keys[key] = gun._.nodes[data._[own.sym.id]];
|
||||
cb(Gun.obj.copy(gun._.node = node));
|
||||
gun._.events.on(gun._.events.at += 1).emit(node);
|
||||
gun._.events.at = 0; // ???? reset it back once everything is done?
|
||||
if(err){ return (gun._.dud||cb.fn)(err) }
|
||||
if(!data){ return (gun._.blank||cb.fn)() }
|
||||
var context = {nodes: {}};
|
||||
context.nodes[data._[own.sym.id]] = data;
|
||||
context = Gun.chain.set.now.union.call(gun, context.nodes); // data safely transformed
|
||||
if(context.err){ return (gun._.dud||cb.fn)(context.err) }
|
||||
gun._.node = gun.__.keys[key] = gun.__.nodes[data._[own.sym.id]];
|
||||
cb(Gun.obj.copy(gun._.node));
|
||||
gun._.events.on(gun._.events.at += 1).emit(gun._.node);
|
||||
gun._.events.at = 0; // ???? reset it back once everything is done? the returns above don't allow for this.
|
||||
}, opt);
|
||||
} else {
|
||||
Gun.log("Warning! You have no persistence layer to load from!");
|
||||
@@ -65,9 +76,9 @@
|
||||
Gun.chain.key = function(key, cb){ // TODO: Need to setImmediate if not loaded yet?
|
||||
Gun.log("make key", key);
|
||||
cb = cb || function(){};
|
||||
this._.keys[key] = this._.node;
|
||||
if(Gun.fns.is(this._.opt.hook.key)){
|
||||
this._.opt.hook.key(key, this._.node, function(err, data){
|
||||
this.__.keys[key] = this._.node;
|
||||
if(Gun.fns.is(this.__.opt.hook.key)){
|
||||
this.__.opt.hook.key(key, this._.node, function(err, data){
|
||||
Gun.log("key made", key);
|
||||
if(err){ return cb(err) }
|
||||
return cb(null);
|
||||
@@ -78,9 +89,9 @@
|
||||
return this;
|
||||
}
|
||||
Gun.chain.path = function(path){ // The focal point follows the path
|
||||
var gun = this;
|
||||
var gun = this.chain();
|
||||
path = path.split('.');
|
||||
Gun.log("PATH stack trace", gun._.events.trace + 1);
|
||||
Gun.log("PATH stack trace", gun._.events.trace + 1, 'was it before loaded?', this._);
|
||||
gun._.events.on(gun._.events.trace += 1).event(function trace(node){
|
||||
Gun.log("stack at", gun._.events.at);
|
||||
if(!path.length){ // if the path resolves to another node, we finish here
|
||||
@@ -104,9 +115,9 @@
|
||||
}
|
||||
}
|
||||
});
|
||||
if(gun._.loaded){
|
||||
if(this._.loaded){ // this was the previous chain, gun is the new one
|
||||
console.log("Send off!", gun._.events.at + 1);
|
||||
gun._.events.on(gun._.events.at += 1).emit(gun._.node);
|
||||
gun._.events.on(gun._.events.at += 1).emit(this._.node);
|
||||
}
|
||||
return gun;
|
||||
}
|
||||
@@ -130,7 +141,8 @@
|
||||
The live state at point of confirmation may or may not be different than when it was called.
|
||||
If this causes any application-level concern, it can compare against the live data by immediately reading it, or accessing the logs if enabled.
|
||||
*/
|
||||
Gun.chain.set = function(val, cb){ // TODO: set failed miserably to catch depth references in social tests
|
||||
Gun.chain.set = function(val, cb, opt){ // TODO: set failed miserably to catch depth references in social tests
|
||||
opt = opt || {};
|
||||
var gun = this, set;
|
||||
if(gun._.field){ // a field cannot be 0!
|
||||
set = {}; // in case we are doing a set on a field, not on a node
|
||||
@@ -144,10 +156,10 @@
|
||||
if(set.err){ return cb(set.err), gun }
|
||||
set = gun.set.now(set.nodes, Gun.time.is()); // set time state on nodes?
|
||||
if(set.err){ return cb(set.err), gun }
|
||||
Gun.union(gun._.nodes, set.nodes); // while this maybe should return a list of the nodes that were changed, we want to send the actual delta
|
||||
gun._.node = gun._.nodes[cb.root._[own.sym.id]] || cb.root; // TODO? Maybe BUG! if val is a new node on a field, _.node should now be that! Or will that happen automatically?
|
||||
if(Gun.fns.is(gun._.opt.hook.set)){
|
||||
gun._.opt.hook.set(set.nodes, function(err, data){ // now iterate through those nodes to S3 and get a callback once all are saved
|
||||
Gun.union(gun.__.nodes, set.nodes); // while this maybe should return a list of the nodes that were changed, we want to send the actual delta
|
||||
gun._.node = gun.__.nodes[cb.root._[own.sym.id]] || cb.root; // TODO? Maybe BUG! if val is a new node on a field, _.node should now be that! Or will that happen automatically?
|
||||
if(Gun.fns.is(gun.__.opt.hook.set)){
|
||||
gun.__.opt.hook.set(set.nodes, function(err, data){ // now iterate through those nodes to S3 and get a callback once all are saved
|
||||
Gun.log("gun set hook callback called");
|
||||
if(err){ return cb(err) }
|
||||
return cb(null);
|
||||
@@ -174,15 +186,34 @@
|
||||
});
|
||||
return context;
|
||||
}
|
||||
Gun.chain.set.now.union = function(prime){
|
||||
var gun = Gun.is(this)? this : null
|
||||
, context = {nodes: {}};
|
||||
if(!gun){
|
||||
context.err = {err: "No gun instance!", corrupt: true};
|
||||
return context;
|
||||
}
|
||||
Gun.obj.map(prime, function(node){
|
||||
var set = Gun.ify.call(gun, node);
|
||||
if(set.err){ return context.err = set.err }
|
||||
Gun.obj.map(set.nodes, function(node, id){
|
||||
context.nodes[id] = node;
|
||||
console.log("Gun set.now.union ----->", node);
|
||||
});
|
||||
});
|
||||
if(context.err){ return context }
|
||||
Gun.union(gun.__.nodes, context.nodes); // need to move good primes onto context.nodes;
|
||||
return context;
|
||||
}
|
||||
Gun.chain.match = function(){ // same as path, except using objects
|
||||
return this;
|
||||
}
|
||||
Gun.chain.blank = function(blank){
|
||||
this._.chain.blank = Gun.fns.is(blank)? blank : function(){};
|
||||
this._.blank = Gun.fns.is(blank)? blank : function(){};
|
||||
return this;
|
||||
}
|
||||
Gun.chain.dud = function(dud){
|
||||
this._.chain.dud = Gun.fns.is(dud)? dud : function(){};
|
||||
this._.dud = Gun.fns.is(dud)? dud : function(){};
|
||||
return this;
|
||||
}
|
||||
Gun.fns = {};
|
||||
@@ -311,11 +342,11 @@
|
||||
}());
|
||||
Gun.roulette = function(l, c){
|
||||
var gun = Gun.is(this)? this : {};
|
||||
if(gun._ && gun._.opt && gun._.opt.uuid){
|
||||
if(Gun.fns.is(gun._.opt.uuid)){
|
||||
return gun._.opt.uuid(l, c);
|
||||
if(gun._ && gun.__.opt && gun.__.opt.uuid){
|
||||
if(Gun.fns.is(gun.__.opt.uuid)){
|
||||
return gun.__.opt.uuid(l, c);
|
||||
}
|
||||
l = l || gun._.opt.uuid.length;
|
||||
l = l || gun.__.opt.uuid.length;
|
||||
}
|
||||
return Gun.text.random(l, c);
|
||||
}
|
||||
@@ -379,6 +410,7 @@
|
||||
var serverState = Gun.time.is();
|
||||
// add more checks?
|
||||
var state = HAM(serverState, deltaStates[field], states[field], deltaValue, current[field]);
|
||||
console.log("HAM:", field, deltaValue, deltaStates[field], current[field], 'the', state, (deltaStates[field] - serverState));
|
||||
if(state.err){
|
||||
Gun.log(".!HYPOTHETICAL AMNESIA MACHINE ERR!.", state.err);
|
||||
return;
|
||||
@@ -428,7 +460,7 @@
|
||||
}
|
||||
}({}));
|
||||
;(function(Serializer){
|
||||
Gun.ify = function(data, gun){ // TODO: BUG: Modify lists to include HAM state
|
||||
Gun.ify = function(data){ // TODO: BUG: Modify lists to include HAM state
|
||||
var gun = Gun.is(this)? this : {}
|
||||
, context = {
|
||||
nodes: {}
|
||||
@@ -586,7 +618,7 @@
|
||||
Page.load = function(key, cb, opt){
|
||||
cb = cb || function(){};
|
||||
opt = opt || {};
|
||||
Gun.obj.map(gun._.opt.peers, function(peer, url){
|
||||
Gun.obj.map(gun.__.opt.peers, function(peer, url){
|
||||
Page.ajax(url + '/' + key, null, function(data){
|
||||
Gun.log('via', url, key, data);
|
||||
// alert(data + data.hello + data.from + data._);
|
||||
@@ -594,8 +626,18 @@
|
||||
});
|
||||
});
|
||||
}
|
||||
Page.set = function(nodes, cb){
|
||||
cb = cb || function(){};
|
||||
// TODO: batch and throttle later.
|
||||
console.log('ajax set', nodes);
|
||||
Gun.obj.map(gun.__.opt.peers, function(peer, url){
|
||||
Page.ajax(url, nodes, function(reply){
|
||||
console.log("set confirmed?", reply);
|
||||
});
|
||||
});
|
||||
}
|
||||
Page.ajax =
|
||||
this.ajax =
|
||||
window.ajax =
|
||||
function(url, data, cb, opt){
|
||||
/*
|
||||
via Sockjs@1.0.0
|
||||
@@ -611,6 +653,8 @@
|
||||
data = u;
|
||||
} else {
|
||||
try{data = JSON.stringify(data);
|
||||
opt.headers = opt.headers || {};
|
||||
opt.headers["Content-Type"] = "application/json;charset=utf-8";
|
||||
}catch(e){}
|
||||
}
|
||||
opt.method = (data? 'POST' : 'GET');
|
||||
@@ -686,11 +730,6 @@
|
||||
if(opt.cookies || opt.credentials || opt.withCredentials){
|
||||
opt.xhr.withCredentials = true;
|
||||
}
|
||||
try{opt.xhr.open(opt.method, url, true);
|
||||
} catch(e) {
|
||||
opt.error();
|
||||
return;
|
||||
}
|
||||
opt.xhr.onreadystatechange = function(){
|
||||
if(!opt.xhr){ return }
|
||||
var reply, status;
|
||||
@@ -708,12 +747,29 @@
|
||||
opt.done(false);
|
||||
}
|
||||
}
|
||||
try{opt.xhr.open(opt.method, url, true);
|
||||
} catch(e) {
|
||||
opt.error();
|
||||
return;
|
||||
}
|
||||
if(opt.headers){
|
||||
try{for(var i in opt.headers){
|
||||
if(opt.headers.hasOwnProperty(i)){
|
||||
opt.xhr.setRequestHeader(i, opt.headers[i]);
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
opt.error();
|
||||
return;
|
||||
}
|
||||
}
|
||||
try{opt.xhr.send(data);
|
||||
}catch(e){
|
||||
opt.error();
|
||||
}
|
||||
return opt;
|
||||
}
|
||||
gun._.opt.hook.load = gun._.opt.hook.load || Page.load;
|
||||
gun.__.opt.hook.load = gun.__.opt.hook.load || Page.load;
|
||||
gun.__.opt.hook.set = gun.__.opt.hook.set || Page.set;
|
||||
});
|
||||
}({}));
|
||||
@@ -1,5 +1,5 @@
|
||||
{ "name": "gun"
|
||||
, "version": "0.0.2a"
|
||||
, "version": "0.0.2b"
|
||||
, "author": "Mark Nadal"
|
||||
, "description": "Graph engine."
|
||||
, "engines": {
|
||||
@@ -9,6 +9,8 @@
|
||||
"mime": "~>1.2.11",
|
||||
"aws-sdk": "~>2.0.0",
|
||||
"request": "~>2.39.0"
|
||||
|
||||
,"express": "~>4.9.0","body-parser": "~>1.8.1"
|
||||
}
|
||||
, "devDependencies": {
|
||||
"chance": "~>2.39.0"
|
||||
|
||||
89
shots.js
89
shots.js
@@ -4,52 +4,83 @@
|
||||
, url = require('url')
|
||||
, meta = {};
|
||||
Gun.on('init').event(function(gun, opt){
|
||||
gun.server = gun.server || function(req, res){ // where is the data? is it JSON? declare contentType=JSON from client?
|
||||
console.log("gun server has requests!", req.headers, req.body, req.url, req.method);
|
||||
gun.server = gun.server || function(req, res, next){ // where is the data? is it JSON? declare contentType=JSON from client?
|
||||
/*meta.CORS(req, res);
|
||||
res.emit('data', {way: 'cool'});
|
||||
res.emit('data', {shish: 'kabob'});
|
||||
res.emit('data', {I: 'love'});
|
||||
res.end();
|
||||
return;*/
|
||||
if(!req || !res){ return }
|
||||
if(!req.url){ return }
|
||||
if(!req.method){ return }
|
||||
next = next || function(){};
|
||||
if(!req || !res){ return next() }
|
||||
if(!req.url){ return next() }
|
||||
if(!req.method){ return next() }
|
||||
var tmp = {};
|
||||
tmp.url = url.parse(req.url, true);
|
||||
if(!gun.server.regex.test(tmp.url.pathname)){ return }
|
||||
tmp.key = tmp.url.pathname.replace(gun.server.regex,'').replace(/^\//i,''); // strip the base
|
||||
if(!tmp.key){
|
||||
return meta.JSON(res, {gun: true});
|
||||
if(!gun.server.regex.test(tmp.url.pathname)){ return next() }
|
||||
tmp.key = tmp.url.pathname.replace(gun.server.regex,'') || '';
|
||||
if(tmp.key.toLowerCase() === '.js'){
|
||||
res.writeHead(200, {'Content-Type': 'text/javascript'});
|
||||
res.end(gun.server.js = gun.server.js || require('fs').readFileSync(__dirname + '/gun.js'));
|
||||
return;
|
||||
}
|
||||
if('get' === req.method.toLowerCase()){ // get is used as subscribe
|
||||
// raw test for now:
|
||||
s3.load(tmp.key, function(err, data){
|
||||
console.log("\ngun server has requests!", req.method, req.url, req.headers, req.body);
|
||||
tmp.key = tmp.key.replace(/^\//i,'') || ''; // strip the base
|
||||
tmp.method = (req.method||'').toLowerCase();
|
||||
if('get' === tmp.method){ // get is used as subscribe
|
||||
if(!tmp.key){
|
||||
return meta.JSON(res, {gun: true});
|
||||
}
|
||||
// raw test for now, no auth:
|
||||
gun.load(tmp.key, function(err, data){
|
||||
console.log("gun subscribed!", err, data);
|
||||
meta.CORS(req, res);
|
||||
return meta.JSON(res, data || err);
|
||||
})
|
||||
} else
|
||||
if('post' === req.method.toLowerCase()){ // post is used as patch, sad that patch has such poor support
|
||||
|
||||
if('post' === tmp.method || 'patch' === tmp.method){ // post is used as patch, sad that patch has such poor support
|
||||
if(!req.body){
|
||||
console.log("Warn: No body on POST?");
|
||||
}
|
||||
// raw test for now, no auth:
|
||||
// should probably load all the nodes first?
|
||||
var context = Gun.chain.set.now.union.call(gun, req.body); // data safely transformed
|
||||
if(context.err){
|
||||
return meta.JSON(res, context.err); // need to standardize errors more
|
||||
}
|
||||
console.log("-------- union ---------");Gun.obj.map(gun.__.nodes, function(node){ console.log(node); });console.log("------------------------");
|
||||
/*
|
||||
WARNING! TODO: BUG! Do not send OK confirmation if amnesiaQuaratine is activated! Not until after it has actually been processed!!!
|
||||
*/
|
||||
if(Gun.fns.is(gun.__.opt.hook.set)){
|
||||
gun.__.opt.hook.set(context.nodes, function(err, data){ // now iterate through those nodes to S3 and get a callback once all are saved
|
||||
if(err){
|
||||
return meta.JSON(res, {err: err}); // server should handle the error for the client first! Not force client to re-attempt.
|
||||
}
|
||||
meta.JSON(res, {ok: 1}); // need to standardize OKs, OK:1 not good.
|
||||
});
|
||||
} else {
|
||||
context.err = "Warning! You have no persistence layer to save to!";
|
||||
Gun.log(context.err);
|
||||
}
|
||||
}
|
||||
}
|
||||
gun.server.regex = /^\/gun/i;
|
||||
var s3 = gun._.opt.s3 = gun._.opt.s3 || S3(opt && opt.s3);
|
||||
s3.path = s3.path || opt.s3.path || '';
|
||||
s3.keyed = s3.keyed || opt.s3.keyed || '';
|
||||
s3.nodes = s3.nodes || opt.s3.nodes || '_/nodes/';
|
||||
gun._.opt.batch = opt.batch || gun._.opt.batch || 10;
|
||||
gun._.opt.throttle = opt.throttle || gun._.opt.throttle || 2;
|
||||
if(!gun._.opt.keepMaxSockets){ require('https').globalAgent.maxSockets = require('http').globalAgent.maxSockets = Infinity } // WARNING: Document this!
|
||||
var s3 = gun.__.opt.s3 = gun.__.opt.s3 || S3(opt && opt.s3);
|
||||
s3.prefix = s3.prefix || opt.s3.prefix || '';
|
||||
s3.prekey = s3.prekey || opt.s3.prekey || '';
|
||||
s3.prenode = s3.prenode || opt.s3.prenode || '_/nodes/';
|
||||
gun.__.opt.batch = opt.batch || gun.__.opt.batch || 10;
|
||||
gun.__.opt.throttle = opt.throttle || gun.__.opt.throttle || 2;
|
||||
if(!gun.__.opt.keepMaxSockets){ require('https').globalAgent.maxSockets = require('http').globalAgent.maxSockets = Infinity } // WARNING: Document this!
|
||||
|
||||
s3.load = s3.load || function(key, cb, opt){
|
||||
cb = cb || function(){};
|
||||
opt = opt || {};
|
||||
if(opt.id){
|
||||
key = s3.path + s3.nodes + key;
|
||||
key = s3.prefix + s3.prenode + key;
|
||||
} else {
|
||||
key = s3.path + s3.keyed + key;
|
||||
key = s3.prefix + s3.prekey + key;
|
||||
}
|
||||
s3.get(key, function(err, data, text, meta){
|
||||
console.log('via s3', key);
|
||||
@@ -83,13 +114,13 @@
|
||||
}
|
||||
});
|
||||
});
|
||||
if(gun._.opt.batch < s3.batching){
|
||||
if(gun.__.opt.batch < s3.batching){
|
||||
return s3.set.now();
|
||||
}
|
||||
if(!gun._.opt.throttle){
|
||||
if(!gun.__.opt.throttle){
|
||||
return s3.set.now();
|
||||
}
|
||||
s3.wait = s3.wait || setTimeout(s3.set.now, gun._.opt.throttle * 1000); // in seconds
|
||||
s3.wait = s3.wait || setTimeout(s3.set.now, gun.__.opt.throttle * 1000); // in seconds
|
||||
}
|
||||
s3.set.now = s3.set.now || function(){
|
||||
clearTimeout(s3.wait);
|
||||
@@ -99,8 +130,8 @@
|
||||
, batch = s3.batch[s3.next];
|
||||
s3.next = Gun.time.is();
|
||||
Gun.obj.map(batch, function put(exists, id){
|
||||
var node = gun._.nodes[id]; // the batch does not actually have the nodes, but what happens when we do cold data? Could this be gone?
|
||||
s3.put(s3.path + s3.nodes + id, node, function(err, reply){
|
||||
var node = gun.__.nodes[id]; // the batch does not actually have the nodes, but what happens when we do cold data? Could this be gone?
|
||||
s3.put(s3.prefix + s3.prenode + id, node, function(err, reply){
|
||||
console.log("s3 put reply", id, err, reply);
|
||||
if(err || !reply){
|
||||
put(exists, id); // naive implementation of retry TODO: BUG: need backoff and anti-infinite-loop!
|
||||
@@ -123,7 +154,7 @@
|
||||
if(!id){
|
||||
return cb({err: "No ID!"});
|
||||
}
|
||||
s3.put(s3.path + s3.keyed + key, '', function(err, reply){ // key is 2 bytes??? Should be smaller
|
||||
s3.put(s3.prefix + s3.prekey + key, '', function(err, reply){ // key is 2 bytes??? Should be smaller
|
||||
console.log("s3 put reply", id, err, reply);
|
||||
if(err || !reply){
|
||||
s3.key(key, node, cb); // naive implementation of retry TODO: BUG: need backoff and anti-infinite-loop!
|
||||
|
||||
@@ -62,7 +62,9 @@ describe('Gun', function(){
|
||||
|
||||
it('path', function(done){
|
||||
this.timeout(9000);
|
||||
var gun = require('./shotgun');
|
||||
var gun = require('gun')({
|
||||
s3: require('./shotgun') // replace this with your own keys!
|
||||
});
|
||||
gun.load('d1ed426098eae2bba8c60605e1e4552f66281770', null, {id: true}) // get Rodney Morris
|
||||
.path('parent.parent.first') // Rodney's parent is Juan Colon, whose parent is Francis Peters
|
||||
.get(function(val){
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
var keys;
|
||||
if(process.env.LIVE || (process.env.NODE_ENV === 'production')){
|
||||
// Keys are provided by environment configs on the server
|
||||
//process.env['redis-install'] = '/tmp';
|
||||
} else {
|
||||
// Keys are hosted outside this folder, you must provide your own with environment variables.
|
||||
if((require('fs').existsSync||require('path').existsSync)(keys = __dirname + '/../../../linux/.ssh/keys-gun.js')){
|
||||
@@ -9,10 +8,13 @@ if(process.env.LIVE || (process.env.NODE_ENV === 'production')){
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = keys || {};
|
||||
/*
|
||||
var Gun = require('../shots');
|
||||
var gun = Gun({
|
||||
peers: 'http://localhost:8888/gun'
|
||||
,s3: keys
|
||||
});
|
||||
|
||||
module.exports = gun;
|
||||
module.exports = gun;
|
||||
*/
|
||||
Reference in New Issue
Block a user