mirror of
https://github.com/amark/gun.git
synced 2025-06-03 20:56:43 +00:00
insert, map, fixes, working on path
This commit is contained in:
parent
146ee003d7
commit
22aea79838
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
node_modules/*
|
||||
npm-debug.log
|
||||
*data.json
|
||||
|
@ -6,7 +6,12 @@ var app = express();
|
||||
|
||||
var Gun = require('gun');
|
||||
var gun = Gun({
|
||||
s3: (process.env.NODE_ENV === 'production')? null : require('../test/shotgun') // replace this with your own keys!
|
||||
file: 'data.json',
|
||||
s3: {
|
||||
key: '', // AWS Access Key
|
||||
secret: '', // AWS Secret Token
|
||||
bucket: '' // The bucket you want to save into
|
||||
}
|
||||
});
|
||||
|
||||
gun.attach(app);
|
||||
|
@ -51,9 +51,12 @@
|
||||
</ul>
|
||||
<script>
|
||||
var gun = Gun(location.origin + '/gun');
|
||||
angular.module('admin', []).controller('editor', function($scope){
|
||||
angular.module('admin', []).controller('editor', function($scope){ //return;
|
||||
$scope.data = {};
|
||||
$scope.$data = gun.load('blob/data').on(function(data){
|
||||
$scope.$data = gun.load('example/angular/todo').blank(function(){
|
||||
console.log("Initializing Data!")
|
||||
gun.set({chicken: 'feet'}).key('example/angular/todo');
|
||||
}).on(function(data){
|
||||
Gun.obj.map(data, function(val, field){
|
||||
if(val === $scope.data[field]){ return }
|
||||
$scope.data[field] = val;
|
||||
@ -73,4 +76,4 @@
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
153
gun.js
153
gun.js
@ -280,18 +280,17 @@
|
||||
}
|
||||
Chain.key = function(key, cb){
|
||||
var gun = this;
|
||||
cb = cb || function(){};
|
||||
gun.shot.then(function(){
|
||||
cb = cb || function(){};
|
||||
if(Gun.obj.is(key)){ // if key is an object then we get the soul directly from it because the node might not exist in cache.
|
||||
if(Gun.obj.is(key)){ // if key is an object then we get the soul directly from it.
|
||||
Gun.obj.map(key, function(soul, field){ return key = field, cb.soul = soul });
|
||||
cb.node = gun.__.keys[key] = gun.__.graph[cb.soul]; // if it is cached, then it is important to reference it.
|
||||
} else { // else the node does exist in cache and we will get the soul from it instead, plus link the key.
|
||||
} else { // else let's get the soul directly from the node, plus link the key.
|
||||
cb.node = gun.__.keys[key] = gun._.node;
|
||||
}
|
||||
if(Gun.fns.is(gun.__.opt.hooks.key)){
|
||||
gun.__.opt.hooks.key(key, cb.soul || (cb.node||{_:{}})._[Gun._.soul], function(err, data){
|
||||
//Gun.log.call(gun, "key made", key);
|
||||
gun.__.keys[key] = cb.node; // once more for good luck.
|
||||
gun.__.keys[key] = cb.node || gun._.node; // once more for good luck.
|
||||
if(err){ return cb(err) }
|
||||
return cb(null);
|
||||
});
|
||||
@ -299,7 +298,9 @@
|
||||
Gun.log.call(gun, "Warning! You have no key hook!");
|
||||
}
|
||||
});
|
||||
if(!gun.back){ gun.shot('then').fire(gun._.node) }
|
||||
if(!gun.back){
|
||||
cb({err: "There exists nothing for the key to reference."});
|
||||
}
|
||||
return gun;
|
||||
}
|
||||
/*
|
||||
@ -321,7 +322,7 @@
|
||||
var gun = this.chain();
|
||||
path = (path || '').split('.');
|
||||
gun.back.shot.then(function trace(node){ // should handle blank and err! Err already handled?
|
||||
//console.log("shot path", path, node);
|
||||
console.log("path happening"); // MARK COME BACK HERE!!!
|
||||
gun.field = null;
|
||||
gun._.node = node;
|
||||
if(!path.length){ // if the path resolves to another node, we finish here.
|
||||
@ -339,8 +340,8 @@
|
||||
gun.shot('then').fire(val); // internals use this thus not frozen yet, but primitive values are passed as copies anyways in js.
|
||||
}
|
||||
});
|
||||
// if(!gun.back){ gun.shot('then').fire() } // replace below with this? maybe???
|
||||
if(gun.back && gun.back._ && gun.back._.loaded){
|
||||
if(gun.back && gun.back._ && gun.back._.loaded){ // is this causing a double trigger?
|
||||
console.log("path back");
|
||||
gun._.node = gun.back._.node;
|
||||
gun.back.shot('then').fire(gun.back._.node);
|
||||
}
|
||||
@ -349,7 +350,8 @@
|
||||
Chain.get = function(cb){
|
||||
var gun = this;
|
||||
gun.shot.then(function(val){
|
||||
console.log("did I get it?", val, gun);
|
||||
console.log("get happening", val);
|
||||
if(!gun._.node){ return } // I think this is safe?
|
||||
cb = cb || function(){};
|
||||
cb.call(gun, Gun.obj.is(val)? Gun.obj.copy(val) : val); // frozen copy
|
||||
});
|
||||
@ -358,8 +360,9 @@
|
||||
Chain.on = function(cb){
|
||||
var gun = this;
|
||||
gun.get(function(node){
|
||||
var get = this; // I'm not sure what state we're in, or which (get or gun) we should this-ify.
|
||||
cb.call(gun, Gun.obj.copy(node)); // frozen copy
|
||||
var get = this;
|
||||
cb = cb || function(){};
|
||||
cb.call(get, Gun.obj.copy(node)); // frozen copy
|
||||
get.__.on(get._.node._[Gun._.soul]).event(function(delta){
|
||||
if(!delta){ return }
|
||||
if(!get.field){
|
||||
@ -387,75 +390,67 @@
|
||||
*/
|
||||
Chain.set = function(val, cb, opt){ // TODO: need to turn deserializer into a trampolining function so stackoverflow doesn't happen.
|
||||
opt = opt || {};
|
||||
var gun = this, set;
|
||||
if(gun.field){ // field is always a string
|
||||
set = {}; // in case we are doing a set on a field, not on a node
|
||||
set[gun.field] = val; // we create a blank node with the field/value to be set
|
||||
val = set;
|
||||
} else
|
||||
if(!Gun.obj.is(val)){
|
||||
return cb({err: "No field exists to set the " + (typeof val) + " on."}), cb.root;
|
||||
}
|
||||
// TODO: should be able to handle val being a relation or a gun context or a gun promise.
|
||||
// TODO: BUG: IF we are setting an object, doing a partial merge, and they are reusing a frozen copy, we need to do a DIFF to update the HAM! Or else we'll get "old" HAM.
|
||||
val._ = Gun.ify.soul.call(gun, {}, gun._.node || val); // set their souls to be the same that way they will merge correctly for us during the union!
|
||||
cb = Gun.fns.is(cb)? cb : function(){};
|
||||
set = Gun.ify.call(gun, val);
|
||||
cb.root = set.root;
|
||||
console.log("chain.set root", cb.root);
|
||||
if(set.err){ return cb(set.err), gun }
|
||||
set = Gun.ify.state(set.nodes, Gun.time.is()); // set time state on nodes?
|
||||
if(set.err){ return cb(set.err), gun }
|
||||
gun.union(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.__.graph[cb.root._[Gun._.soul]] || cb.root;
|
||||
console.log("still rolling", gun._.node);
|
||||
// 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.hooks.set)){
|
||||
gun.__.opt.hooks.set(set.nodes, function(err, data){ // now iterate through those nodes to a persistence layer and get a callback once all are saved
|
||||
if(err){ return cb(err) }
|
||||
return cb(null);
|
||||
});
|
||||
} else {
|
||||
Gun.log.call(gun, "Warning! You have no persistence layer to save to!");
|
||||
}
|
||||
gun.shot.then(function(){ // set/key should cause a subscription, is this working yet?
|
||||
|
||||
var gun = this, set = {};
|
||||
gun.shot.then(function(){
|
||||
cb = Gun.fns.is(cb)? cb : function(){};
|
||||
if(gun.field){ // if a field exists, it should always be a string
|
||||
var partial = {}; // in case we are doing a set on a field, not on a node
|
||||
partial[gun.field] = val; // we create a blank node with the field/value to be set
|
||||
val = partial;
|
||||
} else
|
||||
if(!Gun.obj.is(val)){
|
||||
return cb({err: "No field exists to set the " + (typeof val) + " on."}), gun;
|
||||
}
|
||||
// TODO: should be able to handle val being a relation or a gun context or a gun promise.
|
||||
// TODO: BUG: IF we are setting an object, doing a partial merge, and they are reusing a frozen copy, we need to do a DIFF to update the HAM! Or else we'll get "old" HAM.
|
||||
val._ = Gun.ify.soul.call(gun, {}, gun._.node || val); // set their souls to be the same that way they will merge correctly for us during the union!
|
||||
set = Gun.ify.call(gun, val, set);
|
||||
cb.root = set.root;
|
||||
if(set.err || !cb.root){ return cb(set.err || {err: "No root object!"}), gun }
|
||||
set = Gun.ify.state(set.nodes, Gun.time.is()); // set time state on nodes?
|
||||
if(set.err){ return cb(set.err), gun }
|
||||
gun.union(set.nodes); // while this maybe should return a list of the nodes that were changed, we want to send the actual delta
|
||||
console.log(cb.root);
|
||||
gun._.node = gun.__.graph[cb.root._[Gun._.soul]] || 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.hooks.set)){
|
||||
gun.__.opt.hooks.set(set.nodes, function(err, data){ // now iterate through those nodes to a persistence layer and get a callback once all are saved
|
||||
if(err){ return cb(err) }
|
||||
return cb(null);
|
||||
});
|
||||
} else {
|
||||
Gun.log.call(gun, "Warning! You have no persistence layer to save to!");
|
||||
}
|
||||
});
|
||||
if(!gun.back){
|
||||
gun.shot('then').fire();
|
||||
console.log("gun.set() !gun.back fire()");
|
||||
gun.shot('then').fire(set);
|
||||
}
|
||||
return gun;
|
||||
}
|
||||
|
||||
Chain.insert = function(obj, cb, opt){
|
||||
var gun = this;
|
||||
if(!gun.back){
|
||||
console.log("no back!");
|
||||
gun = gun.set({});
|
||||
}
|
||||
console.log("back!!", gun);
|
||||
gun.shot.then(function(){
|
||||
opt = opt || {};
|
||||
cb = cb || function(){};
|
||||
var item = gun.chain().set(obj).get(function(val){
|
||||
var list = {}, soul = Gun.is.soul.on(val);
|
||||
console.log(val, 'has', soul);
|
||||
if(!soul){ return } // TODO: BUG!!! Handle this edge case!!!
|
||||
list[soul] = val;
|
||||
gun.set(list);
|
||||
});
|
||||
opt = opt || {};
|
||||
cb = cb || function(){};
|
||||
gun = gun.set({}); // insert assumes a graph node. So either create it or merge with the existing one.
|
||||
var error, item = Gun(null).set(obj, function(err){ // create the new item in its own context.
|
||||
error = err; // if this happens, it should get called before the .get
|
||||
}).get(function(val){
|
||||
if(error){ return cb(error) } // which in case it is, allows us to fail fast.
|
||||
var list = {}, soul = Gun.is.soul.on(val);
|
||||
console.log(val, 'has', soul);
|
||||
if(!soul){ return cb({err: "No soul!"}) }
|
||||
list[soul] = val; // other wise, let's then
|
||||
gun.set(list, cb); // merge with the graph node.
|
||||
});
|
||||
return gun;
|
||||
}
|
||||
/*
|
||||
Chain.map = function(cb, opt){
|
||||
var gun = this;
|
||||
gun.shot.then(function(val){
|
||||
cb = cb || function(){};
|
||||
opt = opt || {};
|
||||
Gun.obj.map(val, function(obj, soul){
|
||||
if(!Gun.is.soul(obj) && !opt.all){ return }
|
||||
Gun.obj.map(val, function(obj, soul){ // by default it only maps over nodes
|
||||
if(!Gun.is.soul(obj) && !opt.all){ return } // {all: true} maps over everything
|
||||
gun.load(obj).get(function(val){ // should map have support for blank?
|
||||
cb.call(this, obj, soul);
|
||||
});
|
||||
@ -463,7 +458,6 @@
|
||||
});
|
||||
return gun;
|
||||
}
|
||||
*/
|
||||
// Union is different than set. Set casts non-gun style of data into a gun compatible data.
|
||||
// Union takes already gun compatible data and validates it for a merge.
|
||||
// Meaning it is more low level, such that even set uses union internally.
|
||||
@ -499,10 +493,15 @@
|
||||
return context;
|
||||
}
|
||||
Chain.blank = function(blank){
|
||||
this._.blank = Gun.fns.is(blank)? blank : function(){};
|
||||
return this;
|
||||
var gun = this;
|
||||
gun._.blank = Gun.fns.is(blank)? blank : function(){};
|
||||
gun.shot.then(function(val){
|
||||
if(val === 0){ return }
|
||||
if(!val){ gun._.blank() }
|
||||
});
|
||||
return gun;
|
||||
}
|
||||
Chain.err = Chain.dud = function(dud){ // WARNING: dud will be depreciated in favor of err.
|
||||
Chain.err = function(dud){ // WARNING: dud was depreciated.
|
||||
this._.dud = Gun.fns.is(dud)? dud : function(){};
|
||||
return this;
|
||||
}
|
||||
@ -751,7 +750,8 @@
|
||||
}
|
||||
}({}));
|
||||
;(function(Serializer){
|
||||
Gun.ify = function(data){ // TODO: BUG: Modify lists to include HAM state
|
||||
Gun.ify = function(data, bind){ // TODO: BUG: Modify lists to include HAM state
|
||||
if(Gun.obj.map(bind, function(){ return true })){ return {err: "Bind must be an empty object."} }
|
||||
var gun = Gun.is(this)? this : {}
|
||||
, context = {
|
||||
nodes: {}
|
||||
@ -767,9 +767,10 @@
|
||||
return data;
|
||||
} else
|
||||
if(Gun.obj.is(data)){
|
||||
var value = {}, symbol = {}, seen
|
||||
var value = bind || {}, symbol = {}, seen
|
||||
, err = {err: "Metadata does not support external or circular references at " + sub.path, meta: true};
|
||||
context.root = context.root || value;
|
||||
bind = null;
|
||||
if(seen = ify.seen(context._seen, data)){
|
||||
//Gun.log.call(gun, "seen in _", sub._, sub.path, data);
|
||||
context.err = err;
|
||||
@ -899,7 +900,7 @@
|
||||
console.log("gun load", key);
|
||||
Gun.obj.map(gun.__.opt.peers, function(peer, url){
|
||||
request(url, null, function(err, reply){
|
||||
console.log('via', url, key, reply);
|
||||
//console.log('via', url, key, reply);
|
||||
if(err || !reply){ return } // handle reconnect?
|
||||
if(reply.body && reply.body.err){
|
||||
cb(reply.body.err);
|
||||
@ -975,14 +976,14 @@
|
||||
}
|
||||
tab.set.defer = {};
|
||||
request.createServer(function(req, res){
|
||||
console.log("client server received request", req);
|
||||
//console.log("client server received request", req);
|
||||
if(!req.body){ return }
|
||||
gun.union(req.body);
|
||||
});
|
||||
(function(){
|
||||
tab.store = {};
|
||||
var store = window.localStorage || {setItem: function(){}, removeItem: function(){}, getItem: function(){}};
|
||||
tab.store.set = function(key, val){console.log('setting', key); return store.setItem(key, Gun.text.ify(val)) }
|
||||
tab.store.set = function(key, val){ return store.setItem(key, Gun.text.ify(val)) }
|
||||
tab.store.get = function(key){ return Gun.obj.ify(store.getItem(key)) }
|
||||
tab.store.del = function(key){ return store.removeItem(key) }
|
||||
}());
|
||||
@ -1038,7 +1039,7 @@
|
||||
}catch(e){ return }
|
||||
if(!res){ return }
|
||||
if(res.wsrid){ (r.ws.cbs[res.wsrid]||function(){})(null, res) }
|
||||
console.log("We have a pushed message!", res);
|
||||
//console.log("We have a pushed message!", res);
|
||||
if(res.body){ r.createServer(res, function(){}) } // emit extra events.
|
||||
};
|
||||
ws.onerror = function(e){ console.log(e); };
|
||||
|
@ -12,7 +12,7 @@
|
||||
opt = opt || {};
|
||||
s.AWS.config.bucket = s.config.bucket = opt.bucket || opt.Bucket || s.config.bucket || process.env.AWS_S3_BUCKET;
|
||||
s.AWS.config.region = s.config.region = opt.region || s.config.region || process.env.AWS_REGION || "us-east-1";
|
||||
s.AWS.config.accessKeyId = s.config.accessKeyId = opt.key || opt.accessKeyId || s.config.accessKeyId || process.env.AWS_ACCESS_KEY_ID;
|
||||
s.AWS.config.accessKeyId = s.config.accessKeyId = opt.key = opt.key || opt.accessKeyId || s.config.accessKeyId || process.env.AWS_ACCESS_KEY_ID;
|
||||
s.AWS.config.secretAccessKey = s.config.secretAccessKey = opt.secret || opt.secretAccessKey || s.config.secretAccessKey || process.env.AWS_SECRET_ACCESS_KEY;
|
||||
if(s.config.fakes3 = s.config.fakes3 || opt.fakes3 || process.env.fakes3){
|
||||
s.AWS.config.endpoint = s.config.endpoint = opt.fakes3 || s.config.fakes3 || process.env.fakes3;
|
||||
|
16
lib/file.js
16
lib/file.js
@ -1,12 +1,18 @@
|
||||
// This was written by the wonderful Forrest Tait
|
||||
// twas not designed for production use
|
||||
// only simple local development.
|
||||
|
||||
var Gun = require('../gun');
|
||||
var fs = require('fs');
|
||||
var Gun = require('../gun'), file = {};
|
||||
|
||||
Gun.on('opt').event(function(gun, opts){
|
||||
if(!opts || (opts.s3 && opts.s3.key)){ return } // don't use this plugin if S3 is being used.
|
||||
|
||||
var fs = file.fs = file.fs || require('fs');
|
||||
var raw = file.raw = file.raw || fs.existsSync(opts.file || data.txt)?
|
||||
fs.readFileSync(opts.file || 'data.txt').toString()
|
||||
: null;
|
||||
var all = file.all = file.all || Gun.obj.ify(raw || {nodes: {}, keys: {}});
|
||||
|
||||
var raw = fs.existsSync(opts.file || data.txt) ? fs.readFileSync(opts.file || 'data.txt').toString() : null ;
|
||||
var all = Gun.obj.ify(raw || {nodes: {}, keys: {}});
|
||||
|
||||
gun.opt({hooks: {
|
||||
load: function(key, cb, options){
|
||||
if(Gun.obj.is(key) && key[Gun._.soul]){
|
||||
|
@ -3,6 +3,7 @@
|
||||
var S3 = require('./aws');
|
||||
|
||||
Gun.on('opt').event(function(gun, opt){
|
||||
if(!opt || !opt.s3){ return } // don't use S3 if it isn't specified.
|
||||
opt.s3 = opt.s3 || {};
|
||||
var s3 = gun.__.opt.s3 = gun.__.opt.s3 || S3(opt && opt.s3);
|
||||
s3.prefix = s3.prefix || opt.s3.prefix || '';
|
||||
|
@ -3,5 +3,6 @@
|
||||
var Gun = require('../gun');
|
||||
require('./s3');
|
||||
require('./wsp');
|
||||
require('./file');
|
||||
module.exports = Gun;
|
||||
}());
|
||||
}());
|
||||
|
@ -146,11 +146,9 @@
|
||||
if(!req || !req.url || !req.url.key || !Gun.obj.has(req.body, Gun._.soul)){ return }
|
||||
var load = {}, index = {}, soul;
|
||||
soul = load[Gun._.soul] = index[req.url.key] = req.body[Gun._.soul];
|
||||
gun.load(load, function(e,r){
|
||||
gun.key(index, function(err, reply){
|
||||
if(err){ return cb({headers: {'Content-Type': tran.json}, body: {err: err}}) }
|
||||
cb({headers: {'Content-Type': tran.json}, body: reply});
|
||||
});
|
||||
gun.load(load).key(index, function(err, reply){
|
||||
if(err){ return cb({headers: {'Content-Type': tran.json}, body: {err: err}}) }
|
||||
cb({headers: {'Content-Type': tran.json}, body: reply});
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user