@qtpy/state-management-observable
Version:
1. [Основная идея и архитектура](#основная-идея-и-архитектура) 1.1. [Прозрачная реактивность](#прозрачная-реактивность) 1.2. [Поддержка типизированных строковых ключей](#поддержка-типизированных-строковых-ключей) 1.3. [Подписки с «гранул
2 lines (1 loc) • 8.68 kB
JavaScript
;var z=Object.defineProperty;var N=(M,s,a)=>s in M?z(M,s,{enumerable:!0,configurable:!0,writable:!0,value:a}):M[s]=a;var $=(M,s,a)=>N(M,typeof s!="symbol"?s+"":s,a);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const f=require("./utils.cjs");class B{constructor(s=[],a){$(this,"undoStack",new Map);$(this,"redoStack",new Map);$(this,"perPathMaxLength");this.perPathMaxLength=new Map;for(const[i,l]of s){const S=a(i);this.perPathMaxLength.set(S,l)}}getMaxLength(s){return this.perPathMaxLength.get(s)??0}push(s,a){if(!this.perPathMaxLength.get(s))return;const i=this.undoStack.get(s)??[];i.push(a);const l=this.getMaxLength(s);i.length>l&&i.shift(),this.undoStack.set(s,i),this.redoStack.set(s,[])}getUndo(s,a){const i=this.undoStack.get(s)??[];if(!(a<0||a>=i.length))return i[i.length-1-a]}getRedo(s,a){const i=this.redoStack.get(s)??[];if(!(a<0||a>=i.length))return i[i.length-1-a]}getHistory(s){const a=this.undoStack.get(s)??[],i=this.redoStack.get(s)??[];return{undo:[...a],redo:[...i]}}spliceStack(s,a,i){if(i){const[l,S]=i;if(l<0||l>=s.length||S<=0)return;const d=s.splice(l,S);return a.push(...d),d[d.length-1]}}undo(s,a){const i=this.undoStack.get(s)??[],l=this.redoStack.get(s)??[];if(i.length<=1&&!a)return;if(a){const d=this.spliceStack(i,l,a);return this.undoStack.set(s,i),this.redoStack.set(s,l),d??(i.length>0?i[i.length-1]:void 0)}const S=i.pop();return l.push(S),this.undoStack.set(s,i),this.redoStack.set(s,l),i[i.length-1]}redo(s,a){const i=this.undoStack.get(s)??[],l=this.redoStack.get(s)??[];if(l.length===0&&!a)return;if(a){const d=this.spliceStack(l,i,a);return this.undoStack.set(s,i),this.redoStack.set(s,l),d}const S=l.pop();return i.push(S),this.undoStack.set(s,i),this.redoStack.set(s,l),S}getCurrent(s){const a=this.undoStack.get(s)??[];return a[a.length-1]}clear(s,a="all",i){const l=this.undoStack.get(s)??[],S=this.redoStack.get(s)??[];if(i){const[d,v]=i;if(d<0||d>=(a==="redo"?S:l).length||v<=0)return!1;if(a==="redo")return S.splice(d,v),this.redoStack.set(s,S),!0;if(a==="undo")return l.splice(d,v),this.undoStack.set(s,l),!0;if(a==="all"){const x=l.length>0&&d>=0&&d<l.length&&v>0,p=S.length>0&&d>=0&&d<S.length&&v>0;return x&&l.splice(d,v),p&&S.splice(d,v),this.undoStack.set(s,l),this.redoStack.set(s,S),x||p}}switch(a){case"redo":return this.redoStack.delete(s);case"undo":return this.undoStack.delete(s);default:const d=this.undoStack.delete(s),v=this.redoStack.delete(s);return d||v}}pruneUnused(s){for(const a of[...this.undoStack.keys()])s.has(a)||this.clear(a)}getEntries(){return Array.from(this.undoStack.entries()).map(([s,a])=>{const i=this.redoStack.get(s)??[];return{path:s,current:a[a.length-1],undoLength:a.length,redoLength:i.length,undo:a,redo:i,maxLength:this.getMaxLength(s)}})}}function W(M,s=[],a={}){let i={...M},l=!1,S="user",d=null;const v=new WeakMap,x=[],p=new Set,w=new Map,P=new Map,C=new Set,E=new Map,H=()=>x[x.length-1],U=e=>f.splitPath(e).reduce((n,r)=>{if(n!=null)return n[r]},i),Q=(e,t)=>{const n=f.splitPath(e),r=n.pop(),c=n.reduce((u,g)=>{if(u==null)throw new Error(`Невозможно установить по пути "${e}" — промежуточное значение undefined`);return u[g]},i);c[r]=t};let K=null;function _(e,t=""){return typeof e!="object"||e===null?e:new Proxy(e,{get(r,c,u){const g=typeof c=="string"?c:String(c),h=t?`${t}.${g}`:g;d==null||d.trackedPaths.add(h);const y=Reflect.get(r,c,u);return Array.isArray(r)&&typeof y=="function"&&f.isArrayMethod(g)?(...R)=>{K={name:g};let b;return S="proxy",o.batch(()=>{b=y.apply(u,R)}),l&&t?C.add(t):t&&o.invalidate(t),K=null,b}:y===r?u:y!==null&&typeof y=="object"?_(y,h):y},set(r,c,u,g){const h=typeof c=="string"?c:String(c),y=t?`${t}.${h}`:h,R=Reflect.get(r,c,g);return Object.is(R,u)||(l?H().set(y,u):(o.update(y,u),!K&&t&&o.invalidate(t))),!0},deleteProperty(r,c){const u=typeof c=="string"?c:String(c),g=t?`${t}.${u}`:u,h=Reflect.deleteProperty(r,c);return h&&o.update(g,void 0),h},ownKeys(r){if(d){const c=t?`${t}.`:"";for(const u of Reflect.ownKeys(r))d.trackedPaths.add(`${c}${String(u)}`)}return Reflect.ownKeys(r)}})}function V(e,t,n){let r=!1;const c=f.withMetaSupport(t,()=>{const u=f.getMetaData(n,t),g=u==null?void 0:u._prevSignature,h=f.calculateSnapshotHash(t);return g&&h&&g===h?(r=!0,!0):(h&&f.setMetaData(n,t,{_prevSignature:h}),!0)});return{bool:r||!c&&f.shallowEqual(e,t),isSupportedMetaData:c}}const o={};let L=_(i);Object.defineProperty(o,"$",{get:()=>L,enumerable:!0,configurable:!0});const k=e=>f.getStringPath(o==null?void 0:o.$,e),m=new B((a==null?void 0:a.customLimitsHistory)??[],k);function A(e){p.forEach(n=>{const r=n.__meta;if(l?r.cacheKeys&&r.cacheKeys.has(e):!r.cacheKeys||r.cacheKeys.has(e)){d=r;try{n(L)}finally{d=null}}});const t=w.get(e);if(t){const n=U(e);t.forEach(r=>r(n))}}o.clearHistoryPath=(e,t="all",n)=>{const r=k(e);m.clear(r,t,n)},o.clearAllHistory=()=>{const e=new Set(w.keys());m.pruneUnused(e)};const T=(e,t,n=!1,r=!1)=>{const c=U(e),u=V(c,t,v);u.bool||(n||(u.isSupportedMetaData&&t!==c&&m.push(e,t),u.isSupportedMetaData||m.push(e,t)),Q(e,t),!r&&A(e))};o.update=(e,t,n)=>{f.validatePath(e);const r=k(e);let c=o.resolveValue(e,t);l&&!(n!=null&&n.keepQuiet)?H().set(r,c):T(r,c,!1,n==null?void 0:n.keepQuiet)},o.update.quiet=(e,t)=>{o.update(e,t,{keepQuiet:!0})},o.debounced=(e,t)=>{const n=f.detRandomId();let r=null;const c=(...u)=>{r&&clearTimeout(r),r=setTimeout(()=>{e(...u),E.delete(n)},t),E.set(n,r)};return c.cancel=()=>{r&&(clearTimeout(r),E.delete(n))},c};function q(e){const t=[];for(const[n,r]of e){const c=U(n);V(c,r,v).bool||(S==="user"&&m.push(n,c),Q(n,r),A(n),t.push(n))}t.length&&p.forEach(n=>{n.__meta.cacheKeys||n(L)})}o.resolveValue=(e,t)=>{const n=k(e),r=U(n),c=typeof t=="function"?t(r):t;return f.withMetaSupport(c,()=>{const u=f.calculateSnapshotHash(r);u||f.setMetaData(v,c,{_prevSignature:u})}),c},o.asyncUpdate=async(e,t,n)=>{const{abortPrevious:r=!1,keepQuiet:c=!1}=n??{};f.validatePath(e);const u=k(e);if(r){const h=P.get(u);h&&(h.abort(),P.delete(u))}const g=new AbortController;g.signal.addEventListener("abort",()=>{P.delete(u)},{once:!0}),P.set(u,g);try{const h=U(u),y=await t(h,g.signal);g.signal.aborted||o.update(u,y,{keepQuiet:c})}catch(h){h.name!=="AbortError"&&console.error(h)}finally{P.delete(u)}},o.asyncUpdate.quiet=async(e,t,n={})=>o.asyncUpdate(e,t,{abortPrevious:n.abortPrevious??!1,keepQuiet:!0}),o.batch=e=>{x.push(new Map),l=!0;try{e()}finally{const t=x.pop();if(x.length>0){const n=H();for(const[r,c]of t)n.set(r,c)}else{q(t),l=!1,S="user";for(const n of C)o.invalidate(n);C.clear()}}return Promise.resolve()},o.getUndo=(e,t)=>{f.validatePath(e);const n=k(e);return m.getUndo(n,t)},o.getRedo=(e,t)=>{f.validatePath(e);const n=k(e);return m.getRedo(n,t)},o.getHistory=e=>{f.validatePath(e);const t=k(e);return m.getHistory(t)},o.undo=(e,t)=>{f.validatePath(e);const n=k(e),r=m.undo(n,t);return r!==void 0?(T(n,r,!0),o.update(n,r,{skipHistory:!0,keepQuiet:!0}),!0):(console.warn(`No undo history for path: ${n}`),!1)},o.redo=(e,t)=>{f.validatePath(e);const n=k(e),r=m.redo(n,t);return r!==void 0?(T(n,r,!0),o.update(n,r,{skipHistory:!0,keepQuiet:!0}),!0):(console.warn(`No redo history for path: ${n}`),!1)},o.subscribe=(e,t)=>{const n=t?new Set(t.map(u=>f.normalizeCacheKey(u,o))):void 0,r={active:!0,trackedPaths:new Set,cacheKeys:n},c=u=>{r.active&&e(u)};return c.__meta=r,p.add(c),()=>{r.active=!1,p.delete(c)}},o.subscribeToPath=(e,t,n={})=>{f.validatePath(e);const{immediate:r=!1,cacheKeys:c}=n,u=k(e),g=c?c.map(b=>f.normalizeCacheKey(b,o)):[],h=[u,...g],y=b=>t(b),R={active:!0,trackedPaths:new Set(h),cacheKeys:g.length>0?new Set(g):void 0};return y.__meta=R,h.forEach(b=>{w.has(b)||w.set(b,new Set),w.get(b).add(y)}),r&&y(U(u)),()=>{h.forEach(b=>{var j;(j=w.get(b))==null||j.delete(y)})}},o.invalidateAll=()=>{p.forEach(e=>{d=e.__meta;try{e(L)}finally{d=null}}),w.forEach((e,t)=>{const n=U(t);e.forEach(r=>r(n))})},o.invalidate=e=>{const t=k(e);A(t)},o.cancelAsyncUpdates=e=>{if(e){const t=k(e),n=P.get(t);n&&(n.abort(),P.delete(t))}else P.forEach((t,n)=>{t.abort(),P.delete(n)})},o.clearStore=()=>{p.clear(),w.clear(),P.clear(),E.forEach(e=>clearTimeout(e)),E.clear(),o.clearAllHistory()},o.get=e=>(f.validatePath(e),U(k(e))),o.resolvePath=k,o.getRawStore=()=>i,o.setRawStore=async(e,t)=>{o.cancelAsyncUpdates(),o.clearAllHistory(),E.forEach(n=>clearTimeout(n)),E.clear(),i={...e},L=_(i),t!=null&&t.keepQuiet||o.invalidateAll()},o.getMemoryStats=()=>({subscribersCount:p.size,pathSubscribersCount:w.size,historyEntries:m.getEntries(),activePathsCount:w.size,debounceTimersCount:E.size});let D=o.update;return s.reverse().forEach(e=>{D=e(o,D)}),o.update=D,o}exports.createObservableStore=W;