gun/src/get.js
2016-05-03 18:01:10 -07:00

73 lines
3.1 KiB
JavaScript

var Gun = require('./gun');
Gun.chain.get = (function(){
Gun.on('operating').event(function(gun, at){
if(!gun.__.by(at.soul).node){ gun.__.by(at.soul).node = gun.__.graph[at.soul] }
if(at.field){ return } // TODO: It would be ideal to reuse HAM's field emit.
gun.__.on(at.soul).emit(at);
});
Gun.on('get').event(function(gun, at, ctx, opt, cb){
if(ctx.halt){ return } // TODO: CLEAN UP with event emitter option?
at.change = at.change || gun.__.by(at.soul).node;
if(opt.raw){ return cb.call(opt.on, at) }
if(!ctx.cb.no){ cb.call(ctx.by.chain, null, Gun.obj.copy(ctx.node || gun.__.by(at.soul).node)) }
gun._.at('soul').emit(at).chain(opt.chain);
},0);
Gun.on('get').event(function(gun, at, ctx){
if(ctx.halt){ ctx.halt = false; return } // TODO: CLEAN UP with event emitter option?
}, Infinity);
return function(lex, cb, opt){ // get opens up a reference to a node and loads it.
var gun = this, ctx = {
opt: opt || {},
cb: cb || function(){},
lex: (Gun.text.is(lex) || Gun.num.is(lex))? Gun.is.rel.ify(lex) : lex,
};
ctx.force = ctx.opt.force;
if(cb !== ctx.cb){ ctx.cb.no = true }
if(!Gun.obj.is(ctx.lex)){ return ctx.cb.call(gun = gun.chain(), {err: Gun.log('Invalid get request!', lex)}), gun }
if(!(ctx.soul = ctx.lex[Gun._.soul])){ return ctx.cb.call(gun = this.chain(), {err: Gun.log('No soul to get!')}), gun } // TODO: With `.all` it'll be okay to not have an exact match!
ctx.by = gun.__.by(ctx.soul);
ctx.by.chain = ctx.by.chain || gun.chain();
function load(lex){
var soul = lex[Gun._.soul];
var cached = gun.__.by(soul).node || gun.__.graph[soul];
if(ctx.force){ ctx.force = false }
else if(cached){ return false }
wire(lex, stream, ctx.opt);
return true;
}
function stream(err, data, info){
//console.log("wire.get <--", err, data);
Gun.on('wire.get').emit(ctx.by.chain, ctx, err, data, info);
if(err){
Gun.log(err.err || err);
ctx.cb.call(ctx.by.chain, err);
return ctx.by.chain._.at('err').emit({soul: ctx.soul, err: err.err || err}).chain(ctx.opt.chain);
}
if(!data){
ctx.cb.call(ctx.by.chain, null);
return ctx.by.chain._.at('null').emit({soul: ctx.soul, not: true}).chain(ctx.opt.chain);
}
if(Gun.obj.empty(data)){ return }
if(err = Gun.union(ctx.by.chain, data).err){
ctx.cb.call(ctx.by.chain, err);
return ctx.by.chain._.at('err').emit({soul: Gun.is.node.soul(data) || ctx.soul, err: err.err || err}).chain(ctx.opt.chain);
}
}
function wire(lex, cb, opt){
Gun.on('get.wire').emit(ctx.by.chain, ctx, lex, cb, opt);
if(Gun.fns.is(gun.__.opt.wire.get)){ return gun.__.opt.wire.get(lex, cb, opt) }
if(!Gun.log.count('no-wire-get')){ Gun.log("Warning! You have no persistence layer to get from!") }
cb(null); // This is in memory success, hardly "success" at all.
}
function on(at){
if(on.ran = true){ ctx.opt.on = this }
if(load(ctx.lex)){ return }
Gun.on('get').emit(ctx.by.chain, at, ctx, ctx.opt, ctx.cb, ctx.lex);
}
ctx.opt.on = (ctx.opt.at || gun.__.at)(ctx.soul).event(on);
ctx.by.chain._.get = ctx.lex;
if(!ctx.opt.ran && !on.ran){ on.call(ctx.opt.on, {soul: ctx.soul}) }
return ctx.by.chain;
}
}());