Skip to content

Instantly share code, notes, and snippets.

@danybeltran
Last active June 27, 2022 07:25
Show Gist options
  • Save danybeltran/cbf813368836cf697e9d6759577d81c5 to your computer and use it in GitHub Desktop.
Save danybeltran/cbf813368836cf697e9d6759577d81c5 to your computer and use it in GitHub Desktop.
Minified Atomic State for production apps
/** @license Atomic State
* Copyright (c) Dany Beltran
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/ /**
* An observable class that uses the observer pattern
*/ class Observervable{constructor(){this.suscribers={}}async addSubscriber(a,b){a in this.suscribers||(this.suscribers[a]={});let c=Object.keys(this.suscribers[a]).length+1;"__proto__"!==a&&"prototype"!==a?this.suscribers[a][c]=b:console.warn('"prototype" and "__proto__" are not valid message names')}async removeSubscriber(a,c){for(let b in this.suscribers[a])this.suscribers[a][b]===c&&delete this.suscribers[a][b]}async update(a,b){for(let c in this.suscribers[a])await this.suscribers[a][c](b)}}function createObserver(){let a=new Observervable;return{observer:a,notify:function(b,c,d){a.update(b,{storeName:b,hookCall:c,payload:d})}}}const{createContext:a,useCallback:b,useContext:c,useEffect:d,useMemo:e,useRef:f,useState:g}=React,atomObservables={},defaultAtomsValues={},defaultAtomsInAtomic={},defaultFiltersInAtomic={},usedKeys={},defaultFiltersValues={},atomsEffectsCleanupFunctons={},pendingAtoms={},atomicStateContext=a({prefix:"store"}),AtomicState=({children:i,atoms:f,filters:g,prefix:h="store"})=>{let j=c(atomicStateContext),a=void 0===h?j.prefix:h;if(f)for(let b in f)void 0===defaultAtomsValues[`${a}-${b}`]&&(defaultAtomsValues[`${a}-${b}`]=f[b],defaultAtomsInAtomic[`${a}-${b}`]=!0);if(g)for(let d in g)void 0===defaultFiltersValues[`${a}-${d}`]&&(defaultFiltersValues[`${a}-${d}`]=g[d],defaultFiltersInAtomic[`${a}-${d}`]=!0);return e(()=>i,[h]),React.createElement(atomicStateContext.Provider,{value:{prefix:a}},i)},resolvedAtoms={};function useAtomCreate(a){let{effects:v=[],persist:o,localStoragePersistence:p,sync:w=!0,onSync:x=()=>{}}=a,{prefix:q}=c(atomicStateContext),h=q+"-"+a.name,[y,z]=g(!1),r=p||o,l=e(()=>`${Math.random()}`.split(".")[1],[]);h in atomsEffectsCleanupFunctons||(atomsEffectsCleanupFunctons[h]=[]);let A=void 0!==a.default,j=function(){let e=void 0===defaultAtomsValues[h]&&"function"==typeof a.default,c=e?a.default():a.default instanceof Promise?a.default:void 0,d=c instanceof Promise,b=A&& void 0===defaultAtomsValues[h]?d?a.default:void 0!==c?c:a.default:defaultAtomsValues[h];try{return r?"undefined"!=typeof localStorage&&(void 0===defaultAtomsValues[h]||defaultAtomsInAtomic[h])&&(defaultAtomsInAtomic[h]=!1,defaultAtomsValues[h]=d?void 0:b):void 0===defaultAtomsValues[h]&&(defaultAtomsValues[h]=b),r&&"undefined"!=typeof localStorage&& void 0!==localStorage[h]?defaultAtomsValues[h]:d?void 0:b}catch(f){return b}}(),[s,B]=g(()=>{try{return JSON.parse(localStorage[h])}catch(a){return j}}),[i,C]=g((j instanceof Promise||"function"==typeof j)&& void 0===defaultAtomsValues[h]?void 0:(defaultAtomsValues[h]=j,j));pendingAtoms[h]||(pendingAtoms[h]=0),atomObservables[h]||(atomObservables[h]=createObserver());let{observer:D,notify:t}=atomObservables[h],[m,E]=g(!1),n=f(!1),k=b(async d=>{let e=!1,b="function"==typeof d?await d(i):d,f=await (async()=>{try{return JSON.stringify(b)!==JSON.stringify(defaultAtomsValues[h])}catch(a){return!1}})(),g=await (async()=>{try{if("function"==typeof defaultAtomsValues[h])return!0;if(JSON.stringify(b)===JSON.stringify(a.default)&&!resolvedAtoms[h])return resolvedAtoms[h]=!0,!0}catch(c){return!0}})(),j="function"==typeof defaultAtomsValues[h]||f||g;try{for(let o of atomsEffectsCleanupFunctons[h])o()}catch(q){}finally{atomsEffectsCleanupFunctons[h]=[];try{if(m||n.current)for(let p of v){let c=await p({previous:i,state:b,dispatch:k});void 0===c||c?"function"==typeof c&&atomsEffectsCleanupFunctons[h].push(c):e=!0}}catch(r){E(!0)}finally{e||(defaultAtomsValues[h]=b,j&&t(h,l,b),C(b))}}},[l,t,m,n,i,a.name]);d(()=>{async function a(){if("undefined"!=typeof localStorage&& void 0!==localStorage[h])try{if(localStorage[h]!==JSON.stringify(defaultAtomsValues[h])){let a=JSON.parse(localStorage[h]);k(a),await x(a)}}catch(b){}}if(r&&"undefined"!=typeof window){let b=void 0!==window.addEventListener;if(b&&w)return window.addEventListener("storage",a),()=>{window.removeEventListener("storage",a)}}return()=>{}},[a.name]),d(()=>{if(void 0!==s&&!n.current){let a=setTimeout(()=>{k(s),z(!0)},0),b=setTimeout(()=>{B(void 0),n.current=!0},0);return()=>{clearTimeout(a),clearTimeout(b)}}},[s,k,n]),d(()=>{async function b(){var b;if(void 0===defaultAtomsValues[h]&&"function"==typeof a.default){if(0===pendingAtoms[h]){pendingAtoms[h]+=1;let c=void 0!==a.default?(async()=>"function"==typeof a.default?a.default():a.default)():void 0;void 0!==c&&c.then(a=>{defaultAtomsValues[h]=a,t(h,l,defaultAtomsValues[h]),k(a)})}else pendingAtoms[h]+=1,(i||defaultAtomsValues[h])&&(null===(b=atomObservables[h])|| void 0===b||b.notify(h,l,void 0!==i?i:defaultAtomsValues[h]))}}b()},[i,a.default,k,a.name,l]),d(()=>()=>{pendingAtoms[h]=0},[a.name]),d(()=>{let a=async a=>{a.hookCall!==l&&C(a.payload)};return D.addSubscriber(h,a),()=>{D.removeSubscriber(h,a)}},[m]),d(()=>{if("undefined"!=typeof localStorage){let a="undefined"!=typeof window,b=a&&"addEventListener"in window;r&&(!b||y)?localStorage[h]!==JSON.stringify(defaultAtomsValues[h])&&localStorage.setItem(h,JSON.stringify(i)):void 0===localStorage[h]||r||localStorage.removeItem(h)}},[a.name,r,i]);let F=e(()=>a.actions||{},[]),u=e(()=>Object.fromEntries(Object.keys(F).map(a=>[a,b=>F[a]({args:b,state:i,dispatch:k})])),[i]);return[i,k,u]}const ignoredAtomKeyWarnings={};function atom(a){a.ignoreKeyWarning&&(ignoredAtomKeyWarnings[a.name]=!0),!ignoredAtomKeyWarnings[a.name]&&a.name in usedKeys&&console.warn(`Duplicate atom name '${a.name}' found. This could lead to bugs in atom state. To remove this warning add 'ignoreKeyWarning: true' to all atom definitions that use the name '${a.name}'.`),usedKeys[a.name]=!0;let b=()=>useAtomCreate(a);return b["atom-name"]=a.name,b["init-object"]=a,b}const createAtom=atom,objectFilters={},resolvedFilters={},filterObservables={},subscribedFilters={};function filter(f){let{name:h="",get:i}=f,a=()=>{let n={};a.deps={};let o={},p={},{prefix:j}=c(atomicStateContext),l=j+"-"+h;filterObservables[l]||(filterObservables[l]=createObserver());let q=filterObservables[l],r=b(function(a,b){q.notify(l,a,b)},[j]),s=e(()=>({get:b=>("function"!=typeof b?(n[`${j}-${b.name}`]=!0,o[`${j}-${b.name}`]=defaultAtomsValues[`${j}-${b.name}`],a.deps=Object.assign(Object.assign({},a.deps),{[`${j}-${b.name}`]:!0})):(n[`${j}-${b["atom-name"]}`]=!0,o[`${j}-${b["atom-name"]}`]=defaultAtomsValues[`${j}-${b["atom-name"]}`],a.deps=Object.assign(Object.assign({},a.deps),{[`${j}-${b["atom-name"]}`]:!0})),"function"!=typeof b?defaultAtomsValues[`${j}-${b.name}`]:defaultAtomsValues[`${j}-${b["atom-name"]}`]),read:a=>("function"!=typeof a?p[`${j}-${a.name}`]=!0:p[`${j}-${a["filter-name"]}`]=!0,"function"!=typeof a?defaultFiltersValues[`${j}-${a.name}`]:defaultFiltersValues[`${j}-${a["filter-name"]}`])}),[j]),t=e(()=>Math.random(),[]),k=function(){try{return void 0!==defaultFiltersValues[l]||defaultFiltersInAtomic[l]?(()=>{let a=setTimeout(()=>{r(t,defaultFiltersValues[l]),clearTimeout(a)},0);return defaultFiltersValues[l]})():(()=>{defaultFiltersValues[l]=f.default;let a;try{if(a=i(s),resolvedFilters[l]=!0,void 0===a)return f.default;(async()=>{defaultFiltersValues[l]=await a})()}catch(b){}finally{return a}})()}catch(a){return f.default}}(),[m,u]=g(k instanceof Promise|| void 0===k?f.default:(defaultFiltersValues[l]=k,k));async function v(a){if("function"==typeof a.payload||JSON.stringify(a.payload)!==JSON.stringify(o[`${a.storeName}`])){`${a.storeName}` in o&&(o[`${a.storeName}`]=a.payload);try{let b=await i(s);defaultFiltersValues[l]=b;let c=setTimeout(()=>{u(b),r(t,b),clearTimeout(c)},0)}catch(d){}}}async function w(a){let{storeName:c,payload:b}=a;t!==a.hookCall&&u(b)}return d(()=>{k instanceof Promise&&k.then(a=>{defaultFiltersValues[l]=a,u(a)})},[k]),d(()=>{var a,b;if(!subscribedFilters[l]){for(let c in subscribedFilters[l]=!0,defaultFiltersInAtomic[l]&&i(s),n)null===(a=atomObservables[c])|| void 0===a||a.observer.addSubscriber(c,v);for(let d in p)null===(b=filterObservables[d])|| void 0===b||b.observer.addSubscriber(d,v);return()=>{var a,b;for(let c in defaultFiltersInAtomic[l]=!0,n)null===(a=atomObservables[c])|| void 0===a||a.observer.removeSubscriber(c,v);for(let d in p)null===(b=filterObservables[d])|| void 0===b||b.observer.removeSubscriber(d,v)}}},[f,j]),d(()=>{var a;return null===(a=q.observer)|| void 0===a||a.addSubscriber(l,w),()=>{var a;subscribedFilters[l]=!1,resolvedFilters[l]=!1,null===(a=null==q?void 0:q.observer)|| void 0===a||a.removeSubscriber(l,w)}},[f,j]),m};return a["filter-name"]=h,a["init-object"]=f,a}function useFilter(a){let{prefix:b}=c(atomicStateContext);return"function"!=typeof a?(void 0===objectFilters[`${b}-${a.name}`]?objectFilters[`${b}-${a.name}`]=filter(a):objectFilters[`${b}-${a.name}`]["init-object"]!==a&&(objectFilters[`${b}-${a.name}`]=filter(a)),objectFilters[`${b}-${a.name}`]()):a()}const objectAtoms={};function useAtom(a){return"function"!=typeof a&&(void 0===objectAtoms[a.name]?objectAtoms[a.name]=createAtom(a):objectAtoms[a.name]["init-object"]!==a&&(objectAtoms[a.name]=createAtom(a))),"function"!=typeof a?objectAtoms[a.name]():a()}function useValue(a){return useAtom(a)[0]}const useAtomValue=useValue;function useDispatch(a){return useAtom(a)[1]}const useAtomDispatch=useDispatch;function useActions(a){return useAtom(a)[2]}const useAtomActions=useActions,storageOvservable=(()=>{let a=new Observervable;return a})();function useStorage(a){let[b,c]=g(a||{});async function e(){let b={};if("undefined"!=typeof localStorage){for(let a in localStorage)if(!a.match(/clear|getItem|key|length|removeItem|setItem/))try{void 0!==localStorage[a]&&(b[a]=JSON.parse(localStorage[a]))}catch(d){b[a]=localStorage[a]}}c(b)}return d(()=>{e()},[]),d(()=>(storageOvservable.addSubscriber("store-changed",e),()=>{storageOvservable.removeSubscriber("store-changed",e)}),[]),b}const storage={set(b,a){"undefined"!=typeof localStorage&&"function"==typeof localStorage.setItem&&(localStorage.setItem(b,JSON.stringify(a)),storageOvservable.update("store-changed",a))},async remove(a){"undefined"!=typeof localStorage&&"function"==typeof localStorage.removeItem&&(localStorage.removeItem(a),storageOvservable.update("store-changed",{}))},get(b,a=null){if("undefined"==typeof localStorage)return a;if("function"==typeof localStorage.getItem)try{return JSON.parse(localStorage.getItem(b))}catch(c){return a}else try{return JSON.parse(localStorage[b])}catch(d){return a}}};function useStorageItem(c,a=null){let[b,e]=g(a),f=()=>{if("undefined"!=typeof localStorage&&JSON.stringify(localStorage[c])!==JSON.stringify(a))try{e(JSON.parse(localStorage[c]))}catch(b){e(a)}};return d(()=>(f(),storageOvservable.addSubscriber("store-changed",f),()=>{storageOvservable.removeSubscriber("store-changed",f)}),[]),b}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment