UNPKG

resso

Version:

The simplest React state manager

101 lines (97 loc) 3.1 kB
'use strict'; var shim = require('use-sync-external-store/shim'); const __DEV__ = process.env.NODE_ENV !== 'production'; const isObj = (val) => Object.prototype.toString.call(val) === '[object Object]'; let run = (fn) => { fn(); }; const resso = (data) => { if (__DEV__ && !isObj(data)) { throw new Error('object required'); } const state = {}; const actions = {}; Object.keys(data).forEach((key) => { const initVal = data[key]; // actions if (typeof initVal === 'function') { actions[key] = initVal; return; } // state const setters = new Set(); state[key] = { subscribe: (setter) => { setters.add(setter); return () => setters.delete(setter); }, getSnapshot: () => data[key], triggerUpdate: () => setters.forEach((setter) => setter()), }; }); const setKey = (key, val) => { if (key in state) { const newVal = val instanceof Function ? val(data[key]) : val; if (data[key] !== newVal) { data[key] = newVal; run(() => state[key].triggerUpdate()); } return; } if (__DEV__ && key in actions) { throw new Error(`\`${key}\` is an action, can not update`); } if (__DEV__) { throw new Error(`\`${key}\` is not initialized in store`); } }; return new Proxy(Object.assign(() => undefined, data), { get: (_target, key) => { if (key in actions) { return actions[key]; } if (key in state) { try { return shim.useSyncExternalStore(state[key].subscribe, state[key].getSnapshot, state[key].getSnapshot); // eslint-disable-next-line @typescript-eslint/no-unused-vars } catch (err) { return data[key]; } } if (__DEV__) { throw new Error(`\`${key}\` is not initialized in store`); } }, set: (_target, key, val) => { setKey(key, val); return true; }, apply: (_target, _thisArg, [key, updater]) => { // store('key', val) if (typeof key === 'string') { setKey(key, updater); return; } // store({ key: val }) if (isObj(key)) { const newData = key; Object.keys(newData).forEach((k) => { setKey(k, newData[k]); }); return; } // store(prev => next) if (typeof key === 'function') { const newData = key(data); Object.keys(newData).forEach((k) => { setKey(k, newData[k]); }); } }, }); }; resso.config = ({ batch }) => { run = batch; }; module.exports = resso;