mirror of
https://github.com/amark/gun.git
synced 2026-03-15 21:05:10 +00:00
Merge branch 'master' into feature-multicast
This commit is contained in:
18
lib/fsrm.js
Normal file
18
lib/fsrm.js
Normal file
@@ -0,0 +1,18 @@
|
||||
var fs = require('fs');
|
||||
var nodePath = require('path');
|
||||
|
||||
var dir = __dirname + '/../';
|
||||
|
||||
module.exports = function rm(path, full) {
|
||||
path = full || nodePath.join(dir, path);
|
||||
if(!fs.existsSync(path)){ return }
|
||||
fs.readdirSync(path).forEach(function(file,index){
|
||||
var curPath = path + "/" + file;
|
||||
if(fs.lstatSync(curPath).isDirectory()) { // recurse
|
||||
rm(null, curPath);
|
||||
} else { // delete file
|
||||
fs.unlinkSync(curPath);
|
||||
}
|
||||
});
|
||||
fs.rmdirSync(path);
|
||||
};
|
||||
412
lib/meta.js
412
lib/meta.js
@@ -1,73 +1,72 @@
|
||||
$(function(){
|
||||
var m = window.meta = {edit:[], os:{}}, ua = '', u;
|
||||
try{ua = navigator.userAgent.toLowerCase()}catch(e){}
|
||||
m.os.is = {
|
||||
win: (ua.search("win") >= 0)? "windows":false,
|
||||
lin: (ua.search("linux") >= 0)? "linux":false,
|
||||
mac: (ua.search("mac") >= 0)? "macintosh":false,
|
||||
and: (ua.search("android") >= 0)? "android":false,
|
||||
ios: (ua.search('ipod') >= 0
|
||||
|| ua.search('iphone') >= 0
|
||||
|| ua.search('ipad') >= 0)? "ios":false
|
||||
}
|
||||
var k = m.key = {ctrl: 17, cmd: 91};
|
||||
k.meta = (m.os.is.win||m.os.is.lin||m.os.is.and)? k.ctrl : k.cmd;
|
||||
var noop = function(){}, u;
|
||||
var m = window.meta = {edit:[]};
|
||||
var k = m.key = {};
|
||||
k.meta = {17:17, 91:17, 93:17, 224:17};
|
||||
k.down = function(eve){
|
||||
if($(eve.target).is('input') || eve.repeat){ return }
|
||||
(k.eve = m.eve = eve).which = eve.which || eve.fake || eve.keyCode;
|
||||
if(!eve.fake && eve.which === k.last){ return }
|
||||
if(k.meta === (k.last = eve.which)){ k.down.meta = m.flip(k.wipe()) || true }
|
||||
if(m.flip.is()){
|
||||
(k.combo || (k.combo = [])).push(eve.which);
|
||||
m.check('on', eve.which, k.at || (k.at = m.edit));
|
||||
if(eve.repeat){ return }
|
||||
var key = (k.eve = m.eve = eve).which = eve.which || eve.fake || eve.keyCode;
|
||||
if(!eve.fake && key === k.last){ return } k.last = key;
|
||||
if(!eve.fake && $(eve.target).closest('input, textarea, [contenteditable=true]').length){
|
||||
if(k.meta[key]){ k.down.meta = key = -1 }
|
||||
if(!k.down.meta){ return }
|
||||
}
|
||||
(k.combo || (k.combo = [])).push(key);
|
||||
m.check('on', key, k.at || (k.at = m.edit));
|
||||
if(k.meta[key]){
|
||||
m.list(k.at.back || m.edit);
|
||||
if(k.at && !k.at.back){ m.flip() }
|
||||
}
|
||||
if(eve.metaKey && (k.meta !== eve.which)){ k.up(eve) } // on some systems, meta hijacks keyup
|
||||
}
|
||||
k.up = function(eve){ var tmp;
|
||||
if($(eve.target).is('input')){ return }
|
||||
k.eve = m.eve = eve;
|
||||
k.last = null;
|
||||
eve.which = eve.which || eve.fake || eve.keyCode;
|
||||
if(m.flip.is()){ m.check('up', eve.which) }
|
||||
if(tmp = (k.meta === eve.which)){ k.down.meta = false }
|
||||
if(tmp && k.at === m.edit){ k.wipe() }
|
||||
if(27 === eve.which){ return m.flip(false) }
|
||||
}
|
||||
m.flip = function(tmp, aid){
|
||||
if(aid){
|
||||
m.flip.aid = true;
|
||||
setTimeout(function(){$(document).one('click',function(eve){m.flip(m.flip.aid = false)})},250); // ugly but important for visual aid.
|
||||
var key = (k.eve = m.eve = eve).which = eve.which || eve.fake || eve.keyCode;
|
||||
if(!eve.fake && $(eve.target).closest('input, textarea, [contenteditable=true]').length){
|
||||
if(k.meta[key]){
|
||||
k.down.meta = null;
|
||||
key = -1;
|
||||
} else
|
||||
if(!k.down.meta){ return }
|
||||
}
|
||||
k.last = null;
|
||||
if($(':focus').closest('#meta').length){ return }
|
||||
m.check('up', key);
|
||||
if(-1 === key || 27 === eve.which){ k.wipe() }
|
||||
}
|
||||
m.flip = function(tmp){
|
||||
var board = $('#meta .meta-menu');
|
||||
((tmp === false) || (!tmp && board.is(':visible')))?
|
||||
board.addClass('meta-none')
|
||||
: board.removeClass('meta-none');
|
||||
}
|
||||
m.flip.is = function(){
|
||||
if(m.flip.aid && ((m.eve||{}).fake || k.at !== m.edit)){ m.flip.aid = false }
|
||||
return !m.flip.aid && $('#meta .meta-menu').is(':visible');
|
||||
return $('#meta .meta-menu').is(':visible');
|
||||
}
|
||||
m.flip.wait = 500;
|
||||
m.check = function(how, key, at){
|
||||
at = k.at || m.edit;
|
||||
//m.list(at);
|
||||
var edit = at[key], tmp;
|
||||
var edit = at[key];
|
||||
if(!edit){ return }
|
||||
if(k.eve && k.eve.preventDefault){ k.eve.preventDefault() }
|
||||
var tmp = k.eve || noop;
|
||||
if(tmp.preventDefault){ tmp.preventDefault() }
|
||||
if(edit[how]){
|
||||
edit[how](m.eve);
|
||||
if(k.at !== m.edit && 'up' === how){
|
||||
if(k.down.meta){ m.list(k.at = m.edit) }
|
||||
else { k.wipe() }
|
||||
if(tmp.fake && !edit.fake){
|
||||
m.tap.edit = edit;
|
||||
} else {
|
||||
edit[how](m.eve);
|
||||
/*if(k.at !== m.edit && 'up' === how){
|
||||
if(k.down.meta){ m.list(k.at = m.edit) }
|
||||
else { k.wipe() }
|
||||
}*/
|
||||
}
|
||||
}
|
||||
if('up' != how){ return }
|
||||
edit.back = at;
|
||||
m.list(edit, at);
|
||||
if(at != edit){ edit.back = at }
|
||||
m.list(edit, true);
|
||||
}
|
||||
m.list = function(at){
|
||||
m.list = function(at, opt){
|
||||
if(!at){ return m.flip(false) }
|
||||
var l = [];
|
||||
$.each(at, function(i,k){ 'back' != i && k.combo && l.push(k) });
|
||||
$.each(at, function(i,k){ 'back' != i && k.combo && k.name && l.push(k) });
|
||||
if(!l.length){ return }
|
||||
k.at = at;
|
||||
l = l.sort(function(a,b){
|
||||
@@ -82,8 +81,10 @@ $(function(){
|
||||
$.each(l, function(i, k){
|
||||
$ul.append($('<li>').text(k.name));
|
||||
});
|
||||
if(!at.back){ return }
|
||||
$ul.append($('<li>').html('←').one('click', function(){ m.list(k.at = at.back) }));
|
||||
if(opt){ m.flip(true) }
|
||||
$ul.append($('<li>').html('←').one('click', function(){
|
||||
m.list(k.at = at.back);
|
||||
}));
|
||||
}
|
||||
m.ask = function(help, cb){
|
||||
var $ul = $('#meta .meta-menu ul').empty();
|
||||
@@ -96,34 +97,33 @@ $(function(){
|
||||
});
|
||||
var $li = $('<li>').append($form);
|
||||
$ul.append($li);
|
||||
m.flip(true);
|
||||
$put.focus();
|
||||
}
|
||||
k.wipe = function(){
|
||||
k.wipe = function(opt){
|
||||
k.down.meta = false;
|
||||
k.combo = [];
|
||||
m.flip(false);
|
||||
m.flip.aid = false;
|
||||
if(!opt){ m.flip(false) }
|
||||
m.list(k.at = m.edit);
|
||||
};
|
||||
$(document).on('keydown', k.down).on('keyup', k.up);
|
||||
m.tap = {};
|
||||
m.tap.select = function(eve){
|
||||
m.tap.range = null;
|
||||
if(!(m.tap.text()||'').trim()){
|
||||
if(m.tap.was){
|
||||
m.tap.was = null;
|
||||
m.flip(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
m.flip(m.tap.range = monotype((eve||{}).target), m.tap.was = true);
|
||||
}
|
||||
m.tap.text = function(tmp){
|
||||
return ((tmp = window.getSelection) && tmp().toString()) ||
|
||||
((tmp = document.selection) && tmp.createRange().text) || '';
|
||||
m.tap = function(){
|
||||
var on = $('.meta-on')
|
||||
.or($($(document.querySelectorAll(':hover')).get().reverse()).first())
|
||||
.or($(document.elementFromPoint(meta.tap.x, meta.tap.y)));
|
||||
return on;
|
||||
}
|
||||
$(window).on('blur', k.wipe).on('focus', k.wipe);
|
||||
$(document).on('select contextmenu keyup mouseup', '[contenteditable=true]', m.tap.select);
|
||||
//.on('keydown', '[contenteditable=true]', function(e){});
|
||||
$(document).on('mousedown mousemove mouseup', function(eve){
|
||||
m.tap.eve = eve;
|
||||
m.tap.x = eve.pageX||0;
|
||||
m.tap.y = eve.pageY||0;
|
||||
m.tap.on = $(eve.target);
|
||||
}).on('mousedown touchstart', function(eve){
|
||||
var tmp = m.tap.edit;
|
||||
if(!tmp || !tmp.on){ return }
|
||||
tmp.on(eve);
|
||||
m.tap.edit = null;
|
||||
});
|
||||
$(document).on('touchstart', '#meta .meta-start', function(eve){ m.tap.stun = true });
|
||||
$(document).on('click', '#meta .meta-menu li', function(eve){
|
||||
if(m.tap.stun){ return m.tap.stun = false }
|
||||
@@ -132,10 +132,11 @@ $(function(){
|
||||
k.down(eve);
|
||||
k.up(eve);
|
||||
});
|
||||
$(document).on('keydown', k.down).on('keyup', k.up);
|
||||
meta.edit = function(edit){
|
||||
var tmp = edit.combow = [];
|
||||
$.each(edit.combo || (edit.combo = []), function(i,k){
|
||||
if(!k || !k.length){ return }
|
||||
if(!k || !k.length){ if('number' == typeof k){ tmp.push(k) } return }
|
||||
tmp.push(k.toUpperCase().charCodeAt(0));
|
||||
});
|
||||
var at = meta.edit, l = edit.combo.length;
|
||||
@@ -143,37 +144,7 @@ $(function(){
|
||||
edit.combow = edit.combow.join(',');
|
||||
m.list(meta.edit);
|
||||
}
|
||||
meta.text = {zws: '​'};
|
||||
meta.text.editor = function(opt, as){ var tmp;
|
||||
if(!opt){ return }
|
||||
opt = (typeof opt == 'string')? {edit: opt} : opt.tag? opt : {tag: opt};
|
||||
var r = opt.range = opt.range || m.tap.range || monotype(), cmd = opt.edit;
|
||||
as = opt.as = opt.as || as;
|
||||
if(cmd && document.execCommand){
|
||||
r.restore();
|
||||
if(document.execCommand(cmd, null, as||null)){ return }
|
||||
}
|
||||
if(!opt.tag){ return }
|
||||
opt.tag = $(opt.tag);
|
||||
opt.name = opt.name || opt.tag.prop('tagName');
|
||||
if((tmp = $(r.get()).closest(opt.name)).length){
|
||||
if(r.s === r.e){
|
||||
tmp.after(meta.text.zws);
|
||||
r = r.select(monotype.next(tmp[0]),1);
|
||||
} else {
|
||||
tmp.contents().unwrap(opt.name);
|
||||
}
|
||||
} else
|
||||
if(r.s === r.e){
|
||||
r.insert(opt.tag);
|
||||
r = r.select(opt.tag);
|
||||
} else {
|
||||
r.wrap(opt.tag);
|
||||
}
|
||||
r.restore();
|
||||
opt.range = null;
|
||||
if(m.tap.range){ m.tap.range = monotype() }
|
||||
}
|
||||
$.fn.or = function(s){ return this.length ? this : $(s||'body') };
|
||||
;(function(){try{
|
||||
/* UI */
|
||||
if(meta.css){ return }
|
||||
@@ -199,10 +170,12 @@ $(function(){
|
||||
width: '2em',
|
||||
height: '2em',
|
||||
opacity: 0.7,
|
||||
outline: 'none',
|
||||
color: '#000044',
|
||||
overflow: 'visible',
|
||||
transition: 'all 0.2s ease-in'
|
||||
},
|
||||
'#meta *': {outline: 'none'},
|
||||
'#meta .meta-none': {display: 'none'},
|
||||
'#meta span': {'line-height': '2em'},
|
||||
'#meta .meta-menu': {
|
||||
@@ -263,98 +236,147 @@ $(function(){
|
||||
}
|
||||
}catch(e){}}());
|
||||
;(function(){
|
||||
// on fires when shortcut keydowns or on touch after command selected and then touchdown
|
||||
meta.edit({
|
||||
name: "Bold",
|
||||
combo: ['B'],
|
||||
on: function(e){
|
||||
meta.text.editor('bold');
|
||||
},
|
||||
up: function(){}
|
||||
});
|
||||
meta.edit({
|
||||
name: "Italic",
|
||||
combo: ['I'],
|
||||
on: function(e){
|
||||
meta.text.editor('italic');
|
||||
},
|
||||
up: function(){}
|
||||
});
|
||||
meta.edit({
|
||||
name: "Underline",
|
||||
combo: ['U'],
|
||||
on: function(e){
|
||||
meta.text.editor('underline');
|
||||
},
|
||||
up: function(){}
|
||||
});
|
||||
meta.edit({
|
||||
name: "linK",
|
||||
combo: ['K'],
|
||||
up: function(e){
|
||||
var range = meta.tap.range || monotype();
|
||||
meta.ask('Paste or type link...', function(url){
|
||||
meta.text.editor({tag: $('<a href="'+url+'">link</a>'), edit: url? 'createLink' : 'unlink', as: url, range: range});
|
||||
})
|
||||
},
|
||||
on: function(){}
|
||||
});
|
||||
meta.edit({name: "aliGn", combo: ['G']});
|
||||
meta.edit({
|
||||
name: "Left",
|
||||
combo: ['G','L'],
|
||||
on: function(e){ meta.text.editor('justifyLeft') },
|
||||
up: function(){}
|
||||
});
|
||||
meta.edit({
|
||||
name: "Right",
|
||||
combo: ['G','R'],
|
||||
on: function(e){ meta.text.editor('justifyRight') },
|
||||
up: function(){ }
|
||||
});
|
||||
meta.edit({
|
||||
name: "Middle",
|
||||
combo: ['G','M'],
|
||||
on: function(e){ meta.text.editor('justifyCenter') },
|
||||
up: function(){ }
|
||||
});
|
||||
meta.edit({
|
||||
name: "Justify",
|
||||
combo: ['G','J'],
|
||||
on: function(e){ meta.text.editor('justifyFull') },
|
||||
up: function(){}
|
||||
});
|
||||
// Align Number
|
||||
// Align Points
|
||||
// Align Strike
|
||||
meta.edit({name: "Size", combo: ['S']});
|
||||
meta.edit({
|
||||
name: "Small",
|
||||
combo: ['S','S'],
|
||||
on: function(e){ meta.text.editor('fontSize', 2) },
|
||||
up: function(){ }
|
||||
});
|
||||
meta.edit({
|
||||
name: "Normal",
|
||||
combo: ['S','N'],
|
||||
on: function(e){ meta.text.editor('fontSize', 5) },
|
||||
up: function(){}
|
||||
});
|
||||
meta.edit({
|
||||
name: "Header",
|
||||
combo: ['S','H'],
|
||||
on: function(e){ meta.text.editor('fontSize', 6) },
|
||||
up: function(){}
|
||||
});
|
||||
meta.edit({
|
||||
name: "Title",
|
||||
combo: ['S','T'],
|
||||
on: function(e){ meta.text.editor('fontSize', 7) },
|
||||
up: function(){}
|
||||
});
|
||||
// Size Spacing
|
||||
// Size Super
|
||||
// Size Sub
|
||||
meta.edit({name: "Edit", combo: ['E']});
|
||||
// include basic text editing by default.
|
||||
var monotype = window.monotype || function(){console.log("monotype needed")};
|
||||
var m = meta;
|
||||
m.text = {zws: '​'};
|
||||
m.text.on = function(eve){ var tmp;
|
||||
if($((eve||{}).target).closest('#meta').length){ return }
|
||||
m.text.range = null;
|
||||
if(!(m.text.copy()||'').trim()){
|
||||
m.flip(false);
|
||||
m.list(m.text.it);
|
||||
return;
|
||||
}
|
||||
m.text.range = monotype((eve||{}).target);
|
||||
m.text.it.on(eve);
|
||||
}
|
||||
m.text.copy = function(tmp){
|
||||
return ((tmp = window.getSelection) && tmp().toString()) ||
|
||||
((tmp = document.selection) && tmp.createRange().text) || '';
|
||||
}
|
||||
$(document).on('select contextmenu keyup mouseup', '[contenteditable=true]', m.text.on);
|
||||
m.text.editor = function(opt, as){ var tmp;
|
||||
if(!opt){ return }
|
||||
opt = (typeof opt == 'string')? {edit: opt} : opt.tag? opt : {tag: opt};
|
||||
var r = opt.range = opt.range || m.text.range || monotype(), cmd = opt.edit;
|
||||
as = opt.as = opt.as || as;
|
||||
if(cmd && document.execCommand){
|
||||
r.restore();
|
||||
if(document.execCommand(cmd, null, as||null)){
|
||||
if(m.text.range){ m.text.range = monotype() }
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(!opt.tag){ return }
|
||||
opt.tag = $(opt.tag);
|
||||
opt.name = opt.name || opt.tag.prop('tagName');
|
||||
if((tmp = $(r.get()).closest(opt.name)).length){
|
||||
if(r.s === r.e){
|
||||
tmp.after(m.text.zws);
|
||||
r = r.select(monotype.next(tmp[0]),1);
|
||||
} else {
|
||||
tmp.contents().unwrap(opt.name);
|
||||
}
|
||||
} else
|
||||
if(r.s === r.e){
|
||||
r.insert(opt.tag);
|
||||
r = r.select(opt.tag);
|
||||
} else {
|
||||
r.wrap(opt.tag);
|
||||
}
|
||||
r.restore();
|
||||
opt.range = null;
|
||||
if(m.text.range){ m.text.range = monotype() }
|
||||
}
|
||||
meta.edit(meta.text.it = {combo: [-1], on: function(){ m.list(this, true) }, back: meta.edit}); // -1 is key for typing.
|
||||
meta.text.it[-1] = meta.text.it;
|
||||
meta.edit({
|
||||
name: "Bold",
|
||||
combo: [-1,'B'], fake: -1,
|
||||
on: function(eve){
|
||||
meta.text.editor('bold');
|
||||
},
|
||||
up: function(){}
|
||||
});
|
||||
meta.edit({
|
||||
name: "Italic",
|
||||
combo: [-1,'I'], fake: -1,
|
||||
on: function(eve){
|
||||
meta.text.editor('italic');
|
||||
},
|
||||
up: function(){}
|
||||
});
|
||||
/*meta.edit({
|
||||
name: "Underline",
|
||||
combo: [-1,'U'], fake: -1,
|
||||
on: function(eve){
|
||||
meta.text.editor('underline');
|
||||
},
|
||||
up: function(){}
|
||||
});*/
|
||||
meta.edit({
|
||||
name: "linK",
|
||||
combo: [-1,'K'], fake: -1,
|
||||
on: function(eve){
|
||||
var range = meta.text.range || monotype();
|
||||
meta.ask('Paste or type link...', function(url){
|
||||
meta.text.editor({tag: $('<a href="'+url+'">link</a>'), edit: url? 'createLink' : 'unlink', as: url, range: range});
|
||||
})
|
||||
}
|
||||
});
|
||||
//meta.edit({name: "aliGn", combo: [-1,'G']}); // MOVE TO ADVANCED MENu!
|
||||
meta.edit({
|
||||
name: "Left",
|
||||
combo: [-1,'G','L'], fake: -1,
|
||||
on: function(eve){ meta.text.editor('justifyLeft') },
|
||||
up: function(){}
|
||||
});
|
||||
meta.edit({
|
||||
name: "Right",
|
||||
combo: [-1,'G','R'], fake: -1,
|
||||
on: function(eve){ meta.text.editor('justifyRight') },
|
||||
up: function(){ }
|
||||
});
|
||||
meta.edit({
|
||||
name: "Middle",
|
||||
combo: [-1,'G','M'], fake: -1,
|
||||
on: function(eve){ meta.text.editor('justifyCenter') },
|
||||
up: function(){ }
|
||||
});
|
||||
meta.edit({
|
||||
name: "Justify",
|
||||
combo: [-1,'G','J'], fake: -1,
|
||||
on: function(eve){ meta.text.editor('justifyFull') },
|
||||
up: function(){}
|
||||
});
|
||||
// Align Number
|
||||
// Align Points
|
||||
// Align Strike
|
||||
meta.edit({name: "Size", combo: [-1,'S'], on: function(){ m.list(this, true) }});
|
||||
meta.edit({
|
||||
name: "Small",
|
||||
combo: [-1,'S','S'], fake: -1,
|
||||
on: function(eve){ meta.text.editor('fontSize', 2) },
|
||||
up: function(){ }
|
||||
});
|
||||
meta.edit({
|
||||
name: "Normal",
|
||||
combo: [-1,'S','N'], fake: -1,
|
||||
on: function(eve){ meta.text.editor('fontSize', 5) },
|
||||
up: function(){}
|
||||
});
|
||||
meta.edit({
|
||||
name: "Header",
|
||||
combo: [-1,'S','H'], fake: -1,
|
||||
on: function(eve){ meta.text.editor('fontSize', 6) },
|
||||
up: function(){}
|
||||
});
|
||||
meta.edit({
|
||||
name: "Title",
|
||||
combo: [-1,'S','T'], fake: -1,
|
||||
on: function(eve){ meta.text.editor('fontSize', 7) },
|
||||
up: function(){}
|
||||
});
|
||||
}());
|
||||
});
|
||||
@@ -29,12 +29,13 @@
|
||||
hierarchy: ['div', 'pre', 'ol', 'ul', 'li',
|
||||
'h1', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'a', // block
|
||||
'b', 'code', 'i', 'span', 's', 'sub', 'sup', 'u', // inline
|
||||
'br'] // empty
|
||||
'br', 'img'] // empty
|
||||
,tags: {
|
||||
'a': {attrs:{'href':1}, exclude:{'a':1}},
|
||||
'b': {exclude:{'b':1,'p':1}},
|
||||
'br': {empty: 1},
|
||||
'i': {exclude:{'i':1,'p':1}},
|
||||
'img': {attrs:{'src':1}, empty: 1},
|
||||
'span': {exclude:{'p':1,'ul':1,'ol':1,'li':1,'br':1}},
|
||||
's': {space:1},
|
||||
'u': {exclude:{'u':1,'p':1},space:1},
|
||||
@@ -138,12 +139,17 @@
|
||||
return $(($(e)[0]||{})[d]);
|
||||
}
|
||||
|
||||
var xssattr = /[^a-z:]/ig, xssjs = /javascript:/ig;
|
||||
// url("javascript: // and all permutations
|
||||
// stylesheets can apparently have XSS?
|
||||
|
||||
// create key val attributes object from elements attributes
|
||||
function attrsAsObj(e, filterCb){
|
||||
var attrObj = {};
|
||||
(e = $(e)) && e.length && $(e[0].attributes||[]).each(function(value,name){
|
||||
name = name.nodeName||name.name;
|
||||
value = e.attr(name);
|
||||
if(value.replace(xssattr,'').match(xssjs)){ e.removeAttr(name); return }
|
||||
value = filterCb? filterCb(value,name,e) : value;
|
||||
if(value !== undefined && value !== false)
|
||||
attrObj[name] = value;
|
||||
|
||||
135
lib/radisk.js
135
lib/radisk.js
@@ -5,15 +5,21 @@
|
||||
opt = opt || {};
|
||||
opt.log = opt.log || console.log;
|
||||
opt.file = String(opt.file || 'radata');
|
||||
var has = (Radisk.has || (Radisk.has = {}))[opt.file];
|
||||
if(has){ return has }
|
||||
|
||||
opt.pack = opt.pack || (opt.memory? (opt.memory * 1000 * 1000) : 1399000000) * 0.3; // max_old_space_size defaults to 1400 MB.
|
||||
opt.until = opt.until || opt.wait || 9;
|
||||
opt.batch = opt.batch || 10 * 1000;
|
||||
opt.until = opt.until || opt.wait || 250;
|
||||
opt.batch = opt.batch || (10 * 1000);
|
||||
opt.chunk = opt.chunk || (1024 * 1024 * 10); // 10MB
|
||||
opt.code = opt.code || {};
|
||||
opt.code.from = opt.code.from || '!';
|
||||
//opt.jsonify = true; // TODO: REMOVE!!!!
|
||||
|
||||
function ename(t){ return encodeURIComponent(t).replace(/\*/g, '%2A') }
|
||||
function atomic(v){ return u !== v && (!v || 'object' != typeof v) }
|
||||
var map = Gun.obj.map;
|
||||
var LOG = false;
|
||||
|
||||
if(!opt.store){
|
||||
return opt.log("ERROR: Radisk needs `opt.store` interface with `{get: fn, put: fn (, list: fn)}`!");
|
||||
@@ -36,25 +42,29 @@
|
||||
var r = function(key, val, cb){
|
||||
key = ''+key;
|
||||
if(val instanceof Function){
|
||||
var o = cb;
|
||||
cb = val;
|
||||
val = r.batch(key);
|
||||
if(u !== val){
|
||||
cb(u, val, o);
|
||||
if(atomic(val)){ return }
|
||||
// if a node is requested and some of it is cached... the other parts might not be.
|
||||
return cb(u, val);
|
||||
}
|
||||
if(r.thrash.at){
|
||||
val = r.thrash.at(key);
|
||||
if(u !== val){
|
||||
cb(u, val, o);
|
||||
if(atomic(val)){ cb(u, val, o); return }
|
||||
// if a node is requested and some of it is cached... the other parts might not be.
|
||||
return cb(u, val);
|
||||
}
|
||||
}
|
||||
return r.read(key, cb);
|
||||
return r.read(key, cb, o);
|
||||
}
|
||||
r.batch(key, val);
|
||||
if(cb){ r.batch.acks.push(cb) }
|
||||
if(++r.batch.ed >= opt.batch){ return r.thrash() } // (2)
|
||||
clearTimeout(r.batch.to); // (1)
|
||||
if(r.batch.to){ return }
|
||||
//clearTimeout(r.batch.to); // (1) // THIS LINE IS EVIL! NEVER USE IT! ALSO NEVER DELETE THIS SO WE NEVER MAKE THE SAME MISTAKE AGAIN!
|
||||
r.batch.to = setTimeout(r.thrash, opt.until || 1);
|
||||
}
|
||||
|
||||
@@ -73,9 +83,11 @@
|
||||
r.batch = Radix();
|
||||
r.batch.acks = [];
|
||||
r.batch.ed = 0;
|
||||
//var id = Gun.text.random(2), S = (+new Date); console.log("<<<<<<<<<<<<", id);
|
||||
r.save(batch, function(err, ok){
|
||||
if(++i > 1){ return }
|
||||
if(++i > 1){ opt.log('RAD ERR: Radisk has callbacked multiple times, please report this as a BUG at github.com/amark/gun/issues ! ' + i); return }
|
||||
if(err){ opt.log('err', err) }
|
||||
//console.log(">>>>>>>>>>>>", id, ((+new Date) - S), batch.acks.length);
|
||||
map(batch.acks, function(cb){ cb(err, ok) });
|
||||
thrash.at = null;
|
||||
thrash.ing = false;
|
||||
@@ -90,7 +102,7 @@
|
||||
4. Read the previous file to that into memory
|
||||
5. Scan through the in memory radix for all values lexically less than the limit.
|
||||
6. Merge and write all of those to the in-memory file and back to disk.
|
||||
7. If file to large, split. More details needed here.
|
||||
7. If file too large, split. More details needed here.
|
||||
*/
|
||||
r.save = function(rad, cb){
|
||||
var s = function Span(){};
|
||||
@@ -136,28 +148,32 @@
|
||||
Therefore it is unavoidable that a read will have to happen,
|
||||
the question is just how long you delay it.
|
||||
*/
|
||||
r.write = function(file, rad, cb, force){
|
||||
r.write = function(file, rad, cb, o){
|
||||
o = ('object' == typeof o)? o : {force: o};
|
||||
var f = function Fractal(){};
|
||||
f.text = '';
|
||||
f.count = 0;
|
||||
f.file = file;
|
||||
f.each = function(val, key, k, pre){
|
||||
//console.log("RAD:::", JSON.stringify([val, key, k, pre]));
|
||||
if(u !== val){ f.count++ }
|
||||
if(opt.pack <= (val||'').length){ return cb("Record too big!"), true }
|
||||
var enc = Radisk.encode(pre.length) +'#'+ Radisk.encode(k) + (u === val? '' : ':'+ Radisk.encode(val)) +'\n';
|
||||
if((opt.chunk < f.text.length + enc.length) && (1 < f.count) && !force){
|
||||
if((opt.chunk < f.text.length + enc.length) && (1 < f.count) && !o.force){
|
||||
f.text = '';
|
||||
f.limit = Math.ceil(f.count/2);
|
||||
f.count = 0;
|
||||
f.sub = Radix();
|
||||
Radix.map(rad, f.slice)
|
||||
Radix.map(rad, f.slice);
|
||||
return true;
|
||||
}
|
||||
f.text += enc;
|
||||
}
|
||||
f.write = function(){
|
||||
var tmp = ename(file);
|
||||
var start; LOG && (start = (+new Date)); // comment this out!
|
||||
opt.store.put(tmp, f.text, function(err){
|
||||
LOG && console.log("wrote JSON in", (+new Date) - start); // comment this out!
|
||||
if(err){ return cb(err) }
|
||||
r.list.add(tmp, cb);
|
||||
});
|
||||
@@ -168,7 +184,7 @@
|
||||
var name = f.file;
|
||||
f.file = key;
|
||||
f.count = 0;
|
||||
r.write(name, f.sub, f.next, force);
|
||||
r.write(name, f.sub, f.next, o);
|
||||
return true;
|
||||
}
|
||||
f.sub(key, val);
|
||||
@@ -177,51 +193,73 @@
|
||||
if(err){ return cb(err) }
|
||||
f.sub = Radix();
|
||||
if(!Radix.map(rad, f.slice)){
|
||||
r.write(f.file, f.sub, cb, force);
|
||||
r.write(f.file, f.sub, cb, o);
|
||||
}
|
||||
}
|
||||
if(opt.jsonify){ return r.write.jsonify(f, file, rad, cb, o) } // temporary testing idea
|
||||
if(!Radix.map(rad, f.each, true)){ f.write() }
|
||||
}
|
||||
|
||||
r.write.jsonify = function(f, file, rad, cb, o){
|
||||
var raw;
|
||||
var start; LOG && (start = (+new Date)); // comment this out!
|
||||
try{raw = JSON.stringify(rad.$);
|
||||
}catch(e){ return cb("Record too big!") }
|
||||
LOG && console.log("stringified JSON in", (+new Date) - start); // comment this out!
|
||||
if(opt.chunk < raw.length && !o.force){
|
||||
if(Radix.map(rad, f.each, true)){ return }
|
||||
}
|
||||
f.text = raw;
|
||||
f.write();
|
||||
}
|
||||
|
||||
;(function(){
|
||||
var Q = {};
|
||||
r.read = function(key, cb, next){
|
||||
if(RAD && !next){ // cache
|
||||
r.read = function(key, cb, o){
|
||||
o = o || {};
|
||||
if(RAD && !o.next){ // cache
|
||||
var val = RAD(key);
|
||||
if(u !== val){
|
||||
//if(u !== val){
|
||||
//cb(u, val, o);
|
||||
if(atomic(val)){ cb(u, val, o); return }
|
||||
// if a node is requested and some of it is cached... the other parts might not be.
|
||||
return cb(u, val);
|
||||
}
|
||||
//}
|
||||
}
|
||||
var g = function Get(){}, tmp;
|
||||
g.lex = function(file){
|
||||
file = (u === file)? u : decodeURIComponent(file);
|
||||
if(!file || file > (next || key)){
|
||||
if(next){ g.file = file }
|
||||
if(!file || file > (o.next || key)){
|
||||
if(o.next){ g.file = file }
|
||||
if(tmp = Q[g.file]){
|
||||
tmp.push({key: key, ack: cb, file: g.file});
|
||||
tmp.push({key: key, ack: cb, file: g.file, opt: o});
|
||||
return true;
|
||||
}
|
||||
Q[g.file] = [{key: key, ack: cb, file: g.file}];
|
||||
Q[g.file] = [{key: key, ack: cb, file: g.file, opt: o}];
|
||||
r.parse(g.file, g.it);
|
||||
return true;
|
||||
}
|
||||
g.file = file;
|
||||
}
|
||||
g.it = function(err, disk){
|
||||
g.it = function(err, disk, info){
|
||||
if(g.err = err){ opt.log('err', err) }
|
||||
g.info = info;
|
||||
if(disk){ RAD = g.disk = disk }
|
||||
disk = Q[g.file]; delete Q[g.file];
|
||||
map(disk, g.ack);
|
||||
}
|
||||
g.ack = function(as){
|
||||
if(!as.ack){ return }
|
||||
var tmp = as.key, rad = g.disk || noop, data = rad(tmp), last = rad.last;
|
||||
if(data){ as.ack(g.err, data) }
|
||||
else if(!as.file){ return as.ack(g.err, u) }
|
||||
if(!last || last === tmp){ return as.ack(g.err, u) } // is this correct?
|
||||
if(last > tmp && 0 > last.indexOf(tmp)){ return as.ack(g.err, u) }
|
||||
r.read(tmp, as.ack, as.file);
|
||||
var tmp = as.key, o = as.opt, info = g.info, rad = g.disk || noop, data = rad(tmp), last = rad.last;
|
||||
o.parsed = (o.parsed || 0) + (info.parsed||0);
|
||||
o.chunks = (o.chunks || 0) + 1;
|
||||
if(!o.some){ o.some = (u !== data) }
|
||||
if(u !== data){ as.ack(g.err, data, o) }
|
||||
else if(!as.file){ !o.some && as.ack(g.err, u, o); return }
|
||||
if(/*!last || */last === tmp){ !o.some && as.ack(g.err, u, o); return }
|
||||
if(last && last > tmp && 0 != last.indexOf(tmp)){ !o.some && as.ack(g.err, u, o); return }
|
||||
if(o.some && o.parsed >= o.limit){ return }
|
||||
o.next = as.file;
|
||||
r.read(tmp, as.ack, o);
|
||||
}
|
||||
r.list(g.lex);
|
||||
}
|
||||
@@ -236,14 +274,13 @@
|
||||
Then we can work on the harder problem of being multi-process.
|
||||
*/
|
||||
var Q = {}, s = String.fromCharCode(31);
|
||||
r.parse = function(file, cb){ var q;
|
||||
r.parse = function(file, cb, raw){ var q;
|
||||
if(q = Q[file]){ return q.push(cb) } q = Q[file] = [cb];
|
||||
var p = function Parse(){};
|
||||
var p = function Parse(){}, info = {};
|
||||
p.disk = Radix();
|
||||
p.read = function(err, data){ var tmp;
|
||||
delete Q[file];
|
||||
if((p.err = err) || (p.not = !data)){
|
||||
//return cb(err, u);//map(q, p.ack);
|
||||
return map(q, p.ack);
|
||||
}
|
||||
if(typeof data !== 'string'){
|
||||
@@ -251,12 +288,34 @@
|
||||
if(opt.pack <= data.length){
|
||||
p.err = "Chunk too big!";
|
||||
} else {
|
||||
data = data.toString();
|
||||
data = data.toString(); // If it crashes, it crashes here. How!?? We check size first!
|
||||
}
|
||||
}catch(e){ p.err = e }
|
||||
if(p.err){ return map(q, p.ack) }
|
||||
}
|
||||
info.parsed = data.length;
|
||||
|
||||
var start; LOG && (start = (+new Date)); // keep this commented out in production!
|
||||
if(opt.jsonify){ // temporary testing idea
|
||||
try{
|
||||
var json = JSON.parse(data);
|
||||
p.disk.$ = json;
|
||||
LOG && console.log('parsed JSON in', (+new Date) - start); // keep this commented out in production!
|
||||
map(q, p.ack);
|
||||
return;
|
||||
}catch(e){ tmp = e }
|
||||
if('{' === data[0]){
|
||||
p.err = tmp || "JSON error!";
|
||||
return map(q, p.ack);
|
||||
}
|
||||
}
|
||||
|
||||
var start; LOG && (start = (+new Date)); // keep this commented out in production!
|
||||
var tmp = p.split(data), pre = [], i, k, v;
|
||||
if(!tmp || 0 !== tmp[1]){
|
||||
p.err = "File '"+file+"' does not have root radix! ";
|
||||
return map(q, p.ack);
|
||||
}
|
||||
while(tmp){
|
||||
k = v = u;
|
||||
i = tmp[1];
|
||||
@@ -274,6 +333,7 @@
|
||||
if(u !== k && u !== v){ p.disk(pre.join(''), v) }
|
||||
tmp = p.split(tmp[2]);
|
||||
}
|
||||
LOG && console.log('parsed JSON in', (+new Date) - start); // keep this commented out in production!
|
||||
//cb(err, p.disk);
|
||||
map(q, p.ack);
|
||||
};
|
||||
@@ -290,9 +350,10 @@
|
||||
}
|
||||
p.ack = function(cb){
|
||||
if(!cb){ return }
|
||||
if(p.err || p.not){ return cb(p.err, u) }
|
||||
cb(u, p.disk);
|
||||
if(p.err || p.not){ return cb(p.err, u, info) }
|
||||
cb(u, p.disk, info);
|
||||
}
|
||||
if(raw){ return p.read(null, raw) }
|
||||
opt.store.get(ename(file), p.read);
|
||||
}
|
||||
}());
|
||||
@@ -315,8 +376,11 @@
|
||||
return cb(u, 1);
|
||||
}
|
||||
dir(file, true);
|
||||
cb.listed = (cb.listed || 0) + 1;
|
||||
r.write(f, dir, function(err, ok){
|
||||
if(err){ return cb(err) }
|
||||
cb.listed = (cb.listed || 0) - 1;
|
||||
if(cb.listed !== 0){ return }
|
||||
cb(u, 1);
|
||||
}, true);
|
||||
}
|
||||
@@ -353,6 +417,7 @@
|
||||
}());
|
||||
|
||||
var noop = function(){}, RAD, u;
|
||||
Radisk.has[opt.file] = r;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
53
lib/radix.js
53
lib/radix.js
@@ -5,9 +5,9 @@
|
||||
key = ''+key;
|
||||
if(!t && u !== val){
|
||||
radix.last = (key < radix.last)? radix.last : key;
|
||||
radix.sort = null;
|
||||
delete (radix.$||{})[_];
|
||||
}
|
||||
t = t || radix[_] || (radix[_] = {});
|
||||
t = t || radix.$ || (radix.$ = {});
|
||||
var i = 0, l = key.length-1, k = key[i], at, tmp;
|
||||
while(!(at = t[k]) && i < l){
|
||||
k += key[++i];
|
||||
@@ -15,9 +15,9 @@
|
||||
if(!at){
|
||||
if(!map(t, function(r, s){
|
||||
var ii = 0, kk = '';
|
||||
while(s[ii] == key[ii]){
|
||||
if((s||'').length){ while(s[ii] == key[ii]){
|
||||
kk += s[ii++];
|
||||
}
|
||||
} }
|
||||
if(kk){
|
||||
if(u === val){
|
||||
if(ii <= l){ return }
|
||||
@@ -25,47 +25,52 @@
|
||||
}
|
||||
var __ = {};
|
||||
__[s.slice(ii)] = r;
|
||||
(__[key.slice(ii)] = {})[$] = val;
|
||||
(t[kk] = {})[_] = __;
|
||||
ii = key.slice(ii);
|
||||
('' === ii)? (__[''] = val) : ((__[ii] = {})[''] = val);
|
||||
t[kk] = __;
|
||||
delete t[s];
|
||||
return true;
|
||||
}
|
||||
})){
|
||||
if(u === val){ return; }
|
||||
(t[k] || (t[k] = {}))[$] = val;
|
||||
(t[k] || (t[k] = {}))[''] = val;
|
||||
}
|
||||
if(u === val){
|
||||
return tmp;
|
||||
}
|
||||
} else
|
||||
if(i == l){
|
||||
if(u === val){ return (u === (tmp = at[$]))? at[_] : tmp }
|
||||
at[$] = val;
|
||||
if(u === val){ return (u === (tmp = at['']))? at : tmp }
|
||||
at[''] = val;
|
||||
} else {
|
||||
if(u !== val){ at.sort = null }
|
||||
return radix(key.slice(++i), val, at[_] || (at[_] = {}));
|
||||
if(u !== val){ delete at[_] }
|
||||
return radix(key.slice(++i), val, at || (at = {}));
|
||||
}
|
||||
}
|
||||
return radix;
|
||||
};
|
||||
|
||||
Radix.map = function map(radix, cb, opt, pre){ pre = pre || [];
|
||||
var t = radix[_] || radix, keys = radix.sort || (radix.sort = Object.keys(t).sort()), i = 0, l = keys.length;
|
||||
for(;i < l; i++){ var key = keys[i], tree = t[key], tmp;
|
||||
if(u !== (tmp = tree[$])){
|
||||
tmp = cb(tmp, pre.join('') + key, key, pre);
|
||||
var t = ('function' == typeof radix)? radix.$ || {} : radix;
|
||||
if(!t){ return }
|
||||
var keys = (t[_]||no).sort || (t[_] = function $(){ $.sort = Object.keys(t).sort(); return $ }()).sort;
|
||||
//var keys = Object.keys(t).sort();
|
||||
var i = 0, l = keys.length;
|
||||
for(;i < l; i++){ var key = keys[i], tree = t[key], tmp, p;
|
||||
if(!tree || '' === key || _ === key){ continue }
|
||||
p = pre.slice(); p.push(key);
|
||||
if(u !== (tmp = tree[''])){
|
||||
tmp = cb(tmp, p.join(''), key, pre);
|
||||
if(u !== tmp){ return tmp }
|
||||
} else
|
||||
} else
|
||||
if(opt){
|
||||
cb(u, pre.join(''), key, pre);
|
||||
}
|
||||
if(tmp = tree[_]){
|
||||
pre.push(key);
|
||||
tmp = map(tree, cb, opt, pre);
|
||||
//tmp = map(tmp, cb, opt, pre);
|
||||
tmp = cb(u, pre.join(''), key, pre);
|
||||
if(u !== tmp){ return tmp }
|
||||
pre.pop();
|
||||
}
|
||||
pre = p;
|
||||
tmp = map(tree, cb, opt, pre);
|
||||
if(u !== tmp){ return tmp }
|
||||
pre.pop();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -80,6 +85,6 @@
|
||||
}
|
||||
|
||||
var map = Gun.obj.map, no = {}, u;
|
||||
var $ = String.fromCharCode(30), _ = String.fromCharCode(29);
|
||||
var _ = String.fromCharCode(24);
|
||||
|
||||
}());
|
||||
@@ -3,6 +3,7 @@ var Gun = (typeof window !== "undefined")? window.Gun : require('../gun');
|
||||
function Store(opt){
|
||||
opt = opt || {};
|
||||
opt.file = String(opt.file || 'radata');
|
||||
if(Gun.TESTING){ opt.file = 'radatatest' }
|
||||
var fs = require('fs'), u;
|
||||
var store = function Store(){};
|
||||
|
||||
|
||||
142
lib/rindexed.js
142
lib/rindexed.js
@@ -9,115 +9,47 @@
|
||||
function Store(opt){
|
||||
opt = opt || {};
|
||||
opt.file = String(opt.file || 'radata');
|
||||
var db = null;
|
||||
if(Gun.TESTING){ opt.file = 'radatatest' }
|
||||
opt.chunk = opt.chunk || (1024 * 1024); // 1MB
|
||||
var db = null, u;
|
||||
|
||||
opt.indexedDB = opt.indexedDB || window.indexedDB;
|
||||
// Initialize indexedDB. Version 1.
|
||||
var request = opt.indexedDB.open(opt.file, 1)
|
||||
try{opt.indexedDB = opt.indexedDB || indexedDB}catch(e){}
|
||||
try{if(!opt.indexedDB || 'file:' == location.protocol){
|
||||
var store = {}, s = {};
|
||||
store.put = function(f, d, cb){ s[f] = d; cb(null, 1) };
|
||||
store.get = function(f, cb){ cb(null, s[f] || u) };
|
||||
console.log('Warning: No indexedDB exists to persist data to!');
|
||||
return store;
|
||||
}}catch(e){}
|
||||
|
||||
var store = function Store(){};
|
||||
store.start = function(){
|
||||
var o = indexedDB.open(opt.file, 1);
|
||||
o.onupgradeneeded = function(eve){ (eve.target.result).createObjectStore(opt.file) }
|
||||
o.onsuccess = function(){ db = o.result }
|
||||
o.onerror = function(eve){ console.log(eve||1); }
|
||||
}; store.start();
|
||||
|
||||
// Create schema. onupgradeneeded is called only when DB is first created or when the DB version increases.
|
||||
request.onupgradeneeded = function(event){
|
||||
var db = event.target.result;
|
||||
db.createObjectStore(opt.file);
|
||||
store.put = function(key, data, cb){
|
||||
if(!db){ setTimeout(function(){ store.put(key, data, cb) },1); return }
|
||||
var tx = db.transaction([opt.file], 'readwrite');
|
||||
var obj = tx.objectStore(opt.file);
|
||||
var req = obj.put(data, ''+key);
|
||||
req.onsuccess = obj.onsuccess = tx.onsuccess = function(){ cb(null, 1) }
|
||||
req.onabort = obj.onabort = tx.onabort = function(eve){ cb(eve||'put.tx.abort') }
|
||||
req.onerror = obj.onerror = tx.onerror = function(eve){ cb(eve||'put.tx.error') }
|
||||
}
|
||||
|
||||
// onsuccess is called when the DB is ready.
|
||||
request.onsuccess = function(){
|
||||
db = request.result;
|
||||
store.get = function(key, cb){
|
||||
if(!db){ setTimeout(function(){ store.get(key, cb) },9); return }
|
||||
var tx = db.transaction([opt.file], 'readonly');
|
||||
var obj = tx.objectStore(opt.file);
|
||||
var req = obj.get(''+key);
|
||||
req.onsuccess = function(){ cb(null, req.result) }
|
||||
req.onabort = function(eve){ cb(eve||4) }
|
||||
req.onerror = function(eve){ cb(eve||5) }
|
||||
}
|
||||
|
||||
request.onerror = function(event){
|
||||
console.log('ERROR: RAD IndexedDB generic error:', event);
|
||||
};
|
||||
|
||||
var store = function Store(){}, u;
|
||||
|
||||
store.put = function(file, data, cb){
|
||||
cb = cb || function(){};
|
||||
var doPut = function(){
|
||||
// Start a transaction. The transaction will be automaticallt closed when the last success/error handler took no new action.
|
||||
var transaction = db.transaction([opt.file], 'readwrite');
|
||||
|
||||
// Add or update data.
|
||||
var radStore = transaction.objectStore(opt.file);
|
||||
var putRequest = radStore.put(data, file);
|
||||
putRequest.onsuccess = radStore.onsuccess = transaction.onsuccess = function(){
|
||||
//console.log('RAD IndexedDB put transaction was succesful.');
|
||||
cb(null, 1);
|
||||
};
|
||||
putRequest.onabort = radStore.onabort = transaction.onabort = function(){
|
||||
var es = 'ERROR: RAD IndexedDB put transaction was aborted.';
|
||||
console.log(es);
|
||||
cb(es, undefined);
|
||||
};
|
||||
putRequest.onerror = radStore.onerror = transaction.onerror = function(event){
|
||||
var es = 'ERROR: RAD IndexedDB put transaction was in error: ' + JSON.stringify(event)
|
||||
console.log(es);
|
||||
cb(es, undefined);
|
||||
};
|
||||
}
|
||||
if(!db){
|
||||
waitDbReady(doPut, 100, function(){
|
||||
var es = 'ERROR: Timeout: RAD IndexedDB not ready.';
|
||||
console.log(es);
|
||||
cb(es, undefined);
|
||||
}, 10)
|
||||
} else {
|
||||
doPut();
|
||||
}
|
||||
};
|
||||
|
||||
store.get = function(file, cb){
|
||||
cb = cb || function(){};
|
||||
var doGet = function(){
|
||||
// Start a transaction. The transaction will be automaticallt closed when the last success/error handler took no new action.
|
||||
var transaction = db.transaction([opt.file], 'readwrite');
|
||||
|
||||
// Read data.
|
||||
var radStore = transaction.objectStore(opt.file);
|
||||
var getRequest = radStore.get(file);
|
||||
getRequest.onsuccess = function(){
|
||||
//console.log('RAD IndexedDB get transaction was succesful.');
|
||||
cb(null, getRequest.result);
|
||||
};
|
||||
getRequest.onabort = function(){
|
||||
var es = 'ERROR: RAD IndexedDB get transaction was aborted.';
|
||||
console.log(es);
|
||||
cb(es, undefined);
|
||||
};
|
||||
getRequest.onerror = function(event){
|
||||
var es = 'ERROR: RAD IndexedDB get transaction was in error: ' + JSON.stringify(event)
|
||||
console.log(es);
|
||||
cb(es, undefined);
|
||||
};
|
||||
}
|
||||
if(!db){
|
||||
waitDbReady(doGet, 100, function(){
|
||||
var es = 'ERROR: Timeout: RAD IndexedDB not ready.';
|
||||
console.log(es);
|
||||
cb(es, undefined);
|
||||
}, 10)
|
||||
} else {
|
||||
doGet();
|
||||
}
|
||||
};
|
||||
|
||||
var waitDbReady = function(readyFunc, checkInterval, timeoutFunc, timeoutSecs){
|
||||
var startTime = new Date();
|
||||
var checkFunc = function(){
|
||||
if(db){
|
||||
readyFunc();
|
||||
} else {
|
||||
if((new Date() - startTime) / 1000 >= timeoutSecs){
|
||||
timeoutFunc();
|
||||
} else {
|
||||
setTimeout(checkFunc, checkInterval);
|
||||
}
|
||||
}
|
||||
};
|
||||
checkFunc();
|
||||
};
|
||||
|
||||
setInterval(function(){ db && db.close(); db = null; store.start() }, 1000 * 15); // reset webkit bug?
|
||||
return store;
|
||||
}
|
||||
|
||||
@@ -126,4 +58,4 @@
|
||||
} else {
|
||||
module.exports = Store;
|
||||
}
|
||||
}());
|
||||
}());
|
||||
27
lib/rls.js
Normal file
27
lib/rls.js
Normal file
@@ -0,0 +1,27 @@
|
||||
;(function(){
|
||||
var Gun = (typeof window !== "undefined")? window.Gun : require('../gun');
|
||||
|
||||
Gun.on('create', function(root){
|
||||
this.to.next(root);
|
||||
root.opt.store = root.opt.store || Store(root.opt);
|
||||
});
|
||||
|
||||
function Store(opt){
|
||||
opt = opt || {};
|
||||
opt.file = String(opt.file || 'radata');
|
||||
if(Gun.TESTING){ opt.file = 'radatatest' }
|
||||
var store = function Store(){};
|
||||
|
||||
var ls = localStorage;
|
||||
store.put = function(key, data, cb){ ls[''+key] = data; cb(null, 1) }
|
||||
store.get = function(key, cb){ cb(null, ls[''+key]) }
|
||||
|
||||
return store;
|
||||
}
|
||||
|
||||
if(Gun.window){
|
||||
Gun.window.RlocalStorage = Store;
|
||||
} else {
|
||||
module.exports = Store;
|
||||
}
|
||||
}());
|
||||
@@ -8,8 +8,8 @@ Gun.on('create', function(root){
|
||||
this.to.next(root);
|
||||
var opt = root.opt;
|
||||
if(!process.env.AWS_S3_BUCKET){ return }
|
||||
opt.batch = opt.batch || (1000 * 1);
|
||||
opt.until = opt.until || (1000 * 15);
|
||||
opt.batch = opt.batch || (1000 * 10);
|
||||
opt.until = opt.until || (1000 * 3);
|
||||
opt.chunk = opt.chunk || (1024 * 1024 * 10); // 10MB
|
||||
|
||||
try{AWS = require('aws-sdk');
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var dot = /\.\.+/g;
|
||||
var slash = /\/\/+/g;
|
||||
|
||||
function CDN(dir){
|
||||
return function(req, res){
|
||||
req.url = (req.url||'').replace(dot,'').replace(slash,'/');
|
||||
if(serve(req, res)){ return } // filters GUN requests!
|
||||
fs.createReadStream(path.join(dir, req.url)).on('error',function(tmp){ // static files!
|
||||
try{ tmp = fs.readFileSync(path.join(dir, 'index.html')) }catch(e){}
|
||||
|
||||
138
lib/store.js
138
lib/store.js
@@ -1,58 +1,86 @@
|
||||
var Gun = (typeof window !== "undefined")? window.Gun : require('../gun');
|
||||
|
||||
|
||||
Gun.on('create', function(root){
|
||||
this.to.next(root);
|
||||
var opt = root.opt, u;
|
||||
if(false === opt.radisk){ return }
|
||||
var Radisk = (Gun.window && Gun.window.Radisk) || require('./radisk');
|
||||
var Radix = Radisk.Radix;
|
||||
|
||||
opt.store = opt.store || (!Gun.window && require('./rfs')(opt));
|
||||
var rad = Radisk(opt), esc = String.fromCharCode(27);
|
||||
|
||||
root.on('put', function(msg){
|
||||
this.to.next(msg);
|
||||
var id = msg['#'], track = !msg['@'], acks = track? 0 : u; // only ack non-acks.
|
||||
if(msg.rad && !track){ return } // don't save our own acks
|
||||
Gun.graph.is(msg.put, null, function(val, key, node, soul){
|
||||
if(track){ ++acks }
|
||||
val = Radisk.encode(val, null, esc)+'>'+Radisk.encode(Gun.state.is(node, key), null, esc);
|
||||
rad(soul+'.'+key, val, (track? ack : u));
|
||||
});
|
||||
function ack(err, ok){
|
||||
acks--;
|
||||
if(ack.err){ return }
|
||||
if(ack.err = err){
|
||||
root.on('in', {'@': id, err: err});
|
||||
return;
|
||||
}
|
||||
if(acks){ return }
|
||||
root.on('in', {'@': id, ok: 1});
|
||||
}
|
||||
});
|
||||
|
||||
root.on('get', function(msg){
|
||||
this.to.next(msg);
|
||||
var id = msg['#'], soul = msg.get['#'], key = msg.get['.']||'', tmp = soul+'.'+key, node;
|
||||
rad(tmp, function(err, val){
|
||||
if(val){
|
||||
if(val && typeof val !== 'string'){
|
||||
if(key){
|
||||
val = u;
|
||||
} else {
|
||||
Radix.map(val, each)
|
||||
}
|
||||
}
|
||||
if(!node && val){ each(val, key) }
|
||||
}
|
||||
root.on('in', {'@': id, put: Gun.graph.node(node), err: err? err : u, rad: Radix});
|
||||
});
|
||||
function each(val, key){
|
||||
tmp = val.lastIndexOf('>');
|
||||
var state = Radisk.decode(val.slice(tmp+1), null, esc);
|
||||
val = Radisk.decode(val.slice(0,tmp), null, esc);
|
||||
node = Gun.state.ify(node, key, state, val, soul);
|
||||
}
|
||||
});
|
||||
|
||||
this.to.next(root);
|
||||
var opt = root.opt, u;
|
||||
if(false === opt.radisk){ return }
|
||||
var Radisk = (Gun.window && Gun.window.Radisk) || require('./radisk');
|
||||
var Radix = Radisk.Radix;
|
||||
|
||||
opt.store = opt.store || (!Gun.window && require('./rfs')(opt));
|
||||
var rad = Radisk(opt), esc = String.fromCharCode(27);
|
||||
|
||||
root.on('put', function(msg){
|
||||
this.to.next(msg);
|
||||
var id = msg['#'] || Gun.text.random(3), track = !msg['@'], acks = track? 0 : u; // only ack non-acks.
|
||||
if(msg.rad && !track){ return } // don't save our own acks
|
||||
Gun.graph.is(msg.put, null, function(val, key, node, soul){
|
||||
if(track){ ++acks }
|
||||
//console.log('put:', soul, key, val);
|
||||
val = Radisk.encode(val, null, esc)+'>'+Radisk.encode(Gun.state.is(node, key), null, esc);
|
||||
rad(soul+esc+key, val, (track? ack : u));
|
||||
});
|
||||
function ack(err, ok){
|
||||
acks--;
|
||||
if(ack.err){ return }
|
||||
if(ack.err = err){
|
||||
root.on('in', {'@': id, err: err});
|
||||
return;
|
||||
}
|
||||
if(acks){ return }
|
||||
//console.log("PAT!", id);
|
||||
root.on('in', {'@': id, ok: 1});
|
||||
}
|
||||
});
|
||||
|
||||
root.on('get', function(msg){
|
||||
this.to.next(msg);
|
||||
var id = msg['#'], get = msg.get, soul = msg.get['#'], has = msg.get['.']||'', opt = {}, graph, lex, key, tmp;
|
||||
if(typeof soul == 'string'){
|
||||
key = soul;
|
||||
} else
|
||||
if(soul){
|
||||
if(tmp = soul['*']){ opt.limit = 1 }
|
||||
key = tmp || soul['='];
|
||||
}
|
||||
if(key && !opt.limit){ // a soul.has must be on a soul, and not during soul*
|
||||
if(typeof has == 'string'){
|
||||
key = key+esc+(opt.atom = has);
|
||||
} else
|
||||
if(has){
|
||||
if(tmp = has['*']){ opt.limit = 1 }
|
||||
if(key){ key = key+esc + (tmp || (opt.atom = has['='])) }
|
||||
}
|
||||
}
|
||||
if((tmp = get['%']) || opt.limit){
|
||||
opt.limit = (tmp <= (opt.pack || (1000 * 100)))? tmp : 1;
|
||||
}
|
||||
//var start = (+new Date); // console.log("GET!", id, JSON.stringify(key));
|
||||
rad(key||'', function(err, data, o){
|
||||
if(data){
|
||||
if(typeof data !== 'string'){
|
||||
if(opt.atom){
|
||||
data = u;
|
||||
} else {
|
||||
Radix.map(data, each)
|
||||
}
|
||||
}
|
||||
if(!graph && data){ each(data, '') }
|
||||
}
|
||||
//console.log("GOT!", id, JSON.stringify(key), ((+new Date) - start));
|
||||
root.on('in', {'@': id, put: graph, err: err? err : u, rad: Radix});
|
||||
}, opt);
|
||||
function each(val, has, a,b){
|
||||
if(!val){ return }
|
||||
has = (key+has).split(esc);
|
||||
var soul = has.slice(0,1)[0];
|
||||
has = has.slice(-1)[0];
|
||||
opt.count = (opt.count || 0) + val.length;
|
||||
tmp = val.lastIndexOf('>');
|
||||
var state = Radisk.decode(val.slice(tmp+1), null, esc);
|
||||
val = Radisk.decode(val.slice(0,tmp), null, esc);
|
||||
(graph = graph || {})[soul] = Gun.state.ify(graph[soul], has, state, val, soul);
|
||||
if(opt.limit && opt.limit <= opt.count){ return true }
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -11,19 +11,7 @@ var write = function(path, data){
|
||||
return fs.writeFileSync(nodePath.join(dir, path), data);
|
||||
}
|
||||
|
||||
var rm = function(path, full) {
|
||||
path = full || nodePath.join(dir, path);
|
||||
if(!fs.existsSync(path)){ return }
|
||||
fs.readdirSync(path).forEach(function(file,index){
|
||||
var curPath = path + "/" + file;
|
||||
if(fs.lstatSync(curPath).isDirectory()) { // recurse
|
||||
rm(null, curPath);
|
||||
} else { // delete file
|
||||
fs.unlinkSync(curPath);
|
||||
}
|
||||
});
|
||||
fs.rmdirSync(path);
|
||||
};
|
||||
var rm = require('./fsrm');
|
||||
|
||||
var mk = function(path){
|
||||
path = nodePath.join(dir, path);
|
||||
|
||||
Reference in New Issue
Block a user