substate
Version:
Pub/Sub pattern with State Management
3 lines (2 loc) • 11.5 kB
JavaScript
function t(t,e,r){const s=e.length;if(0===s)return void 0!==r?(t[""]=r,r):t;let n=!1;for(let t=0;t<s;t++)if("."!==e[t]){n=!0;break}if(!n)return void 0!==r?(t[""]=r,r):t[""];let i=t,a=0;const o=void 0!==r;for(let t=0;t<=s;t++){const n=t<s?e[t]:null,c=t===s;if("."===n||"["===n||c){if("["!==n||a<t){const h=e.slice(a,c?s:t);if("["===n)if(o)null==i[h]&&(i[h]=[]),i=i[h];else{if("object"!=typeof i||null==i)return;if(i=i[h],null==i)return}else{if(c)return o?(i[h]=r,r):"object"==typeof i&&null!=i?i[h]:void 0;if(o){if(null==i[h]){const r=t+1<s?e[t+1]:"";i[h]="["===r?[]:{}}i=i[h]}else{if("object"!=typeof i||null==i)return;if(i=i[h],null==i)return}}}if("["===n){for(t++,a=t;t<s&&"]"!==e[t];)t++;if(t>=s){const t=e.slice(a-1);return o?(i[t]=r,r):void 0}const n=e.slice(a,t),c=parseInt(n,10);if(isNaN(c)||n!==c.toString()){const t=`[${n}]`;return o?(i[t]=r,r):i&&"object"==typeof i?i[t]:void 0}if(t++,t>=s)return o?(Array.isArray(i)||(i=[]),i.length<=c&&(i.length=c+1),i[c]=r,r):Array.isArray(i)?i[c]:void 0;if(o){if(Array.isArray(i)||(i=[]),i.length<=c&&(i.length=c+1),null==i[c]){let r=!1;r=t<s&&"."===e[t]?t+1<s&&"["===e[t+1]:t<s&&"["===e[t],i[c]=r?[]:{}}i=i[c]}else{if(!Array.isArray(i))return;if(i=i[c],null==i)return}t<s&&"."===e[t]&&t++,a=t;continue}"."===n?(t++,a=t):c||(a=t)}}return i}function e(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var r,s;var n=e(function(){if(s)return r;function t(t){return t instanceof Buffer?Buffer.from(t):new t.constructor(t.buffer.slice(),t.byteOffset,t.length)}return s=1,r=function(e){if((e=e||{}).circles)return function(e){const r=[],s=[],n=new Map;if(n.set(Date,t=>new Date(t)),n.set(Map,(t,e)=>new Map(a(Array.from(t),e))),n.set(Set,(t,e)=>new Set(a(Array.from(t),e))),e.constructorHandlers)for(const t of e.constructorHandlers)n.set(t[0],t[1]);let i=null;return e.proto?c:o;function a(e,a){const o=Object.keys(e),c=new Array(o.length);for(let h=0;h<o.length;h++){const f=o[h],u=e[f];if("object"!=typeof u||null===u)c[f]=u;else if(u.constructor!==Object&&(i=n.get(u.constructor)))c[f]=i(u,a);else if(ArrayBuffer.isView(u))c[f]=t(u);else{const t=r.indexOf(u);c[f]=-1!==t?s[t]:a(u)}}return c}function o(e){if("object"!=typeof e||null===e)return e;if(Array.isArray(e))return a(e,o);if(e.constructor!==Object&&(i=n.get(e.constructor)))return i(e,o);const c={};r.push(e),s.push(c);for(const a in e){if(!1===Object.hasOwnProperty.call(e,a))continue;const h=e[a];if("object"!=typeof h||null===h)c[a]=h;else if(h.constructor!==Object&&(i=n.get(h.constructor)))c[a]=i(h,o);else if(ArrayBuffer.isView(h))c[a]=t(h);else{const t=r.indexOf(h);c[a]=-1!==t?s[t]:o(h)}}return r.pop(),s.pop(),c}function c(e){if("object"!=typeof e||null===e)return e;if(Array.isArray(e))return a(e,c);if(e.constructor!==Object&&(i=n.get(e.constructor)))return i(e,c);const o={};r.push(e),s.push(o);for(const a in e){const h=e[a];if("object"!=typeof h||null===h)o[a]=h;else if(h.constructor!==Object&&(i=n.get(h.constructor)))o[a]=i(h,c);else if(ArrayBuffer.isView(h))o[a]=t(h);else{const t=r.indexOf(h);o[a]=-1!==t?s[t]:c(h)}}return r.pop(),s.pop(),o}}(e);const r=new Map;if(r.set(Date,t=>new Date(t)),r.set(Map,(t,e)=>new Map(n(Array.from(t),e))),r.set(Set,(t,e)=>new Set(n(Array.from(t),e))),e.constructorHandlers)for(const t of e.constructorHandlers)r.set(t[0],t[1]);let s=null;return e.proto?function e(i){if("object"!=typeof i||null===i)return i;if(Array.isArray(i))return n(i,e);if(i.constructor!==Object&&(s=r.get(i.constructor)))return s(i,e);const a={};for(const n in i){const o=i[n];"object"!=typeof o||null===o?a[n]=o:o.constructor!==Object&&(s=r.get(o.constructor))?a[n]=s(o,e):ArrayBuffer.isView(o)?a[n]=t(o):a[n]=e(o)}return a}:function e(i){if("object"!=typeof i||null===i)return i;if(Array.isArray(i))return n(i,e);if(i.constructor!==Object&&(s=r.get(i.constructor)))return s(i,e);const a={};for(const n in i){if(!1===Object.hasOwnProperty.call(i,n))continue;const o=i[n];"object"!=typeof o||null===o?a[n]=o:o.constructor!==Object&&(s=r.get(o.constructor))?a[n]=s(o,e):ArrayBuffer.isView(o)?a[n]=t(o):a[n]=e(o)}return a};function n(e,n){const i=Object.keys(e),a=new Array(i.length);for(let o=0;o<i.length;o++){const c=i[o],h=e[c];"object"!=typeof h||null===h?a[c]=h:h.constructor!==Object&&(s=r.get(h.constructor))?a[c]=s(h,n):ArrayBuffer.isView(h)?a[c]=t(h):a[c]=n(h)}return a}}}());const i="STATE_UPDATED",a="STATE_RESET",o="UPDATE_STATE",c="TAG_REMOVED",h="TAG_JUMPED",f="HISTORY_LIMIT_CHANGED",u="HISTORY_CLEARED";class l{events;constructor(){this.events=Object.create(null)}on(t,e){this.events[t]||(this.events[t]=[]),this.events[t].push(e)}off(t,e){const r=this.events[t];if(r){const s=r.indexOf(e);s>-1&&(r.splice(s,1),0===r.length&&delete this.events[t])}}removeAll(){this.events=Object.create(null)}removeAllOf(t){this.events[t]=[]}emit(t,e={}){const r=this.events[t];if(r&&r.length>0)for(const t of r)t(e)}}const d=n();class g extends l{name;afterUpdate;beforeUpdate;currentState;stateStorage;defaultDeep;maxHistorySize;taggedStates;_hasMiddleware;_hasTaggedStates;constructor(t={}){super(),this.name=t.name||"SubStateInstance",this.afterUpdate=t.afterUpdate||[],this.beforeUpdate=t.beforeUpdate||[],this.currentState=t.currentState||0,this.stateStorage=t.stateStorage||[],this.defaultDeep=t.defaultDeep||!1,this.maxHistorySize=t.maxHistorySize||50,this.taggedStates=new Map,this._hasMiddleware=this.beforeUpdate.length>0||this.afterUpdate.length>0,this._hasTaggedStates=!1,t.state&&this.stateStorage.push(t.state),this.on(o,t=>this.updateState(t))}getState(t){return this.stateStorage[t]}getCurrentState(){return this.stateStorage[this.currentState]}getProp(e){const r=this.getCurrentState();return function(t){if(void 0===t)throw new Error("String is undefined");return t.includes(".")||t.includes("[")}(e)?t(r,e):r[e]}resetState(){this.currentState=0,this.stateStorage=[this.stateStorage[0]],this.emit(a)}updateState(t){const e=Object.keys(t),r=this.getCurrentState();if(this.canUseFastPathOptimized(t,e))return void this.fastUpdateStateOptimized(t,r,e);this._hasMiddleware&&this.fireBeforeMiddleware(t);const s=function(t,e){return void 0!==t.$deep?t.$deep:e}(t,this.defaultDeep);let n=this.cloneStateOptimized(s,r);n=this.tempUpdateOptimized(n,t,e,this.defaultDeep),this.pushState(n),this.updateTaggedStates(t,n),this._hasMiddleware&&this.fireAfterMiddleware(t),this.emit(t.$type||i,n)}batchUpdateState(t){if(0!==t.length){if(!this._hasMiddleware&&!this._hasTaggedStates){let e=!0;for(let r=0;r<t.length;r++){const s=t[r];if(s.$deep||void 0!==s.$tag){e=!1;break}const n=Object.keys(s);for(let t=0;t<n.length;t++){const r=n[t];if(r.includes(".")||"$deep"===r||"$type"===r||"$tag"===r){e=!1;break}}if(!e)break}if(e)return void this.fastBatchUpdate(t)}for(let e=0;e<t.length;e++)this.updateState(t[e])}}sync(e){const{readerObj:r,stateField:s,readField:n=s,beforeUpdate:a=[],afterUpdate:o=[]}=e;this.validateSyncFields(s);const c=t=>{const e={source:"substate",field:s,readField:n};let r=t;return a.forEach(t=>{r=t(r,e,this)}),r},h=t=>{const e={source:"substate",field:s,readField:n};o.forEach(r=>{r(t,e,this)})},f=e=>{const i=t(e,s);if(void 0!==i){const e=c(i);t(r,n,e),h(e)}},u=this.getProp(s);if(void 0!==u){const e=c(u);t(r,n,e),h(e)}return this.on(i,f),{unsync:()=>{this.off(i,f)}}}clearHistory(){const t=this.stateStorage.length,e=this.getCurrentState();this.stateStorage=[e],this.currentState=0,this.taggedStates.clear(),this.emit(u,{previousLength:t})}limitHistory(t){if(t<1)throw new Error("History size must be at least 1");const e=this.maxHistorySize;if(this.maxHistorySize=t,this.stateStorage.length>t){const e=this.stateStorage.length-t;this.stateStorage.splice(0,e);for(const[t,r]of this.taggedStates.entries())r.stateIndex<e?this.taggedStates.delete(t):r.stateIndex-=e;this.currentState=this.stateStorage.length-1}this.emit(f,{previousSize:e,newSize:t,currentHistoryLength:this.stateStorage.length})}getMemoryUsage(){const t=this.stateStorage.length;if(0===t)return{stateCount:0,taggedCount:0,estimatedSizeKB:0};let e=0;try{const r=Math.min(3,t);let s=0;for(let e=0;e<r;e++){const n=Math.floor(e*(t-1)/Math.max(1,r-1));s+=2*JSON.stringify(this.stateStorage[n]).length}e=(r>0?s/r:0)*t}catch(t){return{stateCount:this.stateStorage.length,taggedCount:this.taggedStates.size,estimatedSizeKB:null}}const r=Math.max(1,Math.round(e/1024));return{stateCount:t,taggedCount:this.taggedStates.size,estimatedSizeKB:r}}getTaggedState(t){const e=this.taggedStates.get(t);return e?d(e.state):void 0}getAvailableTags(){return Array.from(this.taggedStates.keys())}jumpToTag(t){const e=this.taggedStates.get(t);if(!e)throw new Error(`Tag "${t}" not found`);const r=d(e.state);delete r.$tag,this.pushState(r),this.emit(h,{tag:t,state:this.getCurrentState()}),this.emit(i,this.getCurrentState())}removeTag(t){const e=this.taggedStates.has(t);return this.taggedStates.delete(t),e&&this.emit(c,{tag:t}),e}clearTags(){const t=this.taggedStates.size;this.taggedStates.clear(),this.emit("TAGS_CLEARED",{clearedCount:t})}get hasMiddleware(){return this._hasMiddleware}get hasTaggedStates(){return this._hasTaggedStates}updateTaggedStates(t,e){t.$tag&&(this._hasTaggedStates=!0,this.taggedStates.set(t.$tag,{stateIndex:this.currentState,state:d(e)}))}pushState(t){this.stateStorage.push(t),this.stateStorage.length>this.maxHistorySize&&this.performHistoryTrim(),this.currentState=this.stateStorage.length-1}performHistoryTrim(){if(this.stateStorage.length<=this.maxHistorySize)return;const t=this.stateStorage.length-this.maxHistorySize;this.stateStorage.splice(0,t);for(const[e,r]of this.taggedStates.entries())r.stateIndex<t?this.taggedStates.delete(e):r.stateIndex-=t;this.currentState=this.stateStorage.length-1}fireBeforeMiddleware(t){this.beforeUpdate.length>0&&this.beforeUpdate.forEach(e=>{e(this,t)})}fireAfterMiddleware(t){this.afterUpdate.length>0&&this.afterUpdate.forEach(e=>{e(this,t)})}canUseFastPathOptimized(t,e){if(this._hasMiddleware||this._hasTaggedStates||t.$deep||t.$tag)return!1;for(let t=0;t<e.length;t++){const r=e[t];if(r.includes(".")||r.includes("[")||"$type"===r)return!1}return!0}cloneStateOptimized(t,e){return t?d(e):{...e}}tempUpdateOptimized(e,r,s,n){let i=!1;for(let t=0;t<s.length;t++){const e=s[t];if(e.includes(".")||e.includes("[")){i=!0;break}}if(i){const n=[],i=[];for(let t=0;t<s.length;t++){const e=s[t];e.includes(".")||e.includes("[")?i.push(e):n.push(e)}for(let t=0;t<n.length;t++){const s=n[t];e[s]=r[s]}for(let s=0;s<i.length;s++){const n=i[s];t(e,n,r[n])}}else for(let t=0;t<s.length;t++){const n=s[t];e[n]=r[n]}return n||(e.$deep=!1),e.$type=r.$type||o,e}fastUpdateStateOptimized(t,e,r){const s={...e};for(let e=0;e<r.length;e++){const n=r[e];"$deep"!==n&&"$type"!==n&&"$tag"!==n&&(s[n]=t[n])}s.$type=o,this.pushState(s),this.emit(i,s)}fastBatchUpdate(t){const e={...this.getCurrentState()};for(let r=0;r<t.length;r++){const s=t[r],n=Object.keys(s);for(let t=0;t<n.length;t++){const r=n[t];"$deep"!==r&&"$type"!==r&&"$tag"!==r&&(e[r]=s[r])}}e.$type=o,this.pushState(e),this.emit(i,e)}validateSyncFields(t){if(void 0===this.getProp(t))throw new Error(`State field '${t}' not found in current state. Available state properties: ${Object.keys(this.getCurrentState()).join(", ")}`)}}function p(t={}){return new g({name:t.name,state:t.state,defaultDeep:t.defaultDeep??!1,beforeUpdate:t.beforeUpdate||[],afterUpdate:t.afterUpdate||[],maxHistorySize:t.maxHistorySize??50})}export{g as Substate,p as createStore};
//# sourceMappingURL=index.esm.js.map