UNPKG

proxy-live-document

Version:

Mutable, observable, patchable JSON state wrapped in Smart Domains

2 lines (1 loc) 12.8 kB
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});const t=t=>"object"==typeof t&&null!==t,e=Symbol("NoValue"),r=t=>{let e=t,r=[];for(;e.p&&(r.push(e.k),e=e.p,!("op"in e)););return"op"in e?[e,r.reverse()]:null},o=(t,e)=>{var r;return t.c=null!==(r=t.c)&&void 0!==r?r:{},t.c[e]||(t.c[e]={p:t,k:e}),t.c[e]},s=(o,s,i,a)=>{var c;if(s===i)return;if("op"in o)return void(i===e?("new"in o&&delete o.new,Object.assign(o,{op:"remove"})):Object.assign(o,{new:i,op:"remove"===o.op?"replace":o.op}));const h=r(o);if(h){const[r,s]=h;if("new"in r){let n=r.new;s.pop(),s.forEach((e=>{if(!t(n))throw new Error(`We tried to merge two new values, but the new place at ${s.join(", ")} encountered a non object at first encounter of the key ${e}`);e in n&&(n=n[e])})),i===e?delete n[o.k.toString()]:n[o.k.toString()]=i}return}let l="replace";s===e&&(l="add"),i===e&&(l="remove"),Object.assign(o,{op:l,opCount:a,d:!0,...s!==e?{old:s}:{},...i!==e?{new:i}:{}}),o.c&&Object.values(null!==(c=o.c)&&void 0!==c?c:{}).forEach((t=>{n(t)}))},n=e=>{const{c:o}=e;if(Object.values(null!=o?o:{}).forEach((t=>{n(t)})),"old"in e){const o=r(e);if(!o)throw new Error("We tried to merge a subtree of mutation but there was no parent with an old value above: Not sure if error");const[s,n]=o;if(!("old"in s))throw new Error("We tried to merge a subtree of mutation but there was no parent with an old value above: Not sure if error");let i=s.old;n.pop(),n.forEach((e=>{if(!t(i))throw new Error(`We tried to merge two old values, but the new place at ${n.join(", ")} encountered a non object at first encounter of the key ${e}`);e in i&&(i=i[e])})),i[e.k.toString()]=e.old,"op"in e&&(delete e.op,delete e.new,delete e.old)}if("op"in e&&"add"===e.op){const o=r(e);if(!o)throw new Error("We tried to merge a subtree of mutation but there was no parent with an old value above: Not sure if error");const[s,n]=o;if("op"in s&&"remove"===s.op){let r=s.old;n.pop(),n.forEach((e=>{if(!t(r))throw new Error(`We tried to merge two old values, but the new place at ${n.join(", ")} encountered a non object at first encounter of the key ${e}`);e in r&&(r=r[e])})),delete r[e.k.toString()]}"op"in e&&(delete e.op,delete e.new,delete e.old)}"op"in e&&(delete e.op,delete e.new,delete e.old)},i=(t,e,r=[])=>{"op"in t?e.push({op:t.op,old:"old"in t?t.old:void 0,value:"new"in t?t.new:void 0,pathArray:r,opCount:t.opCount,path:`/${r.join("/")}`}):t.c&&Object.values(t.c).forEach((t=>{i(t,e,[...r,t.k])}))};const a=new class{constructor(){this.proxies=new WeakSet}cache(t){this.proxies.add(t)}exists(t){return this.proxies.has(t)}};Object.freeze(a);const c=(t,e,r,o)=>{var s,n,i;let a=t,c=[...e];for(;c.length;){const t=c.shift();a.children=null!==(s=a.children)&&void 0!==s?s:{},a.children[t]=null!==(n=a.children[t])&&void 0!==n?n:{propName:t},a=a.children[t]}return a.subs=null!==(i=a.subs)&&void 0!==i?i:[],r.options=o,a.subs.push(r),a},h=(t,e)=>{var r;if(!t.subs)return!1;const o=null===(r=t.subs)||void 0===r?void 0:r.indexOf(e);if(-1===o)return!1;t.subs=[...t.subs.slice(0,o),...t.subs.slice(o+1)]},l=(t,e)=>{const r="**"===t.propName;if(!t.children)return r?[t]:null;const o=[],s=t.children[e];return r&&o.push(t),s&&o.push(s),t.children["*"]&&o.push(t.children["*"]),t.children["**"]&&o.push(t.children["**"]),o.length?o:null},u=Symbol("Patcher"),p=Symbol("WatcherProxy"),d=Symbol("TargetRef"),y=(t,e)=>{const{op:r,pathArray:o,value:s}=t,n=o.length;if(!n)return;let i,a=e,c=a.hasOwnProperty(u)?{entity:a,pathArray:[...o]}:null;for(let t=0;t<n-1;t+=1){if(i=o[t],!a.hasOwnProperty(i))throw new Error(`applyJSONPatchOperation cannot walk json patch path ${o.join("/")}. Cannot access path ${[...o].slice(0,t).join("/")}.`);a=a[i],a.hasOwnProperty(u)&&(c={entity:a,pathArray:[...o].slice(t+1)})}const h=o[n-1];if(c&&"applyPatch"in c.entity&&"function"==typeof c.entity.applyPatch){const e=t.pathArray.filter((t=>-1!==(null==c?void 0:c.pathArray.indexOf(t)))),r=e.join("/");c.entity.applyPatch({...t,path:r,pathArray:e})}else if(Array.isArray(a))switch(r){case"add":"-"===h?a.push(...Array.isArray(s)?s:[s]):a.splice(Number(h),0,s);break;case"replace":a[h]=s;break;case"remove":a.splice(Number(h),1)}else switch(r){case"add":case"replace":Object.assign(a,{[h]:s});break;case"remove":delete a[h]}};class f{constructor(){this.mutationMaps=new Map,this.mutationDirtyPaths=new Map,this.mutationSelectorPointers=new Map,this.mutationChangePointers=new Map,this.getSubProxy=(t,e,r,o,s)=>{const n=this.mutationMaps.get(t);let i=null==n?void 0:n.get(o);i||(i=new Proxy(o,new m({target:o,selectorPointerArray:r,mutationNode:e,dirtyPaths:this.mutationDirtyPaths.get(t),incOpCount:s,proxyfyAccess:(e,r,o)=>this.getSubProxy(t,r,o,e,s)})),null==n||n.set(o,i));const a={target:o,incOpCount:s,selectorPointerArray:r,mutationNode:e,dirtyPaths:this.mutationDirtyPaths.get(t),proxyfyAccess:(e,r,o)=>this.getSubProxy(t,r,o,e,s)},c=Array.isArray(o)?new b(a):new m(a);return i=new Proxy(o,c),null==n||n.set(o,i),i}}startMutation(t){this.mutationMaps.set(t,new WeakMap);const e=new WeakMap,r=new Set,o=new Array(v.getSelectorTree(t)),s={p:null,k:""};this.mutationChangePointers.set(t,s);let n=0;const i=()=>(n+=1,n),a=new Proxy(t,new m({target:t,selectorPointerArray:o,mutationNode:s,dirtyPaths:r,incOpCount:i,proxyfyAccess:(e,r,o)=>this.getSubProxy(t,r,o,e,i)}));e.set(t,a),this.mutationDirtyPaths.set(t,r),this.mutationMaps.set(t,e),this.mutationSelectorPointers.set(t,o)}hasRoot(t){return this.mutationMaps.has(t)}commit(t){const e=this.mutationDirtyPaths.get(t);if(!e)return[];const r=Array.from(e).reduce(((t,e)=>(e.writeSelectorPointerArray.filter((t=>"root"!==t.propName)).forEach((e=>t.add(e))),t)),new Set),o=(t=>{const e=[];return i(t,e),e.sort(((t,e)=>t.opCount-e.opCount)).map((t=>{const{opCount:e,...r}=t;return r}))})(this.mutationChangePointers.get(t));return v.runSelectorPointers(t,r,o),this.mutationMaps.delete(t),this.mutationDirtyPaths.delete(t),o}mutate(t,e){var r;const o=!this.hasRoot(t);o&&this.startMutation(t);const s=null===(r=this.mutationMaps.get(t))||void 0===r?void 0:r.get(t);if(s)return e(s),o?this.commit(t):[]}}const w=new f,P=(t,e)=>w.mutate(t,e),g=(e,r,o,s,n)=>new Proxy(e,{get:(i,a)=>{if("symbol"==typeof a&&a===p)return!0;if("symbol"==typeof a||"hasOwnProperty"===a)return Reflect.get(i,a);const h=Object.getOwnPropertyDescriptor(i.constructor.prototype,a);if(null==h?void 0:h.get)return h.get.call(g(e,r,o,s,n));{const e=i[a];return s.push(c(o,[...r,a],n)),t(e)?g(e,[...r,a],o,s,n):e}},getOwnPropertyDescriptor:(t,e)=>e===p?{configurable:!0,value:!0}:Reflect.getOwnPropertyDescriptor(t,e),ownKeys:t=>(s.push(c(o,[...r,"*"],n)),Reflect.ownKeys(t))});class m{constructor(t){this.deleted={},this.original={},this.writeSelectorPointerArray=[];const{target:e,proxyfyAccess:r,dirtyPaths:o}=t;this.targetRef=e,this.proxyfyAccess=r,this.dirtyPaths=o,this.selectorPointerArray=t.selectorPointerArray,this.mutationNode=t.mutationNode,this.incOpCount=t.incOpCount}get(t,e){if("symbol"==typeof e&&e===d)return this.targetRef;if("symbol"==typeof e&&e===p)return!0;if("symbol"==typeof e||"hasOwnProperty"===e)return Reflect.get(t,e);if("string"==typeof e&&this.deleted.hasOwnProperty(e))return;const r=t[e];if(a.exists(r))return r;if("object"==typeof r&&null!==r){const{selectorPointerArray:t}=this,s=t.reduce(((t,r)=>{const o=l(r,e);return o&&t.push(...o),t}),[]),n=o(this.mutationNode,e),i=this.proxyfyAccess(r,n,s);return a.exists(i)||a.cache(i),i}return r}set(t,r,n){if("length"===r&&Array.isArray(t))return Reflect.set(t,r,n);this.writeSelectorPointerArray.push(...this.selectorPointerArray.reduce(((t,e)=>{const o=l(e,r);return o&&t.push(...o),t}),[])),this.dirtyPaths.add(this),!this.original.hasOwnProperty(r)&&t.hasOwnProperty(r)&&(this.original[r]=t[r]);let i=n;if("object"==typeof n&&null!==n){const t=n;i=t.hasOwnProperty(p)?t[d]:Array.isArray(n)?[...n]:{...n}}let a=this.original[r];"object"==typeof a&&null!==a&&(a={...a});const c=o(this.mutationNode,r);return s(c,r in t?t[r]:e,i,this.incOpCount()),Reflect.set(t,r,n)}deleteProperty(t,r){if(r in t&&"string"==typeof r){this.writeSelectorPointerArray.push(...this.selectorPointerArray.reduce(((t,e)=>{const o=l(e,r);return o&&t.push(...o),t}),[]));const n=o(this.mutationNode,r);s(n,t[r],e,this.incOpCount()),this.dirtyPaths.add(this),this.deleted[r]=!0,this.original.hasOwnProperty(r)||(this.original[r]=t[r]);let i=this.original[r];"object"==typeof i&&null!==i&&(i={...i})}return Reflect.deleteProperty(t,r)}getOwnPropertyDescriptor(t,e){if("string"!=typeof e||!this.deleted[e])return e===p?{configurable:!0,value:!0}:Reflect.getOwnPropertyDescriptor(t,e)}ownKeys(t){return Reflect.ownKeys(t)}has(t,e){return Reflect.has(t,e)}}class b{constructor(t){this.deleted={},this.original=[],this.writeSelectorPointerArray=[];const{target:e,proxyfyAccess:r,dirtyPaths:o}=t;this.targetRef=e,this.proxyfyAccess=r,this.dirtyPaths=o,this.selectorPointerArray=t.selectorPointerArray,this.mutationNode=t.mutationNode,this.incOpCount=t.incOpCount}get(t,r){switch(r){case"splice":return(...r)=>{const[n,i]=r,a=n+i;for(let r=n;r<a;r+=1){this.writeSelectorPointerArray.push(...this.selectorPointerArray.reduce(((t,e)=>{const o=l(e,r.toString());return o&&t.push(...o),t}),[]));const n=o(this.mutationNode,r.toString());s(n,t[r],e,this.incOpCount()),this.deleted[r]=!0}return this.dirtyPaths.add(this),t.splice(...r)};case"push":return(...r)=>{this.writeSelectorPointerArray.push(...this.selectorPointerArray.reduce(((t,e)=>{const r=l(e,"-");return r&&t.push(...r),t}),[]));const n=o(this.mutationNode,"-");return s(n,e,r,this.incOpCount()),this.dirtyPaths.add(this),t.push(...r)};case"pop":return()=>{const r=t.length-1;this.writeSelectorPointerArray.push(...this.selectorPointerArray.reduce(((t,e)=>{const o=l(e,r.toString());return o&&t.push(...o),t}),[]));const n=o(this.mutationNode,r.toString());return s(n,t[r],e,this.incOpCount()),this.dirtyPaths.add(this),t.pop()};case"shift":return()=>{this.writeSelectorPointerArray.push(...this.selectorPointerArray.reduce(((t,e)=>{const r=l(e,"0");return r&&t.push(...r),t}),[]));const r=o(this.mutationNode,"0");return s(r,t[0],e,this.incOpCount()),this.dirtyPaths.add(this),t.shift()}}return Reflect.get(t,r)}set(t,e,r){this.writeSelectorPointerArray.push(...this.selectorPointerArray.reduce(((t,r)=>{const o=l(r,e);return o&&t.push(...o),t}),[]));const n=o(this.mutationNode,e);return s(n,t[e],r,this.incOpCount()),this.dirtyPaths.add(this),Reflect.set(t,e,r)}deleteProperty(t,r){this.writeSelectorPointerArray.push(...this.selectorPointerArray.reduce(((t,e)=>{const o=l(e,r);return o&&t.push(...o),t}),[]));const n=o(this.mutationNode,r);return s(n,t[r],e,this.incOpCount()),this.dirtyPaths.add(this),Reflect.deleteProperty(t,r)}}class A{constructor(){this.selectorTrees=new WeakMap}getSelectorTree(t){if(!this.selectorTrees.has(t)){const e={propName:"root"};return this.selectorTrees.set(t,e),e}return this.selectorTrees.get(t)}runSelectorPointers(t,e,r){const o=new Set,s=o.add.bind(o),n=(t,e=!1)=>{t.forEach((t=>{const{subs:r,children:o}=t;e?null==r||r.forEach(s):null==r||r.filter((t=>{var e;return null===(e=t.options)||void 0===e?void 0:e.reactToAncestorChanges})).forEach(s),o&&n(Object.values(o))}))};n(e,!0),o.forEach((e=>{e(t,r)}))}}const v=new A;exports.IObservableDomain=class{},exports.LIB_VERSION="2.0.7beta",exports.MutationsManager=f,exports.Patcher=u,exports.ProxyMutationArrayHandler=b,exports.ProxyMutationObjectHandler=m,exports.StateTreeSelectorsManager=A,exports.TargetRef=d,exports.WatcherProxy=p,exports.applyJSONPatchOperation=y,exports.autorun=(t,e)=>{const r=v.getSelectorTree(t);let o=[];const s=()=>{o.forEach((t=>{h(t,n)}))},n=(i,a)=>{s(),o=[];const c=g(t,[],r,o,n);e(c,a)};return n(),s},exports.inversePatch=t=>{const{path:e,pathArray:r,op:o,value:s,old:n}=t;switch(o){case"add":return{op:"remove",value:n,old:s,pathArray:r,path:e};case"remove":return{op:"add",value:n,old:s,pathArray:r,path:e};case"replace":return{op:"replace",value:n,old:s,pathArray:r,path:e}}},exports.mutate=P,exports.mutateFromPatches=(t,e)=>{P(t,(t=>{for(let r=0;r<e.length;r+=1)y(e[r],t)}))},exports.pathMatchesSource=(t,e)=>{if(-1===t.indexOf("**")&&t.length!==e.length)return!1;for(let r=0;r<t.length;r+=1)if(t[r]!==e[r]&&("*"!==t[r]||!e[r])){if(r+1===t.length&&"**"===t[r]&&e[r])return!0;if(e[r]!==t[r])return!1}return!0},exports.select=(t,e,r,o)=>{const s=v.getSelectorTree(t),n=new Set,i=(...t)=>{const e=r(...t);return n.forEach((t=>t(e))),e},a=e.map((t=>c(s,(t=>t.startsWith("/")?t.substring(1).split("/"):t.split("/"))(t),i,o)));return{reshape:()=>{throw new Error("reshape is no longer supported")},observe:t=>(console.warn("observe is depreacated. Use just selectors or autorun instead"),n.add(t),()=>{n.delete(t)}),dispose:()=>{for(const t of a)h(t,i)}}},exports.selectorsManager=v;