UNPKG

@dependable/session

Version:

Save and restore @dependable/state to the session storage

2 lines (1 loc) 3.1 kB
import{observable as e,subscribables as t,registerInitial as r}from"@dependable/state";const o=(e,t)=>{if("function"==typeof e){if("observable"===e.kind){return{$reference:n(e,t)}}throw new Error("Observables can only contain JSON serializable data and other observables")}return e&&"object"==typeof e?Array.isArray(e)?((e,t)=>e.map((e=>o(e,t))))(e,t):((e,t)=>Object.fromEntries(Object.entries(e).map((([e,r])=>[e,o(r,t)]))))(e,t):e},n=(e,t)=>{let r=e.id||e.sessionId||t.ids.get(e);return r||(r="$"+t.nextId++,t.ids.set(e,r)),t[r]||(t.observables[r]=o(e(),t)),r},s=(e,t,r)=>e&&"object"==typeof e?e.$reference?c(e.$reference,t,r):Array.isArray(e)?((e,t,r)=>e.map((e=>s(e,t,r))))(e,t,r):((e,t,r)=>Object.fromEntries(Object.entries(e).map((([e,o])=>[e,s(o,t,r)]))))(e,t,r):e,c=(t,r,o)=>{if(o[t])return o[t];const n=s(r[t],r,o);return(e=>e.match(/^\$\d+$/))(t)?(o[t]=e(n),o[t].sessionId=t):o[t]=e(n,{id:t}),o[t]},f=(e,t)=>{if(e===t)return!0;if(!e&&t||e&&!t)return!1;const r=typeof e;if(r!==typeof t)return!1;if("object"===r){const r=Object.keys(e),o=Object.keys(t);if(r.length!==o.length)return!1;for(let o=0;o<r.length;o++){const n=r[o];if(!f(e[n],t[n]))return!1}return!0}return!1},b=(e,t,r)=>{if(Array.isArray(t))return((e,t,r)=>{if(!Array.isArray(e))return t;const o=[],n=Math.min(e.length,t.length);for(let s=0;s<n;s++)t[s]&&"object"==typeof t[s]&&"object"==typeof e[s]?o[s]=b(e[s],t[s],r):o[s]=t[s];for(let e=n;e<t.length;e++)o[e]=t[e];return o})(e,t,r);const o=Object.keys(e),n=Object.keys(t),s={};for(const o of n)f(e[o],t[o])||(t[o]&&"object"==typeof t[o]&&"object"==typeof e[o]?s[o]=b(e[o],t[o],r):s[o]=t[o]);for(const e of o)e in t||(s[e]=r);return s},a=/^\$del(\d+)$/,i=e=>"string"==typeof e&&e.match(a)?e:e&&"object"==typeof e?Object.values(e).flatMap(i).filter(Boolean):null,l=(e,t)=>{const r=(e=>{const t=i(e).map((e=>parseInt(e.replace(a,"$1")))).reduce(((e,t)=>Math.max(e,t)),0);return t?"$del"+(t+1):"$del"})(t);return{u:b(e,t,r),d:r}},u=(e,t,r)=>t&&e&&"object"==typeof t&&"object"==typeof e?Array.isArray(t)?((e,t,r)=>{const o=e.slice(t.length);for(let n=0;n<t.length;n++)o[n]=u(e[n],t[n],r);return o})(e,t,r):((e,t,r)=>{const o={...e};for(const n of Object.keys(t))t[n]===r?delete o[n]:o[n]=u(e[n],t[n],r);return o})(e,t,r):t;let j=0;const d=()=>{const e=y(j);sessionStorage.setItem("@dependable/session",JSON.stringify(e))},p=()=>{const e=sessionStorage.getItem("@dependable/session");if(!e)throw new Error("No session to restore");sessionStorage.removeItem("@dependable/session");const t=JSON.parse(e);O(t)},y=(e=0)=>((e,t=0)=>{const r={nextId:t,ids:new Map,observables:{}};return Array.from(e).filter((e=>"observable"===e.kind)).sort(((e,t)=>e.id<t.id?-1:e.id>t.id?1:0)).forEach((e=>{n(e,r)})),{nextId:r.nextId,observables:r.observables}})(t(),e),O=e=>{const t=(e=>{const t={};for(const r of Object.keys(e.observables))c(r,e.observables,t);return t})(e);j=e.nextId;for(const e of Object.values(t))r(e)},$=(e,t)=>l(e,t),v=(e,t)=>((e,t)=>u(e,t.u,t.d))(e,t);export{v as applySnapshotDiff,y as createSnapshot,$ as diffSnapshots,p as restoreSession,O as restoreSnapshot,d as saveSession};