UNPKG

lycabinet

Version:

A simple small JSON Object storage helper with good performance.

2 lines 14.9 kB
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("Lycabinet",[],e):"object"==typeof exports?exports.Lycabinet=e():t.Lycabinet=e()}(self,(function(){return(()=>{"use strict";var t={d:(e,o)=>{for(var n in o)t.o(o,n)&&!t.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:o[n]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e)},e={};t.d(e,{default:()=>O});const o=function(t,e){return void 0===t[e=(t.length+e)%t.length]&&d&&console.error(`The index ${e} in array ${t.toString()} is overflowed!`),t[e]};function n(t,e){let o=t,n="";for(let t=0;t<e.length;t++)if(n=e[t],o=o&&o[n],void 0===o)return;return o}const r=(()=>{const t=[];return window.addEventListener("storage",(e=>{t.forEach((t=>{t(e)}))}),!1),(e,o=!1)=>{o?f(t,e):t.push(e)}})(),i=function(...t){let e;return t.reduce(((t,o)=>{for(let e in o)t[e]&&u(t[e])?i(t[e],o[e]):t[e]=o[e];return e=t,t}),t[0]),e},s=function(t,e,o=null){for(let n in e)t[n]&&u(t[n])?s(t[n],e[n]):t[n]=o?o(t[n],e[n]):e[n];return t};function a(t,e){if(!t)return e;let o=null;for(let n in e)if(o=t[n],l(o)){if(!u(o))continue;a(o,e[n])}else t[n]=e[n];return t}function c(t,e=Object.create(null),o=!0){if(u(t)){var n=e;for(var r in t)n[r]=c(t[r]);return n}return h(t)?t.slice():o&&g(t)?Object.create(t.prototype).constructor:t}const l=t=>null!=t,u=t=>"[object Object]"===Object.prototype.toString.call(t),h=t=>Array.isArray&&Array.isArray(t)||t instanceof Array||"object"==typeof t&&"Array"===Object.prototype.toString.call(t).slice(-6,-1),g=t=>t instanceof Function;var f=(t,e)=>{if(t.length){let o=t.indexOf(e);if(o>-1)return t.splice(o,1)}};const _="[Lycabinet]: ",d=!1,p="idle",y="loading";function b(t,e,o){let n=Object.create(null);if(e.length>0){let o=[];e.forEach(((e,r)=>{let i=o[r]=e.split("."),s=t,a=n;i.forEach(((t,e)=>{s=s[t],e+1<i.length&&l(s)?l(a[t])||(a[t]={}):a[t]=s,a=a[t]}))}))}else Object.assign(n,t);let r=[],i=c(n);return o.forEach(((t,e,o)=>{let n=r[e]=t.split("."),s=i;for(let t=0;t<n.length&&(console.log({pointer:s,current:n[t]}),l(s[n[t]]));t++)t===n.length-1&&(s[n[t]]=void 0),s=s[n[t]]})),n=i,n}let v=null;function m(t,e=!0,o=!1){const n=[],r=t=>{n.unshift(t);for(let e in t)u(t[e])&&r(t[e])};return r(t),n.forEach(((t,n,r)=>{for(let i in t)u(t[i])&&(r[n][i]=S(t[i],e,o))})),S(t,e,o)}function S(t,e=!1,o=!0){let n=Object.create(null);n._parent=null,n.triggers=[],n.value=t;const r={enumerable:!1,configurable:!0,writable:!1},i=t=>n.triggers.push(t),s=t=>f(n.triggers,t),a=["$addListener","$removeListener"];a.forEach(((t,e)=>{n[t]={value:null},Object.defineProperty(n,t,{value:e?s:i,...r})}));const c=n.value;return new Proxy(t,{get:(t,e,o)=>(d&&console.info("Getted",t,e,o,n),a.indexOf(e)>-1?n[e]:c[e]),set(t,r,i,s){d&&console.info("Setted",t,r,s,n);const a=c[r];if(e?u(i)&&(c[r]=o?S(i,!1,!0):m(i,e,!1)):c[r]=i,i!==a){let t=n.triggers;for(let e=0;e<t.length;e++){if(!g(t[e]))throw new Error("The get proxy handler listener added in target is Not a Function which type is "+typeof t[e]);t[e](r,i,a)}null!==v&&v()}return!0}})}const L="cabinetSyncTabs";function w(...t){this.__init.apply(this,t)}!function(t){const e=Object.create(null);d&&(window.__cabinet=e);const o=t.prototype;o.getCabinet=function(){return this.__storage},o.isIdentical=function(){return this.__storage===e[this.__root]},o.hasStore=function(){return l(e[this.__root])&&u(e[this.__root])},o.getStore=function(){return e[this.__root]},o.setStore=function(t){e[this.__root]=t},o.removeStore=function(){return!(this.options.useSharedCabinet||!this.options.shareCabinet||!this.isIdentical()||(e[this.__root]=void 0,0))},t.$removeStore=function(t){e[t]=void 0},d&&(t.$getStore=function(t){return e[t]})}(w),function(t){t.prototype._mixins=[],t.mixin=function(e){return t.prototype._mixins.push(e),this},t.prototype.__install=function(...e){e.unshift(this),t.prototype._mixins.forEach((t=>{t.apply(t,e)}))}}(w),function(t){let e=null;t.mixin((function(n){let r=null;n!==e&&(r=Object.create(null)),e=n,n._on=function(t,e){if(d&&!g(e))throw new Error("[Laction]:The second parameter of _on method must be a callback function!");r||(r=Object.create(null)),(r[t]||(r[t]=[])).push(e)},n._off=function(t,e){const o=r[t]||(r[t]=[]);f(o,e)},n._trigger=function(t,...e){const n=r[t]||(r[t]=[]);n.counter||(n.counter=0),n.counter++;const i=[];let s=n.length;e.push(i);for(let t=0;t<s;t++){let o=n[t].apply(this,e);l(o)&&i.push(o),s!==n.length&&(t--,s=n.length)}return i.length>0?o(i,-1):e.length>1?o(e,-2):null},n._once=function(t,e,o=0){const n=r[t]||(r[t]=[]);if(n.counter&&!1!==o&&~~o<=n.counter)e(n.counter);else{var i=function(...o){e.apply(this,o),this._off(t,i)};this._on(t,i)}},n._isHappend=function(t,e=0){return(r[t]||(r[t]=[])).counter>e},n._setlog=function(){return!!t.DEBUG&&(new Set(Object.keys(r).concat(["created","mounted","beforeLoad","beforeLocalLoad","localLoaded","loaded","loadFromCache","storageSync","setItem","writeLock","writeBackflow","getItem","removeItem","lazySave","beforeSave","beforeLocalSave","localSaved","saved","busy","beforeClear","beforeLocalClear","localCleared","cleared","error","destroyed"])).forEach((e=>{let o=r[e]&&r[e]._logHandle;o&&this._off(e,o);const n=()=>{t.DEBUG&&console.log(`[Lycabinet${t.SeparateLog?"-"+this.__root:""}]:Triggered the event: '${e}'`)};this._on(e,n),r[e]._logHandle=n})),!0)}}))}(w),function(t){t.DEBUG=!0,t.SeparateLog=!1;const e=t.prototype;e.__init=function(t,e={}){if(e.initStorage&&!u(e.initStorage))throw new Error(`${_}The type of the provided option "initStorage" must be an Object!`);if("string"!=typeof(o=t)||o.constructor!=String)throw new Error(`${_}The param "root" should be an string, than type ${typeof t}!`);var o;this.__root=(t||"lycabinet")+"";const n={root:this.__root,autoload:!0,lazyPeriod:~~e.lazyPeriod||5e3,saveMutex:!0,autoLazy:!0,logEvent:!1,useSharedCabinet:!0,shareCabinet:!0,deepMerge:!1,customMerge:null,localInterface:{database:window.localStorage,getItem:"getItem",setItem:"setItem",removeItem:"removeItem"},concurrent:!!(e.outerLoad||e.outerSave||e.outerClear),outerLoad:null,outerSave:null,outerClear:null};this.options=i(n,e),this.__install(n),n.logEvent&&this._setlog(),this.status="created",this._trigger("created"),n.autoload&&this._init(e.initStorage||Object.create(null))},e._init=function(t=null){t=t||this.options.initStorage||Object.create(null);const e=function(){var t;(t=this.__tempStorage)&&(h(t)?t.length:Object.keys(t).length)&&(i(this.__storage,this.__tempStorage),this.__tempStorage=Object.create(null),this._trigger("writeBackflow"))};this._on("loaded",e),this._on("cleared",e);const o=this.options.useSharedCabinet&&this.hasStore();return o?(this.__storage=this.getStore(),Object.assign(t,this.__storage),this._trigger("loadFromCache")):(this.__storage=this.__storage||t,this.options.shareCabinet&&this.setStore(this.__storage)),this.status="mounted",this._trigger("mounted"),o?this.status=p:this.options.autoload?this.load():this.status=p,this},e.isVacant=function(){return this.status===p},e.set=function(t,e){return[y,"clearing"].indexOf(this.status)>-1?(this._trigger("writeLock"),this.__tempStorage=this.__tempStorage||(this.__tempStorage=Object.create(null)),this.__tempStorage[t]=e,this):(this.__storage[t]=e,this._trigger("setItem",t,e),this)},e.get=function(t){let e=this.__storage[t];return this._trigger("getItem",t,e),e},e.remove=function(t){let e=!1;var o,n;return n=t=>{this.__storage.hasOwnProperty(t)&&(this.set(t,void 0),e=!0)},(o=t).forEach?o.forEach(n):n(o),e&&this._trigger("removeItem",t,e),this},e.clear=function(t={}){const e=l(t.concurrent)?t.concurrent:this.options.concurrent,o=l(t.onCloud)?t.onCloud:!!this.options.outerClear;this.status=y,this._trigger("beforeClear");let n=()=>{const t=o&&!e;if(this._trigger("beforeLocalClear",t),t)return d&&console.log(`${_}The local clear action is ignored by options: concurrent:false.`),this;const n=this.options.localInterface;n.database[n.removeItem](this.__root),this._trigger("localCleared",this.__root)};const r=n=>{this.status=p,this._trigger("cleared",o,e),t.onceDone&&t.onceDone(n,o)},i=[this.__root,this.__storage],s=()=>{r(!0)},a=(t,e="cloudClearings")=>{r(!1),!0!==this._trigger("error","clear",e)&&o&&console.error(`${_}Failed tfo Clear the cabinet "${this.__root}" on cloud. ${t}`)};try{t.reset&&Reflect.ownKeys(this.__storage).forEach((t=>{delete this.__storage[t]})),n(),o?this.options.outerClear(i,s,a):r(!0)}catch(t){a(t,"unknown")}return this},e.load=function(t={}){const e=l(t.concurrent)?t.concurrent:this.options.concurrent,o=l(t.onCloud)?t.onCloud:!!this.options.outerLoad,n=l(t.deepMerge)?~~t.deepMerge:this.options.deepMerge;this.status=y,this._trigger("beforeLoad");let r=()=>{let r=null;const a=o&&!e;if(this._trigger("beforeLocalLoad",a),a)return d&&console.log("${LogToken}The local load action is ignored by options: concurrent=false."),this;const c=this.options.localInterface;let l=c.database[c.getItem](this.__root);l=this._trigger("localLoaded",l),r=JSON.parse(l),n?t.disableMerge?i(this.__storage,r):s(this.__storage,r,this.options.customMerge):Object.assign(this.__storage,r)};const a=n=>{this.status=p,this._trigger("loaded",o,e),t.onceDone&&t.onceDone(n,o)},c=[this.__root,this.__storage],h=e=>{if(!l(e)||!u(e))throw new Error(`${_}Load cabinet with empty 'data' which type is ${typeof e}`);n?t.disableMerge?i(this.__storage,e):s(this.__storage,e,this.options.customMerge):Object.assign(this.__storage,e),a(!0)},g=(t,e="cloudLoadings")=>{a(!1),!0!==this._trigger("error","load",e)&&o&&console.error(`${_}Failed to Load the cabinet "${this.__root}" on cloud. ${t}`)};try{r(),o?this.options.outerLoad(c,h,g):a(!0)}catch(t){g(t,"unknown")}return this},e.save=function(t={}){const e=l(t.onCloud)?t.onCloud:!!this.options.outerSave,o=l(t.concurrent)?t.concurrent:this.options.concurrent;let n=this.options.saveMutex&&!this.isVacant();if(this._trigger("beforeSave",n),n)return d&&console.log(`${_}The 'save' manipulation is deserted for busy. Current Status: ${this.status} .Set 'saveMutex' false to disable it.`),this._trigger("busy",this.status),this.options.autoLazy&&this.lazySave(e,o),this;this.status="saving";let r=()=>{const t=e&&!o;if(this._trigger("beforeLocalSave",t),t)return d&&console.log("${LogToken}The local save action is ignored by options: concurrent=false."),this;let n=JSON.stringify(this.__storage);n=this._trigger("localSaved",n);const r=this.options.localInterface;r.database[r.setItem](this.__root,n)};const i=n=>{this.status=p,this._trigger("saved",e,o),t.onceDone&&t.onceDone(n,e)},s=[this.__root,this.__storage],a=()=>{i(!0)},c=(t,o="cloudSavings")=>{i(!1),!0!==this._trigger("error","save",o)&&e&&console.error(`${_}Failed to Save the cabinet "${this.__root}" on cloud. ${t}`)};try{r(),e?this.options.outerSave(s,a,c):i(!0)}catch(t){c(t,"unknown")}return this},e.forEach=function(t){let e;const o=this.__storage;for(let n in o)e=o[n],t(e,n,o);return this},e.map=function(t){let e;const o=this.__storage;for(let n in o)e=o[n],o[n]=t(e,n,o);return this},e.destroy=function(t=!0){t&&(this.clear({reset:!0,onCloud:!1,concurrent:!1}),this.removeStore()),this.status="destroyed",this._trigger("destroyed")}}(w),function(t){var e;t.prototype.lazySave=(e=0,function(...t){var o=(new Date).getTime();let n=o-e>5e3;return this._trigger("lazySave",n),n&&(e=o,d&&console.log("Lazy executed!",o,e,n),this.save(...t)),this}),t.prototype.lazySet=function(t,e,...o){return this.set(t,e).lazySave(...o),this}}(w),function(t){t.install=function(e,o){t.mixin((function(t){a(t.options,{useLaction:{lazyOrbitId:-1}});let o=t.__root+"_lazy";const n=e.testHookName(o,!0);t.getLazyKey=()=>n,t._lazyKey=n,e.registerHook({name:n,once:!0,debounce:!0,action:(...e)=>{t.save(...e)}}),t._on("destroyed",(()=>{e.unregisterHook(n)}))})),t.prototype.lazySave=function(...t){return t.unshift(this._lazyKey),e.bubble(t,this.options.useLaction.lazyOrbitId,!1),this._trigger("lazySave"),this}}}(w),function(t){const e=t.prototype;e.delete=e.remove,e.read=e.get,e.storage=e.getCabinet,e.isConsistent=e.isIdentical}(w),function(t){const e=t.prototype;t.mixin((function(t){const e=t.options;(e.includes||e.excludes)&&t._once("mounted",(()=>{t.setFilter()})),a(e,{includes:[],excludes:[]})})),e.setFilter=function(){const t=this;Object.defineProperty(this.getCabinet(),"toJSON",{configurable:!0,enumerable:!1,value:function(){return b(t.getCabinet(),t.options.includes,t.options.excludes)}})},t.$filter=b}(w),function(t){const e=t.prototype;e.initObserver=function(t={}){if(Object.assign(t,{deepMerge:!0}),a(t,{lazy:!0,initWatch:!0,deepWatch:!0,shallowWatch:!1}),v=()=>{t.lazy?this.lazySave():this.save()},!t.initWatch)return!1;this.__storage=m(this.__storage,t.deepWatch,t.shallowWatch),this.setStore(this.__storage)},t.$set=function(t,e,o=!1,n=!0){return function(t,e,o=null){let n=t,r="",i=0;for(;i<e.length-1;i++)if(r=e[i],l(n[r])){if(!((s=n[r])instanceof Object||"object"==typeof s))return i;n=n[r]}else n=n[r]={};var s;return r=e[i],g(o)?o(n,r):n[r]=o,!0}(t,e,((t,e)=>{u(t[e])||(t[e]={}),d&&t[e].$addListener&&console.warn(`${_}The target have been converted before!`,t[e]),t[e]=S(t[e],o,n)}))},t.$get=function(t,e){return n(t,e)},e.$set=function(e,o=!1,n=!0){return t.$set(this.__storage,e.split("."),o,n)},e.$get=function(t){return n(this.__storage,t.split("."))}}(w),function(t){t.mixin((function(t){t._on("localLoaded",(function(t,e){let n=e.length?o(e,-1):t;return n||(n="{}"),n})),t._on("localSaved",(function(t,e){return e.length?o(e,-1):t}))})),t.mixin((function(t){t._on("setItem",(function(){this._dirty=!0})),t._on("saved",(function(){this._dirty=!1}))}));var e=[];r((t=>{let o,n=t.key;L===t.key&&(n=t.newValue.slice(-t.newValue.lastIndexOf("|")));for(let t=0;t<e.length;t++)if(o=e[t],!o.useLoadCache&&[o.__root].indexOf(n)>-1){d&&console.log("[Lycabinet]: Synchronizing data from other tabs..."),o.load({onCloud:!1,concurrent:!0,deepMerge:!0,disableMerge:!0}),o._trigger("storageSync");break}})),t.mixin((function(t){e.push(t),t._on("destroyed",(()=>{f(e,t)})),t._on("loadFromCache",(function(){this.useLoadCache=!0})),function(t,e){let o=null;for(let n in e)o=t[n],l(o)||(t[n]=e[n])}(t.options,{autoNotifyTabs:t.options.localInterface.database===window.sessionStorage}),t._on("saved",(function(t,e){if(this.options.autoNotifyTabs){if(t&&!e)return!1;this.notifyTabs()}}))})),t.prototype.notifyTabs=function(){const t=(new Date).getTime(),e=window.localStorage;try{e.setItem(L,`${this.__root}|${t}`)}catch(t){t instanceof DOMException&&(22===t.code||1014===t.code||"QuotaExceededError"===t.name||"NS_ERROR_DOM_QUOTA_REACHED"===t.name)&&e&&0!==e.length&&console.error("[lycabinet]: Sync storage from tabs failed cause LocalStorage is not supportted!",t)}}}(w),function(t){t.mixin((function(t){t._on("localLoaded",(function(t,e){return e.length?o(e,-1):t})),t._on("localSaved",(function(t,e){return e.length?o(e,-1):t}))}))}(w);const O=w;return e.default})()})); //# sourceMappingURL=lycabinet.min.js.map