lycabinet
Version:
A simple small JSON Object storage helper with good performance.
101 lines (94 loc) • 3.18 kB
text/typescript
/**
* Add a filter before save the storage.
* You should give a value to the options : includes & excludes.
* (Via to JSON hook)
* @param {*} Lycabinet
*/
import { DEBUG, deepClone, deepSupplement, is_Defined } from '../utils/util';
export function addFilter(Lycabinet){
const Proto = Lycabinet.prototype;
/**
* Set a filter by options
* Support dot `.` selection expression
* @param {Object} cabinetIns {includes: [], excludes:[] }
*/
Lycabinet.mixin(function(cabinetIns){
const opt = cabinetIns.options;
if(opt.includes || opt.excludes){
cabinetIns._once("mounted", ()=>{
cabinetIns.setFilter(); // auto set.
});
}
deepSupplement(opt, {
includes: [], // vacant equals to all!
excludes: [], // vacant equals to none.
});
});
Proto.setFilter = function(){
const _this = this;
Object.defineProperty(this.getCabinet(), 'toJSON', {
configurable: true,
enumerable: false, // hide in enumeration.
value: function(){
const cabinet = _this.getCabinet();
// set the basement includes.
const Includes = _this.options.includes;
const Excludes = _this.options.excludes;
return CustomFilter(cabinet, Includes, Excludes);
},
});
};
/**
* Allow you appointed the specific Storage Object and
* temporary Includes/Excludes options.
*/
Lycabinet.$filter = CustomFilter;
}
/**
* Helper Function.
*/
function CustomFilter(cabinet, Includes, Excludes){
let filtered = Object.create(null);
if(Includes.length>0){
let includesKeyMap: number[]= [];
Includes.forEach( (associatedKey,index)=>{
let current = includesKeyMap[index] = associatedKey.split(".");
let currentStore = cabinet;
let targetStore = filtered;
current.forEach((item, i )=>{
currentStore = currentStore[item];
// Compliment the non-final selection.
if( i +1 < current.length && is_Defined( currentStore )){
if(!is_Defined(targetStore[item]) )
targetStore[item] = {};
// else
// targetStore[item] = currentStore;
}else
targetStore[item] = currentStore;
targetStore = targetStore[item];
});
});
// if the configuration of `includes` option is not designed, it will mean exactly includes all by default.
}else Object.assign(filtered, cabinet);
// caculating the exclude filtering.
let excludesKeyMap: Array<number>= [];
let currentStore = deepClone(filtered);
Excludes.forEach( (associatedKey, index, arr)=>{
let current = excludesKeyMap[index] = associatedKey.split(".");
let pointer = currentStore;
for(let i=0; i<current.length; i++){
console.log({pointer, current: current[i]});
if(is_Defined(pointer[current[i]]) ){
// find the target.
if(i === current.length-1){
pointer[current[i]] = void 0;
}
// continue
pointer = pointer[current[i]];
}else
break ;
};
});
filtered = currentStore;
return filtered;
}