🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@statx/core

Package Overview
Dependencies
Maintainers
1
Versions
60
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@statx/core - npm Package Compare versions

Comparing version
1.0.22
to
1.0.27
+1
-1
build/index.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"index.js","sources":["../src/core.ts"],"sourcesContent":["import {\r\n ComputedInternal,\r\n Listner,\r\n StateType,\r\n Settings,\r\n StateVariants,\r\n Action,\r\n Options,\r\n ComputedInternalOptions,\r\n Nullable,\r\n StatlessFunc,\r\n GetStatlessFunc,\r\n HistoryInternal,\r\n State,\r\n Computed,\r\n Func,\r\n UnSubscribe,\r\n CommonInternal,\r\n StateInternal,\r\n SetterFunc,\r\n ActionOptions,\r\n} from './types.js'\r\n\r\nlet isNotifying = false\r\nlet isActionNow = false\r\nlet recording: Set<StateInternal> | undefined\r\n\r\nconst defaultName = 'Unnamed state'\r\nconst names = new Set()\r\nconst requesters: ComputedInternal[] = []\r\nconst states2notify = new Set<StateVariants>()\r\nconst settings: Settings = {\r\n historyLength: 5,\r\n}\r\n\r\nexport const getHistoryValue = (state: StateVariants): unknown => {\r\n return state.history[state.historyCursor]\r\n}\r\nconst pushHistory = <T extends HistoryInternal>(state: T, value: unknown) => {\r\n const cursorHistory = state.historyCursor\r\n state.historyCursor = (cursorHistory + 1) % state.history.length\r\n state.history[state.historyCursor] = value\r\n}\r\n\r\nconst getName = (name?: string): string => {\r\n if (name && names.has(name)) {\r\n console.error(`Name ${name} already used! Replaced to undefined`)\r\n return defaultName\r\n }\r\n if (name) {\r\n return name\r\n }\r\n return defaultName\r\n}\r\n\r\nexport const setSetting = (data: Partial<Settings>) => {\r\n Object.assign(settings, data)\r\n}\r\n\r\nconst getComputed = (state: CommonInternal | ComputedInternal) => {\r\n if ('reducer' in state) {\r\n return state\r\n }\r\n}\r\n\r\nconst isFunction = (v: unknown): v is Func => {\r\n return typeof v === 'function'\r\n}\r\n\r\nconst isDontNeedRecalc = (state: CommonInternal, prevState: unknown): boolean => {\r\n return state.hasParentUpdates === false && prevState !== undefined\r\n}\r\n\r\nconst getComputedValue = (state: ComputedInternal): unknown => {\r\n try {\r\n const prevState = getHistoryValue(state)\r\n\r\n if (isDontNeedRecalc(state, prevState)) {\r\n if (recording) {\r\n state.depends.forEach((item) => {\r\n recording?.add(item)\r\n })\r\n }\r\n return prevState\r\n }\r\n\r\n assert(state.isComputing, `Loops dosen't allows. Name: ${state.name ?? 'Unnamed state'}`)\r\n\r\n requesters.push(state)\r\n state.depends.forEach((item) => {\r\n item.childs.delete(state)\r\n })\r\n state.depends.clear()\r\n state.isComputing = true\r\n const value = state.reducer(prevState ?? state.initial)\r\n state.isComputing = false\r\n state.hasParentUpdates = false\r\n\r\n requesters.pop()\r\n pushHistory(state, value)\r\n\r\n return value\r\n } catch (e) {\r\n console.error((e as Error).message)\r\n return undefined\r\n }\r\n}\r\n\r\nconst getValue = (state: CommonInternal) => {\r\n const reducer = getComputed(state)\r\n try {\r\n const lastRequester = requesters.at(-1)\r\n if (lastRequester && !state.childs.has(lastRequester)) {\r\n state.childs.add(lastRequester)\r\n lastRequester.depends.add(state)\r\n }\r\n if (reducer) {\r\n return getComputedValue(reducer)\r\n }\r\n return getHistoryValue(state)\r\n } finally {\r\n if (recording && !reducer) {\r\n recording.add(state)\r\n }\r\n }\r\n}\r\n\r\nconst getValueOfSetterFunction = (state: CommonInternal, value: SetterFunc): unknown => {\r\n const prevValue = getHistoryValue(state)\r\n return value(prevValue)\r\n}\r\n\r\nconst setValue = (state: CommonInternal, value: unknown): void => {\r\n const newValue = isFunction(value) ? getValueOfSetterFunction(state, value) : value\r\n\r\n if (newValue === getHistoryValue(state)) {\r\n return\r\n }\r\n pushHistory(state, newValue)\r\n invalidateSubtree(state)\r\n notifySubscribers()\r\n}\r\n\r\n/**\r\n * Mark all subtree is non actual.\r\n * Collect all nodes to notify subscribers im microtask queue.\r\n */\r\nconst invalidateSubtree = (state: CommonInternal) => {\r\n const stack: CommonInternal[] = [state]\r\n\r\n while (stack.length) {\r\n const st = stack.pop()\r\n st.childs.forEach((it) => stack.push(it))\r\n st.hasParentUpdates = true\r\n if (st.subscribes.size) {\r\n states2notify.add(st)\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Notify all collected subscribers once in microtask queue\r\n */\r\nconst notifySubscribers = () => {\r\n if (isNotifying === false) {\r\n isNotifying = true\r\n queueMicrotask(() => {\r\n // Нужно обновить дерево\r\n states2notify.forEach((state) => {\r\n try {\r\n state.subscribes.forEach((listner) => {\r\n return listner(getValue(state))\r\n })\r\n } catch (e) {\r\n console.error('Error in subscriber function of:', state.name)\r\n }\r\n })\r\n states2notify.clear()\r\n isNotifying = false\r\n })\r\n }\r\n}\r\n\r\n/**\r\n * Start collecting all non computed states.\r\n *\r\n * Helper for render adapters.\r\n */\r\nexport const startRecord = () => {\r\n recording = new Set()\r\n}\r\n\r\n/**\r\n * Flush all collected non computed states.\r\n */\r\nexport const flushStates = (): Set<StateInternal> => {\r\n const data = recording\r\n recording = undefined\r\n return data\r\n}\r\n\r\nexport const subscribe = (state: CommonInternal | CommonInternal, listner: Listner): UnSubscribe => {\r\n /**\r\n * Если значение стейта ниразу не расчитывалось, его нужно обновить\r\n * Если подписываемся на вычисляемый стэйт, то нужно узнать всех родителей\r\n * Родители могут меняться, поэтому после каждого вычисления нужно обновлять зависимости дерева\r\n *\r\n * При отписке нужно оповестить всех на кого были опдписанты о том что мы отписались\r\n *\r\n */\r\n\r\n if (state.subscribes.has(listner)) {\r\n return () => ({})\r\n }\r\n\r\n const computedState = getComputed(state)\r\n // Нужно актуализировать в родилеях зависимость\r\n if (computedState) {\r\n getComputedValue(computedState)\r\n state.depends.forEach((parent) => parent.childs.add(state))\r\n }\r\n\r\n state.subscribes.add(listner)\r\n\r\n return () => {\r\n state.subscribes.delete(listner)\r\n if (state.subscribes.size === 0) {\r\n state.depends.forEach((parent) => parent.childs.delete(state))\r\n }\r\n }\r\n}\r\n\r\nconst assert = (condtion: boolean, msg: string) => {\r\n if (condtion) {\r\n throw new Error(msg)\r\n }\r\n}\r\n\r\n/**\r\n *\r\n * @param value - Reducer or value\r\n * @param name - name of state. For loggin or easy debug\r\n * @returns State<T>\r\n */\r\nexport function state<T extends StateType = StateType>(value: T, options?: Options): State<T> {\r\n assert(isFunction(value), 'Function not allowed in state')\r\n\r\n const data: CommonInternal = {\r\n childs: new Set(),\r\n depends: new Set(),\r\n history: Array.from({length: settings.historyLength}),\r\n historyCursor: -1,\r\n name: getName(options?.name),\r\n subscribes: new Set(),\r\n hasParentUpdates: undefined,\r\n }\r\n\r\n setValue(data, value)\r\n\r\n const publicApi = function () {\r\n return getValue(data)\r\n }\r\n\r\n Object.defineProperty(publicApi, 'name', {value: data.name})\r\n publicApi.subscribe = (listner: Listner) => subscribe(data, listner)\r\n publicApi.set = (value: T) => setValue(data, value)\r\n publicApi._internal = data\r\n\r\n return publicApi as State<T>\r\n}\r\n\r\nexport const computed = <\r\n T extends StateType = -1,\r\n S extends StatlessFunc<T> = StatlessFunc<T>,\r\n O extends Nullable<ComputedInternalOptions> = Nullable<ComputedInternalOptions>,\r\n>(\r\n value: GetStatlessFunc<T, S, O>,\r\n options?: O,\r\n): Computed<T> => {\r\n const data: ComputedInternal = {\r\n childs: new Set(),\r\n depends: new Set(),\r\n hasParentUpdates: true,\r\n history: Array.from({length: settings.historyLength}),\r\n historyCursor: -1,\r\n initial: options?.initial as ReturnType<typeof value> | undefined,\r\n isComputing: false,\r\n name: getName(options?.name),\r\n reducer: value,\r\n subscribes: new Set(),\r\n }\r\n\r\n const publicApi = function () {\r\n return getValue(data)\r\n }\r\n\r\n Object.defineProperty(publicApi, 'name', {value: data.name})\r\n publicApi.subscribe = (listner: Listner<T>) => subscribe(data, listner as Listner)\r\n publicApi._internal = data\r\n\r\n return publicApi as Computed<T>\r\n}\r\n\r\n/**\r\n * ## Action state\r\n *\r\n * @param value - Action function\r\n * @param name\r\n */\r\nexport const action = <T extends unknown[]>(\r\n value: (...args: T) => void,\r\n options?: ActionOptions,\r\n): Action<T> => {\r\n return {\r\n run: (...args: T) => {\r\n isActionNow = true\r\n value(...args)\r\n isActionNow = false\r\n return this\r\n },\r\n name: getName(options?.name),\r\n onAction: options?.onAction,\r\n }\r\n}\r\n"],"names":["_this","this","recording","isNotifying","names","Set","requesters","states2notify","getHistoryValue","state","history","historyCursor","pushHistory","value","length","getName","name","has","console","error","defaultName","getComputed","isFunction","v","getComputedValue","prevState","hasParentUpdates","undefined","isDontNeedRecalc","depends","forEach","item","add","assert","isComputing","push","childs","delete","clear","reducer","initial","pop","e","message","getValue","lastRequester","at","setValue","newValue","getValueOfSetterFunction","invalidateSubtree","notifySubscribers","stack","st","it","subscribes","size","queueMicrotask","listner","subscribe","computedState","parent","condtion","msg","Error","options","run","slice","call","arguments","onAction","data","Array","from","publicApi","Object","defineProperty","_internal","set"],"mappings":"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"}
{"version":3,"file":"index.js","sources":["../src/core.ts"],"sourcesContent":["import {\r\n ComputedInternal,\r\n Listner,\r\n StateType,\r\n Settings,\r\n StateVariants,\r\n Action,\r\n Options,\r\n ComputedInternalOptions,\r\n Nullable,\r\n StatlessFunc,\r\n GetStatlessFunc,\r\n HistoryInternal,\r\n State,\r\n Computed,\r\n Func,\r\n UnSubscribe,\r\n CommonInternal,\r\n StateInternal,\r\n SetterFunc,\r\n ActionOptions,\r\n} from './types.js'\r\n\r\nlet isNotifying = false\r\nlet isActionNow = false\r\nlet recording: Set<StateInternal> | undefined\r\n\r\nconst defaultName = 'Unnamed state'\r\nconst names = new Set()\r\nconst requesters: ComputedInternal[] = []\r\nconst states2notify = new Set<StateVariants>()\r\nconst settings: Settings = {\r\n historyLength: 5,\r\n}\r\n\r\nexport const getHistoryValue = (state: StateVariants): unknown => {\r\n return state.history[state.historyCursor]\r\n}\r\nconst pushHistory = <T extends HistoryInternal>(state: T, value: unknown) => {\r\n const cursorHistory = state.historyCursor\r\n state.historyCursor = (cursorHistory + 1) % state.history.length\r\n state.history[state.historyCursor] = value\r\n}\r\n\r\nconst getName = (name?: string): string => {\r\n if (name && names.has(name)) {\r\n console.error(`Name ${name} already used! Replaced to undefined`)\r\n return defaultName\r\n }\r\n if (name) {\r\n return name\r\n }\r\n return defaultName\r\n}\r\n\r\nexport const setSetting = (data: Partial<Settings>) => {\r\n Object.assign(settings, data)\r\n}\r\n\r\nconst getComputed = (state: CommonInternal | ComputedInternal) => {\r\n if ('reducer' in state) {\r\n return state\r\n }\r\n}\r\n\r\nconst isFunction = (v: unknown): v is Func => {\r\n return typeof v === 'function'\r\n}\r\n\r\nconst isDontNeedRecalc = (state: CommonInternal, prevState: unknown): boolean => {\r\n return state.hasParentUpdates === false && prevState !== undefined\r\n}\r\n\r\nconst getComputedValue = (state: ComputedInternal): unknown => {\r\n try {\r\n const prevState = getHistoryValue(state)\r\n\r\n if (isDontNeedRecalc(state, prevState)) {\r\n if (recording) {\r\n state.depends.forEach((item) => {\r\n recording?.add(item)\r\n })\r\n }\r\n return prevState\r\n }\r\n\r\n assert(state.isComputing, `Loops dosen't allows. Name: ${state.name ?? 'Unnamed state'}`)\r\n\r\n requesters.push(state)\r\n state.depends.forEach((item) => {\r\n item.childs.delete(state)\r\n })\r\n state.depends.clear()\r\n state.isComputing = true\r\n const value = state.reducer(prevState ?? state.initial)\r\n state.isComputing = false\r\n state.hasParentUpdates = false\r\n\r\n requesters.pop()\r\n pushHistory(state, value)\r\n\r\n return value\r\n } catch (e) {\r\n console.error((e as Error).message)\r\n return undefined\r\n }\r\n}\r\n\r\nconst getValue = (state: CommonInternal) => {\r\n const reducer = getComputed(state)\r\n try {\r\n const lastRequester = requesters.at(-1)\r\n if (lastRequester && !state.childs.has(lastRequester)) {\r\n state.childs.add(lastRequester)\r\n lastRequester.depends.add(state)\r\n }\r\n if (reducer) {\r\n return getComputedValue(reducer)\r\n }\r\n return getHistoryValue(state)\r\n } finally {\r\n if (recording && !reducer) {\r\n recording.add(state)\r\n }\r\n }\r\n}\r\n\r\nconst getValueOfSetterFunction = (state: CommonInternal, value: SetterFunc): unknown => {\r\n const prevValue = getHistoryValue(state)\r\n return value(prevValue)\r\n}\r\n\r\nconst setValue = (state: CommonInternal, value: unknown): void => {\r\n const newValue = isFunction(value) ? getValueOfSetterFunction(state, value) : value\r\n\r\n if (newValue === getHistoryValue(state)) {\r\n return\r\n }\r\n pushHistory(state, newValue)\r\n invalidateSubtree(state)\r\n notifySubscribers()\r\n}\r\n\r\n/**\r\n * Mark all subtree is non actual.\r\n * Collect all nodes to notify subscribers im microtask queue.\r\n */\r\nconst invalidateSubtree = (state: CommonInternal) => {\r\n const stack: CommonInternal[] = [state]\r\n\r\n while (stack.length) {\r\n const st = stack.pop()\r\n st.childs.forEach((it) => stack.push(it))\r\n st.hasParentUpdates = true\r\n if (st.subscribes.size) {\r\n states2notify.add(st)\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Notify all collected subscribers once in microtask queue\r\n */\r\nconst notifySubscribers = () => {\r\n if (isNotifying === false) {\r\n isNotifying = true\r\n queueMicrotask(() => {\r\n // Нужно обновить дерево\r\n states2notify.forEach((state) => {\r\n try {\r\n state.subscribes.forEach((listner) => {\r\n return listner(getValue(state))\r\n })\r\n } catch (e) {\r\n console.error('Error in subscriber function of:', state.name)\r\n }\r\n })\r\n states2notify.clear()\r\n isNotifying = false\r\n })\r\n }\r\n}\r\n\r\n/**\r\n * Start collecting all non computed states.\r\n *\r\n * Helper for render adapters.\r\n */\r\nexport const startRecord = () => {\r\n recording = new Set()\r\n}\r\n\r\n/**\r\n * Flush all collected non computed states.\r\n */\r\nexport const flushStates = (): Set<StateInternal> => {\r\n const data = recording\r\n recording = undefined\r\n return data\r\n}\r\n\r\nexport const subscribe = (state: CommonInternal | CommonInternal, listner: Listner): UnSubscribe => {\r\n /**\r\n * Если значение стейта ниразу не расчитывалось, его нужно обновить\r\n * Если подписываемся на вычисляемый стэйт, то нужно узнать всех родителей\r\n * Родители могут меняться, поэтому после каждого вычисления нужно обновлять зависимости дерева\r\n *\r\n * При отписке нужно оповестить всех на кого были опдписанты о том что мы отписались\r\n *\r\n */\r\n\r\n if (state.subscribes.has(listner)) {\r\n return () => ({})\r\n }\r\n\r\n const computedState = getComputed(state)\r\n // Нужно актуализировать в родилеях зависимость\r\n if (computedState) {\r\n getComputedValue(computedState)\r\n state.depends.forEach((parent) => parent.childs.add(state))\r\n }\r\n\r\n state.subscribes.add(listner)\r\n\r\n return () => {\r\n state.subscribes.delete(listner)\r\n if (state.subscribes.size === 0) {\r\n state.depends.forEach((parent) => parent.childs.delete(state))\r\n }\r\n }\r\n}\r\n\r\nconst assert = (condtion: boolean, msg: string) => {\r\n if (condtion) {\r\n throw new Error(msg)\r\n }\r\n}\r\n\r\n/**\r\n *\r\n * @param value - Reducer or value\r\n * @param name - name of state. For loggin or easy debug\r\n * @returns State<T>\r\n */\r\nexport function state<T extends StateType = StateType>(value: T, options?: Options): State<T> {\r\n assert(isFunction(value), 'Function not allowed in state')\r\n\r\n const data: CommonInternal = {\r\n childs: new Set(),\r\n depends: new Set(),\r\n history: Array.from({length: settings.historyLength}),\r\n historyCursor: -1,\r\n name: getName(options?.name),\r\n subscribes: new Set(),\r\n hasParentUpdates: undefined,\r\n }\r\n\r\n setValue(data, value)\r\n\r\n const publicApi = function () {\r\n return getValue(data)\r\n }\r\n\r\n Object.defineProperty(publicApi, 'name', {value: data.name})\r\n publicApi.subscribe = (listner: Listner) => subscribe(data, listner)\r\n publicApi.set = (value: T) => setValue(data, value)\r\n publicApi._internal = data\r\n\r\n return publicApi as State<T>\r\n}\r\n\r\nexport const computed = <\r\n T extends StateType = -1,\r\n S extends StatlessFunc<T> = StatlessFunc<T>,\r\n O extends Nullable<ComputedInternalOptions> = Nullable<ComputedInternalOptions>,\r\n>(\r\n value: GetStatlessFunc<T, S, O>,\r\n options?: O,\r\n): Computed<T> => {\r\n const data: ComputedInternal = {\r\n childs: new Set(),\r\n depends: new Set(),\r\n hasParentUpdates: true,\r\n history: Array.from({length: settings.historyLength}),\r\n historyCursor: -1,\r\n initial: options?.initial as ReturnType<typeof value> | undefined,\r\n isComputing: false,\r\n name: getName(options?.name),\r\n reducer: value,\r\n subscribes: new Set(),\r\n }\r\n\r\n const publicApi = function () {\r\n return getValue(data)\r\n }\r\n\r\n Object.defineProperty(publicApi, 'name', {value: data.name})\r\n publicApi.subscribe = (listner: Listner<T>) => subscribe(data, listner as Listner)\r\n publicApi._internal = data\r\n\r\n return publicApi as Computed<T>\r\n}\r\n\r\n/**\r\n * Action state\r\n * @param value - Action function\r\n * @param name\r\n */\r\nexport const action = <T extends unknown[]>(\r\n value: (...args: T) => void,\r\n options?: ActionOptions,\r\n): Action<T> => {\r\n return {\r\n run: (...args: T) => {\r\n isActionNow = true\r\n value(...args)\r\n isActionNow = false\r\n return this\r\n },\r\n name: getName(options?.name),\r\n onAction: options?.onAction,\r\n }\r\n}\r\n"],"names":["_this","this","recording","isNotifying","names","Set","requesters","states2notify","getHistoryValue","state","history","historyCursor","pushHistory","value","length","getName","name","has","console","error","defaultName","getComputed","isFunction","v","getComputedValue","prevState","hasParentUpdates","undefined","isDontNeedRecalc","depends","forEach","item","add","assert","isComputing","push","childs","delete","clear","reducer","initial","pop","e","message","getValue","lastRequester","at","setValue","newValue","getValueOfSetterFunction","invalidateSubtree","notifySubscribers","stack","st","it","subscribes","size","queueMicrotask","listner","subscribe","computedState","parent","condtion","msg","Error","options","run","slice","call","arguments","onAction","data","Array","from","publicApi","Object","defineProperty","_internal","set"],"mappings":"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"}

@@ -1,1 +0,1 @@

{"version":3,"file":"index.modern.mjs","sources":["../src/core.ts"],"sourcesContent":["import {\r\n ComputedInternal,\r\n Listner,\r\n StateType,\r\n Settings,\r\n StateVariants,\r\n Action,\r\n Options,\r\n ComputedInternalOptions,\r\n Nullable,\r\n StatlessFunc,\r\n GetStatlessFunc,\r\n HistoryInternal,\r\n State,\r\n Computed,\r\n Func,\r\n UnSubscribe,\r\n CommonInternal,\r\n StateInternal,\r\n SetterFunc,\r\n ActionOptions,\r\n} from './types.js'\r\n\r\nlet isNotifying = false\r\nlet isActionNow = false\r\nlet recording: Set<StateInternal> | undefined\r\n\r\nconst defaultName = 'Unnamed state'\r\nconst names = new Set()\r\nconst requesters: ComputedInternal[] = []\r\nconst states2notify = new Set<StateVariants>()\r\nconst settings: Settings = {\r\n historyLength: 5,\r\n}\r\n\r\nexport const getHistoryValue = (state: StateVariants): unknown => {\r\n return state.history[state.historyCursor]\r\n}\r\nconst pushHistory = <T extends HistoryInternal>(state: T, value: unknown) => {\r\n const cursorHistory = state.historyCursor\r\n state.historyCursor = (cursorHistory + 1) % state.history.length\r\n state.history[state.historyCursor] = value\r\n}\r\n\r\nconst getName = (name?: string): string => {\r\n if (name && names.has(name)) {\r\n console.error(`Name ${name} already used! Replaced to undefined`)\r\n return defaultName\r\n }\r\n if (name) {\r\n return name\r\n }\r\n return defaultName\r\n}\r\n\r\nexport const setSetting = (data: Partial<Settings>) => {\r\n Object.assign(settings, data)\r\n}\r\n\r\nconst getComputed = (state: CommonInternal | ComputedInternal) => {\r\n if ('reducer' in state) {\r\n return state\r\n }\r\n}\r\n\r\nconst isFunction = (v: unknown): v is Func => {\r\n return typeof v === 'function'\r\n}\r\n\r\nconst isDontNeedRecalc = (state: CommonInternal, prevState: unknown): boolean => {\r\n return state.hasParentUpdates === false && prevState !== undefined\r\n}\r\n\r\nconst getComputedValue = (state: ComputedInternal): unknown => {\r\n try {\r\n const prevState = getHistoryValue(state)\r\n\r\n if (isDontNeedRecalc(state, prevState)) {\r\n if (recording) {\r\n state.depends.forEach((item) => {\r\n recording?.add(item)\r\n })\r\n }\r\n return prevState\r\n }\r\n\r\n assert(state.isComputing, `Loops dosen't allows. Name: ${state.name ?? 'Unnamed state'}`)\r\n\r\n requesters.push(state)\r\n state.depends.forEach((item) => {\r\n item.childs.delete(state)\r\n })\r\n state.depends.clear()\r\n state.isComputing = true\r\n const value = state.reducer(prevState ?? state.initial)\r\n state.isComputing = false\r\n state.hasParentUpdates = false\r\n\r\n requesters.pop()\r\n pushHistory(state, value)\r\n\r\n return value\r\n } catch (e) {\r\n console.error((e as Error).message)\r\n return undefined\r\n }\r\n}\r\n\r\nconst getValue = (state: CommonInternal) => {\r\n const reducer = getComputed(state)\r\n try {\r\n const lastRequester = requesters.at(-1)\r\n if (lastRequester && !state.childs.has(lastRequester)) {\r\n state.childs.add(lastRequester)\r\n lastRequester.depends.add(state)\r\n }\r\n if (reducer) {\r\n return getComputedValue(reducer)\r\n }\r\n return getHistoryValue(state)\r\n } finally {\r\n if (recording && !reducer) {\r\n recording.add(state)\r\n }\r\n }\r\n}\r\n\r\nconst getValueOfSetterFunction = (state: CommonInternal, value: SetterFunc): unknown => {\r\n const prevValue = getHistoryValue(state)\r\n return value(prevValue)\r\n}\r\n\r\nconst setValue = (state: CommonInternal, value: unknown): void => {\r\n const newValue = isFunction(value) ? getValueOfSetterFunction(state, value) : value\r\n\r\n if (newValue === getHistoryValue(state)) {\r\n return\r\n }\r\n pushHistory(state, newValue)\r\n invalidateSubtree(state)\r\n notifySubscribers()\r\n}\r\n\r\n/**\r\n * Mark all subtree is non actual.\r\n * Collect all nodes to notify subscribers im microtask queue.\r\n */\r\nconst invalidateSubtree = (state: CommonInternal) => {\r\n const stack: CommonInternal[] = [state]\r\n\r\n while (stack.length) {\r\n const st = stack.pop()\r\n st.childs.forEach((it) => stack.push(it))\r\n st.hasParentUpdates = true\r\n if (st.subscribes.size) {\r\n states2notify.add(st)\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Notify all collected subscribers once in microtask queue\r\n */\r\nconst notifySubscribers = () => {\r\n if (isNotifying === false) {\r\n isNotifying = true\r\n queueMicrotask(() => {\r\n // Нужно обновить дерево\r\n states2notify.forEach((state) => {\r\n try {\r\n state.subscribes.forEach((listner) => {\r\n return listner(getValue(state))\r\n })\r\n } catch (e) {\r\n console.error('Error in subscriber function of:', state.name)\r\n }\r\n })\r\n states2notify.clear()\r\n isNotifying = false\r\n })\r\n }\r\n}\r\n\r\n/**\r\n * Start collecting all non computed states.\r\n *\r\n * Helper for render adapters.\r\n */\r\nexport const startRecord = () => {\r\n recording = new Set()\r\n}\r\n\r\n/**\r\n * Flush all collected non computed states.\r\n */\r\nexport const flushStates = (): Set<StateInternal> => {\r\n const data = recording\r\n recording = undefined\r\n return data\r\n}\r\n\r\nexport const subscribe = (state: CommonInternal | CommonInternal, listner: Listner): UnSubscribe => {\r\n /**\r\n * Если значение стейта ниразу не расчитывалось, его нужно обновить\r\n * Если подписываемся на вычисляемый стэйт, то нужно узнать всех родителей\r\n * Родители могут меняться, поэтому после каждого вычисления нужно обновлять зависимости дерева\r\n *\r\n * При отписке нужно оповестить всех на кого были опдписанты о том что мы отписались\r\n *\r\n */\r\n\r\n if (state.subscribes.has(listner)) {\r\n return () => ({})\r\n }\r\n\r\n const computedState = getComputed(state)\r\n // Нужно актуализировать в родилеях зависимость\r\n if (computedState) {\r\n getComputedValue(computedState)\r\n state.depends.forEach((parent) => parent.childs.add(state))\r\n }\r\n\r\n state.subscribes.add(listner)\r\n\r\n return () => {\r\n state.subscribes.delete(listner)\r\n if (state.subscribes.size === 0) {\r\n state.depends.forEach((parent) => parent.childs.delete(state))\r\n }\r\n }\r\n}\r\n\r\nconst assert = (condtion: boolean, msg: string) => {\r\n if (condtion) {\r\n throw new Error(msg)\r\n }\r\n}\r\n\r\n/**\r\n *\r\n * @param value - Reducer or value\r\n * @param name - name of state. For loggin or easy debug\r\n * @returns State<T>\r\n */\r\nexport function state<T extends StateType = StateType>(value: T, options?: Options): State<T> {\r\n assert(isFunction(value), 'Function not allowed in state')\r\n\r\n const data: CommonInternal = {\r\n childs: new Set(),\r\n depends: new Set(),\r\n history: Array.from({length: settings.historyLength}),\r\n historyCursor: -1,\r\n name: getName(options?.name),\r\n subscribes: new Set(),\r\n hasParentUpdates: undefined,\r\n }\r\n\r\n setValue(data, value)\r\n\r\n const publicApi = function () {\r\n return getValue(data)\r\n }\r\n\r\n Object.defineProperty(publicApi, 'name', {value: data.name})\r\n publicApi.subscribe = (listner: Listner) => subscribe(data, listner)\r\n publicApi.set = (value: T) => setValue(data, value)\r\n publicApi._internal = data\r\n\r\n return publicApi as State<T>\r\n}\r\n\r\nexport const computed = <\r\n T extends StateType = -1,\r\n S extends StatlessFunc<T> = StatlessFunc<T>,\r\n O extends Nullable<ComputedInternalOptions> = Nullable<ComputedInternalOptions>,\r\n>(\r\n value: GetStatlessFunc<T, S, O>,\r\n options?: O,\r\n): Computed<T> => {\r\n const data: ComputedInternal = {\r\n childs: new Set(),\r\n depends: new Set(),\r\n hasParentUpdates: true,\r\n history: Array.from({length: settings.historyLength}),\r\n historyCursor: -1,\r\n initial: options?.initial as ReturnType<typeof value> | undefined,\r\n isComputing: false,\r\n name: getName(options?.name),\r\n reducer: value,\r\n subscribes: new Set(),\r\n }\r\n\r\n const publicApi = function () {\r\n return getValue(data)\r\n }\r\n\r\n Object.defineProperty(publicApi, 'name', {value: data.name})\r\n publicApi.subscribe = (listner: Listner<T>) => subscribe(data, listner as Listner)\r\n publicApi._internal = data\r\n\r\n return publicApi as Computed<T>\r\n}\r\n\r\n/**\r\n * ## Action state\r\n *\r\n * @param value - Action function\r\n * @param name\r\n */\r\nexport const action = <T extends unknown[]>(\r\n value: (...args: T) => void,\r\n options?: ActionOptions,\r\n): Action<T> => {\r\n return {\r\n run: (...args: T) => {\r\n isActionNow = true\r\n value(...args)\r\n isActionNow = false\r\n return this\r\n },\r\n name: getName(options?.name),\r\n onAction: options?.onAction,\r\n }\r\n}\r\n"],"names":["recording","isNotifying","names","Set","requesters","states2notify","getHistoryValue","state","history","historyCursor","pushHistory","value","length","getName","name","has","console","error","defaultName","getComputed","isFunction","v","getComputedValue","_state$name","prevState","hasParentUpdates","undefined","isDontNeedRecalc","depends","forEach","item","_recording","add","assert","isComputing","push","childs","delete","clear","reducer","initial","pop","e","message","getValue","lastRequester","at","setValue","newValue","getValueOfSetterFunction","invalidateSubtree","notifySubscribers","stack","st","it","subscribes","size","queueMicrotask","listner","startRecord","flushStates","data","subscribe","computedState","parent","condtion","msg","Error","options","Array","from","publicApi","Object","defineProperty","set","_internal","computed","action","run","args","this","onAction"],"mappings":"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"}
{"version":3,"file":"index.modern.mjs","sources":["../src/core.ts"],"sourcesContent":["import {\r\n ComputedInternal,\r\n Listner,\r\n StateType,\r\n Settings,\r\n StateVariants,\r\n Action,\r\n Options,\r\n ComputedInternalOptions,\r\n Nullable,\r\n StatlessFunc,\r\n GetStatlessFunc,\r\n HistoryInternal,\r\n State,\r\n Computed,\r\n Func,\r\n UnSubscribe,\r\n CommonInternal,\r\n StateInternal,\r\n SetterFunc,\r\n ActionOptions,\r\n} from './types.js'\r\n\r\nlet isNotifying = false\r\nlet isActionNow = false\r\nlet recording: Set<StateInternal> | undefined\r\n\r\nconst defaultName = 'Unnamed state'\r\nconst names = new Set()\r\nconst requesters: ComputedInternal[] = []\r\nconst states2notify = new Set<StateVariants>()\r\nconst settings: Settings = {\r\n historyLength: 5,\r\n}\r\n\r\nexport const getHistoryValue = (state: StateVariants): unknown => {\r\n return state.history[state.historyCursor]\r\n}\r\nconst pushHistory = <T extends HistoryInternal>(state: T, value: unknown) => {\r\n const cursorHistory = state.historyCursor\r\n state.historyCursor = (cursorHistory + 1) % state.history.length\r\n state.history[state.historyCursor] = value\r\n}\r\n\r\nconst getName = (name?: string): string => {\r\n if (name && names.has(name)) {\r\n console.error(`Name ${name} already used! Replaced to undefined`)\r\n return defaultName\r\n }\r\n if (name) {\r\n return name\r\n }\r\n return defaultName\r\n}\r\n\r\nexport const setSetting = (data: Partial<Settings>) => {\r\n Object.assign(settings, data)\r\n}\r\n\r\nconst getComputed = (state: CommonInternal | ComputedInternal) => {\r\n if ('reducer' in state) {\r\n return state\r\n }\r\n}\r\n\r\nconst isFunction = (v: unknown): v is Func => {\r\n return typeof v === 'function'\r\n}\r\n\r\nconst isDontNeedRecalc = (state: CommonInternal, prevState: unknown): boolean => {\r\n return state.hasParentUpdates === false && prevState !== undefined\r\n}\r\n\r\nconst getComputedValue = (state: ComputedInternal): unknown => {\r\n try {\r\n const prevState = getHistoryValue(state)\r\n\r\n if (isDontNeedRecalc(state, prevState)) {\r\n if (recording) {\r\n state.depends.forEach((item) => {\r\n recording?.add(item)\r\n })\r\n }\r\n return prevState\r\n }\r\n\r\n assert(state.isComputing, `Loops dosen't allows. Name: ${state.name ?? 'Unnamed state'}`)\r\n\r\n requesters.push(state)\r\n state.depends.forEach((item) => {\r\n item.childs.delete(state)\r\n })\r\n state.depends.clear()\r\n state.isComputing = true\r\n const value = state.reducer(prevState ?? state.initial)\r\n state.isComputing = false\r\n state.hasParentUpdates = false\r\n\r\n requesters.pop()\r\n pushHistory(state, value)\r\n\r\n return value\r\n } catch (e) {\r\n console.error((e as Error).message)\r\n return undefined\r\n }\r\n}\r\n\r\nconst getValue = (state: CommonInternal) => {\r\n const reducer = getComputed(state)\r\n try {\r\n const lastRequester = requesters.at(-1)\r\n if (lastRequester && !state.childs.has(lastRequester)) {\r\n state.childs.add(lastRequester)\r\n lastRequester.depends.add(state)\r\n }\r\n if (reducer) {\r\n return getComputedValue(reducer)\r\n }\r\n return getHistoryValue(state)\r\n } finally {\r\n if (recording && !reducer) {\r\n recording.add(state)\r\n }\r\n }\r\n}\r\n\r\nconst getValueOfSetterFunction = (state: CommonInternal, value: SetterFunc): unknown => {\r\n const prevValue = getHistoryValue(state)\r\n return value(prevValue)\r\n}\r\n\r\nconst setValue = (state: CommonInternal, value: unknown): void => {\r\n const newValue = isFunction(value) ? getValueOfSetterFunction(state, value) : value\r\n\r\n if (newValue === getHistoryValue(state)) {\r\n return\r\n }\r\n pushHistory(state, newValue)\r\n invalidateSubtree(state)\r\n notifySubscribers()\r\n}\r\n\r\n/**\r\n * Mark all subtree is non actual.\r\n * Collect all nodes to notify subscribers im microtask queue.\r\n */\r\nconst invalidateSubtree = (state: CommonInternal) => {\r\n const stack: CommonInternal[] = [state]\r\n\r\n while (stack.length) {\r\n const st = stack.pop()\r\n st.childs.forEach((it) => stack.push(it))\r\n st.hasParentUpdates = true\r\n if (st.subscribes.size) {\r\n states2notify.add(st)\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Notify all collected subscribers once in microtask queue\r\n */\r\nconst notifySubscribers = () => {\r\n if (isNotifying === false) {\r\n isNotifying = true\r\n queueMicrotask(() => {\r\n // Нужно обновить дерево\r\n states2notify.forEach((state) => {\r\n try {\r\n state.subscribes.forEach((listner) => {\r\n return listner(getValue(state))\r\n })\r\n } catch (e) {\r\n console.error('Error in subscriber function of:', state.name)\r\n }\r\n })\r\n states2notify.clear()\r\n isNotifying = false\r\n })\r\n }\r\n}\r\n\r\n/**\r\n * Start collecting all non computed states.\r\n *\r\n * Helper for render adapters.\r\n */\r\nexport const startRecord = () => {\r\n recording = new Set()\r\n}\r\n\r\n/**\r\n * Flush all collected non computed states.\r\n */\r\nexport const flushStates = (): Set<StateInternal> => {\r\n const data = recording\r\n recording = undefined\r\n return data\r\n}\r\n\r\nexport const subscribe = (state: CommonInternal | CommonInternal, listner: Listner): UnSubscribe => {\r\n /**\r\n * Если значение стейта ниразу не расчитывалось, его нужно обновить\r\n * Если подписываемся на вычисляемый стэйт, то нужно узнать всех родителей\r\n * Родители могут меняться, поэтому после каждого вычисления нужно обновлять зависимости дерева\r\n *\r\n * При отписке нужно оповестить всех на кого были опдписанты о том что мы отписались\r\n *\r\n */\r\n\r\n if (state.subscribes.has(listner)) {\r\n return () => ({})\r\n }\r\n\r\n const computedState = getComputed(state)\r\n // Нужно актуализировать в родилеях зависимость\r\n if (computedState) {\r\n getComputedValue(computedState)\r\n state.depends.forEach((parent) => parent.childs.add(state))\r\n }\r\n\r\n state.subscribes.add(listner)\r\n\r\n return () => {\r\n state.subscribes.delete(listner)\r\n if (state.subscribes.size === 0) {\r\n state.depends.forEach((parent) => parent.childs.delete(state))\r\n }\r\n }\r\n}\r\n\r\nconst assert = (condtion: boolean, msg: string) => {\r\n if (condtion) {\r\n throw new Error(msg)\r\n }\r\n}\r\n\r\n/**\r\n *\r\n * @param value - Reducer or value\r\n * @param name - name of state. For loggin or easy debug\r\n * @returns State<T>\r\n */\r\nexport function state<T extends StateType = StateType>(value: T, options?: Options): State<T> {\r\n assert(isFunction(value), 'Function not allowed in state')\r\n\r\n const data: CommonInternal = {\r\n childs: new Set(),\r\n depends: new Set(),\r\n history: Array.from({length: settings.historyLength}),\r\n historyCursor: -1,\r\n name: getName(options?.name),\r\n subscribes: new Set(),\r\n hasParentUpdates: undefined,\r\n }\r\n\r\n setValue(data, value)\r\n\r\n const publicApi = function () {\r\n return getValue(data)\r\n }\r\n\r\n Object.defineProperty(publicApi, 'name', {value: data.name})\r\n publicApi.subscribe = (listner: Listner) => subscribe(data, listner)\r\n publicApi.set = (value: T) => setValue(data, value)\r\n publicApi._internal = data\r\n\r\n return publicApi as State<T>\r\n}\r\n\r\nexport const computed = <\r\n T extends StateType = -1,\r\n S extends StatlessFunc<T> = StatlessFunc<T>,\r\n O extends Nullable<ComputedInternalOptions> = Nullable<ComputedInternalOptions>,\r\n>(\r\n value: GetStatlessFunc<T, S, O>,\r\n options?: O,\r\n): Computed<T> => {\r\n const data: ComputedInternal = {\r\n childs: new Set(),\r\n depends: new Set(),\r\n hasParentUpdates: true,\r\n history: Array.from({length: settings.historyLength}),\r\n historyCursor: -1,\r\n initial: options?.initial as ReturnType<typeof value> | undefined,\r\n isComputing: false,\r\n name: getName(options?.name),\r\n reducer: value,\r\n subscribes: new Set(),\r\n }\r\n\r\n const publicApi = function () {\r\n return getValue(data)\r\n }\r\n\r\n Object.defineProperty(publicApi, 'name', {value: data.name})\r\n publicApi.subscribe = (listner: Listner<T>) => subscribe(data, listner as Listner)\r\n publicApi._internal = data\r\n\r\n return publicApi as Computed<T>\r\n}\r\n\r\n/**\r\n * Action state\r\n * @param value - Action function\r\n * @param name\r\n */\r\nexport const action = <T extends unknown[]>(\r\n value: (...args: T) => void,\r\n options?: ActionOptions,\r\n): Action<T> => {\r\n return {\r\n run: (...args: T) => {\r\n isActionNow = true\r\n value(...args)\r\n isActionNow = false\r\n return this\r\n },\r\n name: getName(options?.name),\r\n onAction: options?.onAction,\r\n }\r\n}\r\n"],"names":["recording","isNotifying","names","Set","requesters","states2notify","getHistoryValue","state","history","historyCursor","pushHistory","value","length","getName","name","has","console","error","defaultName","getComputed","isFunction","v","getComputedValue","_state$name","prevState","hasParentUpdates","undefined","isDontNeedRecalc","depends","forEach","item","_recording","add","assert","isComputing","push","childs","delete","clear","reducer","initial","pop","e","message","getValue","lastRequester","at","setValue","newValue","getValueOfSetterFunction","invalidateSubtree","notifySubscribers","stack","st","it","subscribes","size","queueMicrotask","listner","startRecord","flushStates","data","subscribe","computedState","parent","condtion","msg","Error","options","Array","from","publicApi","Object","defineProperty","set","_internal","computed","action","run","args","this","onAction"],"mappings":"AAuBA,IAEIA,EAFWC,GAAG,EAIlB,QAAoB,gBACTC,EAAG,IAAIC,IACZC,EAAiC,GACjCC,EAAgB,QAKTC,EAAmBC,KACjBC,QAAQD,EAAME,eAEvBC,EAAc,CAA4BH,EAAUI,KAExDJ,EAAME,eADgBF,EAAME,cACW,GAAKF,EAAMC,QAAQI,OAC1DL,EAAMC,QAAQD,EAAME,eAAiBE,CACvC,EAEaE,EAAIC,GACXA,GAAQZ,EAAMa,IAAID,IACpBE,QAAQC,cAAcH,yCAEvBI,GACGJ,GAINI,EAMMC,EAAeZ,IACnB,GAAI,YAAkBA,EACpB,OAAOA,CACR,EAGGa,EAAcC,GACE,mBAANA,EAOMC,EAAIf,IACxB,IAAI,IAAAgB,EACF,MAAeC,EAAGlB,EAAgBC,GAElC,GARqB,EAACA,EAAuBiB,KACb,MAArBC,uBAA4CC,IAAdF,EAOrCG,CAAiBpB,EAAOiB,GAM1B,OALIxB,GACFO,EAAMqB,QAAQC,QAASC,IACrB,IAAAC,EAAS,OAATA,EAAA/B,IAAA+B,EAAWC,IAAIF,EACjB,GAEKN,EAGTS,EAAO1B,EAAM2B,YAAa,+BAA6C,OAA7CX,EAA+BhB,EAAMO,MAAQS,EAAA,mBAEvEnB,EAAW+B,KAAK5B,GAChBA,EAAMqB,QAAQC,QAASC,IACrBA,EAAKM,OAAOC,OAAO9B,EAAK,GAE1BA,EAAMqB,QAAQU,QACd/B,EAAM2B,aAAc,EACpB,MAAWvB,EAAGJ,EAAMgC,cAAQf,EAAAA,EAAajB,EAAMiC,SAO/C,OANAjC,EAAM2B,aAAc,EACpB3B,EAAMkB,kBAAmB,EAEzBrB,EAAWqC,MACX/B,EAAYH,EAAOI,IAMpB,CAHC,MAAO+B,GAEP,YADA1B,QAAQC,MAAOyB,EAAYC,QAE5B,GAGGC,EAAYrC,IAChB,MAAagC,EAAGpB,EAAYZ,GAC5B,IACE,MAAMsC,EAAgBzC,EAAW0C,IAAI,GAKrC,OAJID,IAAkBtC,EAAM6B,OAAOrB,IAAI8B,KACrCtC,EAAM6B,OAAOJ,IAAIa,GACjBA,EAAcjB,QAAQI,IAAIzB,IAExBgC,EACqBjB,EAACiB,GAEnBjC,EAAgBC,EAKxB,CAJA,QACKP,IAAcuC,GAChBvC,EAAUgC,IAAIzB,EAEjB,GAQGwC,EAAW,CAACxC,EAAuBI,KACvC,MAAMqC,EAAW5B,EAAWT,GANG,EAACJ,EAAuBI,MACrCL,EAAgBC,IAKG0C,CAAyB1C,EAAOI,GAASA,EAE1EqC,IAAa1C,EAAgBC,KAGjCG,EAAYH,EAAOyC,GACnBE,EAAkB3C,GAClB4C,MAOqBD,EAAI3C,IACzB,MAAM6C,EAA0B,CAAC7C,GAEjC,KAAO6C,EAAMxC,QAAQ,CACnB,MAAQyC,EAAGD,EAAMX,MACjBY,EAAGjB,OAAOP,QAASyB,GAAOF,EAAMjB,KAAKmB,IACrCD,EAAG5B,kBAAmB,EAClB4B,EAAGE,WAAWC,MAChBnD,EAAc2B,IAAIqB,EAErB,GAMGF,EAAoB,MACJ,IAAhBlD,IACFA,GAAc,EACdwD,eAAe,KAEbpD,EAAcwB,QAAStB,IACrB,IACEA,EAAMgD,WAAW1B,QAAS6B,GACVA,EAACd,EAASrC,IAI3B,CAFC,MAAOmC,GACP1B,QAAQC,MAAM,mCAAoCV,EAAMO,KACzD,IAEHT,EAAciC,QACdrC,GAAc,CAAA,GAEjB,EAQU0D,EAAc,KACzB3D,EAAY,IACdG,GAAA,EAKwByD,EAAG,KACzB,MAAMC,EAAO7D,EAEb,OADAA,OAAY0B,EAEdmC,GAEsBC,EAAG,CAACvD,EAAwCmD,KAUhE,GAAInD,EAAMgD,WAAWxC,IAAI2C,GACvB,MAAO,KAAO,CAAE,GAGlB,MAAMK,EAAgB5C,EAAYZ,GASlC,OAPIwD,IACFzC,EAAiByC,GACjBxD,EAAMqB,QAAQC,QAASmC,GAAWA,EAAO5B,OAAOJ,IAAIzB,KAGtDA,EAAMgD,WAAWvB,IAAI0B,GAEd,KACLnD,EAAMgD,WAAWlB,OAAOqB,GACM,IAA1BnD,EAAMgD,WAAWC,MACnBjD,EAAMqB,QAAQC,QAASmC,GAAWA,EAAO5B,OAAOC,OAAO9B,GACxD,CACH,EAGU0B,EAAG,CAACgC,EAAmBC,KACjC,GAAID,EACF,UAAeE,MAACD,EACjB,EASa,SAAK3D,EAAkCI,EAAUyD,GAC/DnC,EAAOb,EAAWT,GAAQ,iCAE1B,MAAMkD,EAAuB,CAC3BzB,OAAQ,IAASjC,IACjByB,QAAS,IAASzB,IAClBK,QAAS6D,MAAMC,KAAK,CAAC1D,OA1NR,IA2NbH,eAAgB,EAChBK,KAAMD,EAAQuD,MAAAA,OAAAA,EAAAA,EAAStD,MACvByC,WAAY,QACZ9B,sBAAkBC,GAGpBqB,EAASc,EAAMlD,GAEf,MAAe4D,EAAG,WAChB,OAAe3B,EAACiB,EAClB,EAOA,OALAW,OAAOC,eAAeF,EAAW,OAAQ,CAAC5D,MAAOkD,EAAK/C,OACtDyD,EAAUT,UAAaJ,GAAqBI,EAAUD,EAAMH,GAC5Da,EAAUG,IAAO/D,GAAaoC,EAASc,EAAMlD,GAC7C4D,EAAUI,UAAYd,EAEfU,CACT,CAEaK,MAAQA,EAAG,CAKtBjE,EACAyD,KAEA,MAAUP,EAAqB,CAC7BzB,OAAQ,IAAIjC,IACZyB,QAAS,IAAIzB,IACbsB,kBAAkB,EAClBjB,QAAS6D,MAAMC,KAAK,CAAC1D,OA3PR,IA4PbH,eAAgB,EAChB+B,QAAS4B,MAAAA,OAAAA,EAAAA,EAAS5B,QAClBN,aAAa,EACbpB,KAAMD,EAAe,MAAPuD,OAAO,EAAPA,EAAStD,MACvByB,QAAS5B,EACT4C,WAAY,IAAIpD,KAGZoE,EAAY,WAChB,OAAO3B,EAASiB,EAClB,EAMA,OAJAW,OAAOC,eAAeF,EAAW,OAAQ,CAAC5D,MAAOkD,EAAK/C,OACtDyD,EAAUT,UAAaJ,GAAwBI,EAAUD,EAAMH,GAC/Da,EAAUI,UAAYd,EAEfU,GAQIM,EAAS,CACpBlE,EACAyD,KAEO,CACLU,IAAK,IAAIC,KAEPpE,KAASoE,EAGXC,EACAlE,KAAMD,EAAe,MAAPuD,OAAO,EAAPA,EAAStD,MACvBmE,SAAUb,MAAAA,OAAAA,EAAAA,EAASa"}

@@ -1,1 +0,1 @@

{"version":3,"file":"index.module.js","sources":["../src/core.ts"],"sourcesContent":["import {\r\n ComputedInternal,\r\n Listner,\r\n StateType,\r\n Settings,\r\n StateVariants,\r\n Action,\r\n Options,\r\n ComputedInternalOptions,\r\n Nullable,\r\n StatlessFunc,\r\n GetStatlessFunc,\r\n HistoryInternal,\r\n State,\r\n Computed,\r\n Func,\r\n UnSubscribe,\r\n CommonInternal,\r\n StateInternal,\r\n SetterFunc,\r\n ActionOptions,\r\n} from './types.js'\r\n\r\nlet isNotifying = false\r\nlet isActionNow = false\r\nlet recording: Set<StateInternal> | undefined\r\n\r\nconst defaultName = 'Unnamed state'\r\nconst names = new Set()\r\nconst requesters: ComputedInternal[] = []\r\nconst states2notify = new Set<StateVariants>()\r\nconst settings: Settings = {\r\n historyLength: 5,\r\n}\r\n\r\nexport const getHistoryValue = (state: StateVariants): unknown => {\r\n return state.history[state.historyCursor]\r\n}\r\nconst pushHistory = <T extends HistoryInternal>(state: T, value: unknown) => {\r\n const cursorHistory = state.historyCursor\r\n state.historyCursor = (cursorHistory + 1) % state.history.length\r\n state.history[state.historyCursor] = value\r\n}\r\n\r\nconst getName = (name?: string): string => {\r\n if (name && names.has(name)) {\r\n console.error(`Name ${name} already used! Replaced to undefined`)\r\n return defaultName\r\n }\r\n if (name) {\r\n return name\r\n }\r\n return defaultName\r\n}\r\n\r\nexport const setSetting = (data: Partial<Settings>) => {\r\n Object.assign(settings, data)\r\n}\r\n\r\nconst getComputed = (state: CommonInternal | ComputedInternal) => {\r\n if ('reducer' in state) {\r\n return state\r\n }\r\n}\r\n\r\nconst isFunction = (v: unknown): v is Func => {\r\n return typeof v === 'function'\r\n}\r\n\r\nconst isDontNeedRecalc = (state: CommonInternal, prevState: unknown): boolean => {\r\n return state.hasParentUpdates === false && prevState !== undefined\r\n}\r\n\r\nconst getComputedValue = (state: ComputedInternal): unknown => {\r\n try {\r\n const prevState = getHistoryValue(state)\r\n\r\n if (isDontNeedRecalc(state, prevState)) {\r\n if (recording) {\r\n state.depends.forEach((item) => {\r\n recording?.add(item)\r\n })\r\n }\r\n return prevState\r\n }\r\n\r\n assert(state.isComputing, `Loops dosen't allows. Name: ${state.name ?? 'Unnamed state'}`)\r\n\r\n requesters.push(state)\r\n state.depends.forEach((item) => {\r\n item.childs.delete(state)\r\n })\r\n state.depends.clear()\r\n state.isComputing = true\r\n const value = state.reducer(prevState ?? state.initial)\r\n state.isComputing = false\r\n state.hasParentUpdates = false\r\n\r\n requesters.pop()\r\n pushHistory(state, value)\r\n\r\n return value\r\n } catch (e) {\r\n console.error((e as Error).message)\r\n return undefined\r\n }\r\n}\r\n\r\nconst getValue = (state: CommonInternal) => {\r\n const reducer = getComputed(state)\r\n try {\r\n const lastRequester = requesters.at(-1)\r\n if (lastRequester && !state.childs.has(lastRequester)) {\r\n state.childs.add(lastRequester)\r\n lastRequester.depends.add(state)\r\n }\r\n if (reducer) {\r\n return getComputedValue(reducer)\r\n }\r\n return getHistoryValue(state)\r\n } finally {\r\n if (recording && !reducer) {\r\n recording.add(state)\r\n }\r\n }\r\n}\r\n\r\nconst getValueOfSetterFunction = (state: CommonInternal, value: SetterFunc): unknown => {\r\n const prevValue = getHistoryValue(state)\r\n return value(prevValue)\r\n}\r\n\r\nconst setValue = (state: CommonInternal, value: unknown): void => {\r\n const newValue = isFunction(value) ? getValueOfSetterFunction(state, value) : value\r\n\r\n if (newValue === getHistoryValue(state)) {\r\n return\r\n }\r\n pushHistory(state, newValue)\r\n invalidateSubtree(state)\r\n notifySubscribers()\r\n}\r\n\r\n/**\r\n * Mark all subtree is non actual.\r\n * Collect all nodes to notify subscribers im microtask queue.\r\n */\r\nconst invalidateSubtree = (state: CommonInternal) => {\r\n const stack: CommonInternal[] = [state]\r\n\r\n while (stack.length) {\r\n const st = stack.pop()\r\n st.childs.forEach((it) => stack.push(it))\r\n st.hasParentUpdates = true\r\n if (st.subscribes.size) {\r\n states2notify.add(st)\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Notify all collected subscribers once in microtask queue\r\n */\r\nconst notifySubscribers = () => {\r\n if (isNotifying === false) {\r\n isNotifying = true\r\n queueMicrotask(() => {\r\n // Нужно обновить дерево\r\n states2notify.forEach((state) => {\r\n try {\r\n state.subscribes.forEach((listner) => {\r\n return listner(getValue(state))\r\n })\r\n } catch (e) {\r\n console.error('Error in subscriber function of:', state.name)\r\n }\r\n })\r\n states2notify.clear()\r\n isNotifying = false\r\n })\r\n }\r\n}\r\n\r\n/**\r\n * Start collecting all non computed states.\r\n *\r\n * Helper for render adapters.\r\n */\r\nexport const startRecord = () => {\r\n recording = new Set()\r\n}\r\n\r\n/**\r\n * Flush all collected non computed states.\r\n */\r\nexport const flushStates = (): Set<StateInternal> => {\r\n const data = recording\r\n recording = undefined\r\n return data\r\n}\r\n\r\nexport const subscribe = (state: CommonInternal | CommonInternal, listner: Listner): UnSubscribe => {\r\n /**\r\n * Если значение стейта ниразу не расчитывалось, его нужно обновить\r\n * Если подписываемся на вычисляемый стэйт, то нужно узнать всех родителей\r\n * Родители могут меняться, поэтому после каждого вычисления нужно обновлять зависимости дерева\r\n *\r\n * При отписке нужно оповестить всех на кого были опдписанты о том что мы отписались\r\n *\r\n */\r\n\r\n if (state.subscribes.has(listner)) {\r\n return () => ({})\r\n }\r\n\r\n const computedState = getComputed(state)\r\n // Нужно актуализировать в родилеях зависимость\r\n if (computedState) {\r\n getComputedValue(computedState)\r\n state.depends.forEach((parent) => parent.childs.add(state))\r\n }\r\n\r\n state.subscribes.add(listner)\r\n\r\n return () => {\r\n state.subscribes.delete(listner)\r\n if (state.subscribes.size === 0) {\r\n state.depends.forEach((parent) => parent.childs.delete(state))\r\n }\r\n }\r\n}\r\n\r\nconst assert = (condtion: boolean, msg: string) => {\r\n if (condtion) {\r\n throw new Error(msg)\r\n }\r\n}\r\n\r\n/**\r\n *\r\n * @param value - Reducer or value\r\n * @param name - name of state. For loggin or easy debug\r\n * @returns State<T>\r\n */\r\nexport function state<T extends StateType = StateType>(value: T, options?: Options): State<T> {\r\n assert(isFunction(value), 'Function not allowed in state')\r\n\r\n const data: CommonInternal = {\r\n childs: new Set(),\r\n depends: new Set(),\r\n history: Array.from({length: settings.historyLength}),\r\n historyCursor: -1,\r\n name: getName(options?.name),\r\n subscribes: new Set(),\r\n hasParentUpdates: undefined,\r\n }\r\n\r\n setValue(data, value)\r\n\r\n const publicApi = function () {\r\n return getValue(data)\r\n }\r\n\r\n Object.defineProperty(publicApi, 'name', {value: data.name})\r\n publicApi.subscribe = (listner: Listner) => subscribe(data, listner)\r\n publicApi.set = (value: T) => setValue(data, value)\r\n publicApi._internal = data\r\n\r\n return publicApi as State<T>\r\n}\r\n\r\nexport const computed = <\r\n T extends StateType = -1,\r\n S extends StatlessFunc<T> = StatlessFunc<T>,\r\n O extends Nullable<ComputedInternalOptions> = Nullable<ComputedInternalOptions>,\r\n>(\r\n value: GetStatlessFunc<T, S, O>,\r\n options?: O,\r\n): Computed<T> => {\r\n const data: ComputedInternal = {\r\n childs: new Set(),\r\n depends: new Set(),\r\n hasParentUpdates: true,\r\n history: Array.from({length: settings.historyLength}),\r\n historyCursor: -1,\r\n initial: options?.initial as ReturnType<typeof value> | undefined,\r\n isComputing: false,\r\n name: getName(options?.name),\r\n reducer: value,\r\n subscribes: new Set(),\r\n }\r\n\r\n const publicApi = function () {\r\n return getValue(data)\r\n }\r\n\r\n Object.defineProperty(publicApi, 'name', {value: data.name})\r\n publicApi.subscribe = (listner: Listner<T>) => subscribe(data, listner as Listner)\r\n publicApi._internal = data\r\n\r\n return publicApi as Computed<T>\r\n}\r\n\r\n/**\r\n * ## Action state\r\n *\r\n * @param value - Action function\r\n * @param name\r\n */\r\nexport const action = <T extends unknown[]>(\r\n value: (...args: T) => void,\r\n options?: ActionOptions,\r\n): Action<T> => {\r\n return {\r\n run: (...args: T) => {\r\n isActionNow = true\r\n value(...args)\r\n isActionNow = false\r\n return this\r\n },\r\n name: getName(options?.name),\r\n onAction: options?.onAction,\r\n }\r\n}\r\n"],"names":["_this","this","recording","isNotifying","names","Set","requesters","states2notify","getHistoryValue","state","history","historyCursor","pushHistory","value","length","getName","name","has","console","error","defaultName","getComputed","isFunction","v","getComputedValue","prevState","hasParentUpdates","undefined","isDontNeedRecalc","depends","forEach","item","add","assert","isComputing","push","childs","delete","clear","reducer","initial","pop","e","message","getValue","lastRequester","at","setValue","newValue","getValueOfSetterFunction","invalidateSubtree","notifySubscribers","stack","st","it","subscribes","size","queueMicrotask","listner","startRecord","data","subscribe","computedState","parent","condtion","msg","Error","options","Array","from","publicApi","Object","defineProperty","set","_internal","computed","action","run","slice","call","arguments","onAction"],"mappings":"AAuBA,IAAAA,OAAAC,EAAA,IAEIC,EAFWC,GAAG,EAIlB,QAAoB,gBACTC,EAAG,IAAIC,IACZC,EAAiC,GACjCC,EAAgB,QAKTC,EAAmBC,GAClBA,EAACC,QAAQD,EAAME,eAEZC,EAAG,CAA4BH,EAAUI,KAExDJ,EAAME,eADgBF,EAAME,cACW,GAAKF,EAAMC,QAAQI,OAC1DL,EAAMC,QAAQD,EAAME,eAAiBE,CAAAA,EAGjCE,EAAWC,GACXA,GAAQZ,EAAMa,IAAID,IACpBE,QAAQC,cAAcH,yCAEvBI,GACGJ,GAINI,EAMiBC,EAAIZ,IACnB,GAAI,cACF,OAAOA,CACR,EAGGa,EAAcC,GACE,mBAANA,EAOMC,EAAIf,IACxB,IACE,MAAMgB,EAAYjB,EAAgBC,GAElC,GARqB,EAACA,EAAuBgB,KACb,IAAtBhB,EAACiB,uBAA4CC,IAAdF,EAOrCG,CAAiBnB,EAAOgB,GAM1B,OALIvB,GACFO,EAAMoB,QAAQC,QAASC,IACrB7B,GAAW8B,IAAID,EAAI,GAGhBN,EAGTQ,EAAOxB,EAAMyB,YAAa,+BAA+BzB,EAAMO,MAAQ,mBAEvEV,EAAW6B,KAAK1B,GAChBA,EAAMoB,QAAQC,QAASC,IACrBA,EAAKK,OAAOC,OAAO5B,EAAK,GAE1BA,EAAMoB,QAAQS,QACd7B,EAAMyB,aAAc,EACpB,QAAczB,EAAM8B,QAAQd,GAAahB,EAAM+B,SAO/C,OANA/B,EAAMyB,aAAc,EACpBzB,EAAMiB,kBAAmB,EAEzBpB,EAAWmC,MACX7B,EAAYH,EAAOI,GAGpBA,CAGA,CAHC,MAAO6B,GAEP,YADAxB,QAAQC,MAAOuB,EAAYC,QAE5B,GAGWC,EAAInC,IAChB,QAAgBY,EAAYZ,GAC5B,IACE,MAAmBoC,EAAGvC,EAAWwC,IAAI,GAKrC,OAJID,IAAkBpC,EAAM2B,OAAOnB,IAAI4B,KACrCpC,EAAM2B,OAAOJ,IAAIa,GACjBA,EAAchB,QAAQG,IAAIvB,IAExB8B,EACqBf,EAACe,GAEJ/B,EAACC,EAKxB,CAJA,QACKP,IAAcqC,GAChBrC,EAAU8B,IAAIvB,EAEjB,GAQWsC,EAAG,CAACtC,EAAuBI,KACvC,MAAcmC,EAAG1B,EAAWT,GANG,EAACJ,EAAuBI,IAE3CA,EADML,EAAgBC,IAKGwC,CAAyBxC,EAAOI,GAASA,EAE1EmC,IAAaxC,EAAgBC,KAGjCG,EAAYH,EAAOuC,GACnBE,EAAkBzC,GAClB0C,IAAiB,EAOID,EAAIzC,IACzB,MAAM2C,EAA0B,CAAC3C,GAEjC,KAAO2C,EAAMtC,QAAQ,CACnB,MAAMuC,EAAKD,EAAMX,MACjBY,EAAGjB,OAAON,QAASwB,GAAOF,EAAMjB,KAAKmB,IACrCD,EAAG3B,kBAAmB,EAClB2B,EAAGE,WAAWC,MAChBjD,EAAcyB,IAAIqB,EAErB,GAMoBF,EAAG,MACJ,IAAhBhD,IACFA,GAAc,EACdsD,eAAe,KAEblD,EAAcuB,QAASrB,IACrB,IACEA,EAAM8C,WAAWzB,QAAS4B,GACVA,EAACd,EAASnC,IAI3B,CAFC,MAAOiC,GACPxB,QAAQC,MAAM,mCAAoCV,EAAMO,KACzD,IAEHT,EAAc+B,QACdnC,GAAc,CAAA,GAEjB,EAQUwD,EAAc,KACzBzD,EAAY,IAAIG,GAClB,IAK2B,KACzB,MAAUuD,EAAG1D,EAEb,OADAA,OAAYyB,EAEdiC,GAEsBC,EAAG,CAACpD,EAAwCiD,KAUhE,GAAIjD,EAAM8C,WAAWtC,IAAIyC,GACvB,MAAO,KAAO,CAAE,GAGlB,MAAMI,EAAgBzC,EAAYZ,GASlC,OAPIqD,IACFtC,EAAiBsC,GACjBrD,EAAMoB,QAAQC,QAASiC,GAAWA,EAAO3B,OAAOJ,IAAIvB,KAGtDA,EAAM8C,WAAWvB,IAAI0B,GAEd,KACLjD,EAAM8C,WAAWlB,OAAOqB,GACM,IAA1BjD,EAAM8C,WAAWC,MACnB/C,EAAMoB,QAAQC,QAASiC,GAAWA,EAAO3B,OAAOC,OAAO5B,GACxD,CACH,EAGUwB,EAAG,CAAC+B,EAAmBC,KACjC,GAAID,EACF,MAAM,IAASE,MAACD,EACjB,EASa,SAAKxD,EAAkCI,EAAUsD,GAC/DlC,EAAOX,EAAWT,GAAQ,iCAE1B,MAAM+C,EAAuB,CAC3BxB,OAAQ,IAAS/B,IACjBwB,QAAS,IAAIxB,IACbK,QAAS0D,MAAMC,KAAK,CAACvD,OA1NR,IA2NbH,eAAgB,EAChBK,KAAMD,EAAQoD,GAASnD,MACvBuC,WAAY,IAASlD,IACrBqB,sBAAkBC,GAGpBoB,EAASa,EAAM/C,GAEf,MAAMyD,EAAY,WAChB,OAAe1B,EAACgB,EAClB,EAOA,OALAW,OAAOC,eAAeF,EAAW,OAAQ,CAACzD,MAAO+C,EAAK5C,OACtDsD,EAAUT,UAAaH,GAAqBG,EAAUD,EAAMF,GAC5DY,EAAUG,IAAO5D,GAAakC,EAASa,EAAM/C,GAC7CyD,EAAUI,UAAYd,EAGxBU,CAAA,CAEaK,MAAAA,EAAW,CAKtB9D,EACAsD,KAEA,MAAMP,EAAyB,CAC7BxB,OAAQ,IAAI/B,IACZwB,QAAS,IAAIxB,IACbqB,kBAAkB,EAClBhB,QAAS0D,MAAMC,KAAK,CAACvD,OA3PR,IA4PbH,eAAgB,EAChB6B,QAAS2B,GAAS3B,QAClBN,aAAa,EACblB,KAAMD,EAAQoD,GAASnD,MACvBuB,QAAS1B,EACT0C,WAAY,SAGRe,EAAY,WAChB,SAAgBV,EAClB,EAMA,OAJAW,OAAOC,eAAeF,EAAW,OAAQ,CAACzD,MAAO+C,EAAK5C,OACtDsD,EAAUT,UAAaH,GAAwBG,EAAUD,EAAMF,GAC/DY,EAAUI,UAAYd,EAEfU,GASIM,EAAS,CACpB/D,EACAsD,KAEO,CACLU,IAAK,WAIH,OAFAhE,KAAa,GAAAiE,MAAAC,KAAAC,YAENhF,CACT,EACAgB,KAAMD,EAAQoD,GAASnD,MACvBiE,SAAUd,GAASc"}
{"version":3,"file":"index.module.js","sources":["../src/core.ts"],"sourcesContent":["import {\r\n ComputedInternal,\r\n Listner,\r\n StateType,\r\n Settings,\r\n StateVariants,\r\n Action,\r\n Options,\r\n ComputedInternalOptions,\r\n Nullable,\r\n StatlessFunc,\r\n GetStatlessFunc,\r\n HistoryInternal,\r\n State,\r\n Computed,\r\n Func,\r\n UnSubscribe,\r\n CommonInternal,\r\n StateInternal,\r\n SetterFunc,\r\n ActionOptions,\r\n} from './types.js'\r\n\r\nlet isNotifying = false\r\nlet isActionNow = false\r\nlet recording: Set<StateInternal> | undefined\r\n\r\nconst defaultName = 'Unnamed state'\r\nconst names = new Set()\r\nconst requesters: ComputedInternal[] = []\r\nconst states2notify = new Set<StateVariants>()\r\nconst settings: Settings = {\r\n historyLength: 5,\r\n}\r\n\r\nexport const getHistoryValue = (state: StateVariants): unknown => {\r\n return state.history[state.historyCursor]\r\n}\r\nconst pushHistory = <T extends HistoryInternal>(state: T, value: unknown) => {\r\n const cursorHistory = state.historyCursor\r\n state.historyCursor = (cursorHistory + 1) % state.history.length\r\n state.history[state.historyCursor] = value\r\n}\r\n\r\nconst getName = (name?: string): string => {\r\n if (name && names.has(name)) {\r\n console.error(`Name ${name} already used! Replaced to undefined`)\r\n return defaultName\r\n }\r\n if (name) {\r\n return name\r\n }\r\n return defaultName\r\n}\r\n\r\nexport const setSetting = (data: Partial<Settings>) => {\r\n Object.assign(settings, data)\r\n}\r\n\r\nconst getComputed = (state: CommonInternal | ComputedInternal) => {\r\n if ('reducer' in state) {\r\n return state\r\n }\r\n}\r\n\r\nconst isFunction = (v: unknown): v is Func => {\r\n return typeof v === 'function'\r\n}\r\n\r\nconst isDontNeedRecalc = (state: CommonInternal, prevState: unknown): boolean => {\r\n return state.hasParentUpdates === false && prevState !== undefined\r\n}\r\n\r\nconst getComputedValue = (state: ComputedInternal): unknown => {\r\n try {\r\n const prevState = getHistoryValue(state)\r\n\r\n if (isDontNeedRecalc(state, prevState)) {\r\n if (recording) {\r\n state.depends.forEach((item) => {\r\n recording?.add(item)\r\n })\r\n }\r\n return prevState\r\n }\r\n\r\n assert(state.isComputing, `Loops dosen't allows. Name: ${state.name ?? 'Unnamed state'}`)\r\n\r\n requesters.push(state)\r\n state.depends.forEach((item) => {\r\n item.childs.delete(state)\r\n })\r\n state.depends.clear()\r\n state.isComputing = true\r\n const value = state.reducer(prevState ?? state.initial)\r\n state.isComputing = false\r\n state.hasParentUpdates = false\r\n\r\n requesters.pop()\r\n pushHistory(state, value)\r\n\r\n return value\r\n } catch (e) {\r\n console.error((e as Error).message)\r\n return undefined\r\n }\r\n}\r\n\r\nconst getValue = (state: CommonInternal) => {\r\n const reducer = getComputed(state)\r\n try {\r\n const lastRequester = requesters.at(-1)\r\n if (lastRequester && !state.childs.has(lastRequester)) {\r\n state.childs.add(lastRequester)\r\n lastRequester.depends.add(state)\r\n }\r\n if (reducer) {\r\n return getComputedValue(reducer)\r\n }\r\n return getHistoryValue(state)\r\n } finally {\r\n if (recording && !reducer) {\r\n recording.add(state)\r\n }\r\n }\r\n}\r\n\r\nconst getValueOfSetterFunction = (state: CommonInternal, value: SetterFunc): unknown => {\r\n const prevValue = getHistoryValue(state)\r\n return value(prevValue)\r\n}\r\n\r\nconst setValue = (state: CommonInternal, value: unknown): void => {\r\n const newValue = isFunction(value) ? getValueOfSetterFunction(state, value) : value\r\n\r\n if (newValue === getHistoryValue(state)) {\r\n return\r\n }\r\n pushHistory(state, newValue)\r\n invalidateSubtree(state)\r\n notifySubscribers()\r\n}\r\n\r\n/**\r\n * Mark all subtree is non actual.\r\n * Collect all nodes to notify subscribers im microtask queue.\r\n */\r\nconst invalidateSubtree = (state: CommonInternal) => {\r\n const stack: CommonInternal[] = [state]\r\n\r\n while (stack.length) {\r\n const st = stack.pop()\r\n st.childs.forEach((it) => stack.push(it))\r\n st.hasParentUpdates = true\r\n if (st.subscribes.size) {\r\n states2notify.add(st)\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Notify all collected subscribers once in microtask queue\r\n */\r\nconst notifySubscribers = () => {\r\n if (isNotifying === false) {\r\n isNotifying = true\r\n queueMicrotask(() => {\r\n // Нужно обновить дерево\r\n states2notify.forEach((state) => {\r\n try {\r\n state.subscribes.forEach((listner) => {\r\n return listner(getValue(state))\r\n })\r\n } catch (e) {\r\n console.error('Error in subscriber function of:', state.name)\r\n }\r\n })\r\n states2notify.clear()\r\n isNotifying = false\r\n })\r\n }\r\n}\r\n\r\n/**\r\n * Start collecting all non computed states.\r\n *\r\n * Helper for render adapters.\r\n */\r\nexport const startRecord = () => {\r\n recording = new Set()\r\n}\r\n\r\n/**\r\n * Flush all collected non computed states.\r\n */\r\nexport const flushStates = (): Set<StateInternal> => {\r\n const data = recording\r\n recording = undefined\r\n return data\r\n}\r\n\r\nexport const subscribe = (state: CommonInternal | CommonInternal, listner: Listner): UnSubscribe => {\r\n /**\r\n * Если значение стейта ниразу не расчитывалось, его нужно обновить\r\n * Если подписываемся на вычисляемый стэйт, то нужно узнать всех родителей\r\n * Родители могут меняться, поэтому после каждого вычисления нужно обновлять зависимости дерева\r\n *\r\n * При отписке нужно оповестить всех на кого были опдписанты о том что мы отписались\r\n *\r\n */\r\n\r\n if (state.subscribes.has(listner)) {\r\n return () => ({})\r\n }\r\n\r\n const computedState = getComputed(state)\r\n // Нужно актуализировать в родилеях зависимость\r\n if (computedState) {\r\n getComputedValue(computedState)\r\n state.depends.forEach((parent) => parent.childs.add(state))\r\n }\r\n\r\n state.subscribes.add(listner)\r\n\r\n return () => {\r\n state.subscribes.delete(listner)\r\n if (state.subscribes.size === 0) {\r\n state.depends.forEach((parent) => parent.childs.delete(state))\r\n }\r\n }\r\n}\r\n\r\nconst assert = (condtion: boolean, msg: string) => {\r\n if (condtion) {\r\n throw new Error(msg)\r\n }\r\n}\r\n\r\n/**\r\n *\r\n * @param value - Reducer or value\r\n * @param name - name of state. For loggin or easy debug\r\n * @returns State<T>\r\n */\r\nexport function state<T extends StateType = StateType>(value: T, options?: Options): State<T> {\r\n assert(isFunction(value), 'Function not allowed in state')\r\n\r\n const data: CommonInternal = {\r\n childs: new Set(),\r\n depends: new Set(),\r\n history: Array.from({length: settings.historyLength}),\r\n historyCursor: -1,\r\n name: getName(options?.name),\r\n subscribes: new Set(),\r\n hasParentUpdates: undefined,\r\n }\r\n\r\n setValue(data, value)\r\n\r\n const publicApi = function () {\r\n return getValue(data)\r\n }\r\n\r\n Object.defineProperty(publicApi, 'name', {value: data.name})\r\n publicApi.subscribe = (listner: Listner) => subscribe(data, listner)\r\n publicApi.set = (value: T) => setValue(data, value)\r\n publicApi._internal = data\r\n\r\n return publicApi as State<T>\r\n}\r\n\r\nexport const computed = <\r\n T extends StateType = -1,\r\n S extends StatlessFunc<T> = StatlessFunc<T>,\r\n O extends Nullable<ComputedInternalOptions> = Nullable<ComputedInternalOptions>,\r\n>(\r\n value: GetStatlessFunc<T, S, O>,\r\n options?: O,\r\n): Computed<T> => {\r\n const data: ComputedInternal = {\r\n childs: new Set(),\r\n depends: new Set(),\r\n hasParentUpdates: true,\r\n history: Array.from({length: settings.historyLength}),\r\n historyCursor: -1,\r\n initial: options?.initial as ReturnType<typeof value> | undefined,\r\n isComputing: false,\r\n name: getName(options?.name),\r\n reducer: value,\r\n subscribes: new Set(),\r\n }\r\n\r\n const publicApi = function () {\r\n return getValue(data)\r\n }\r\n\r\n Object.defineProperty(publicApi, 'name', {value: data.name})\r\n publicApi.subscribe = (listner: Listner<T>) => subscribe(data, listner as Listner)\r\n publicApi._internal = data\r\n\r\n return publicApi as Computed<T>\r\n}\r\n\r\n/**\r\n * Action state\r\n * @param value - Action function\r\n * @param name\r\n */\r\nexport const action = <T extends unknown[]>(\r\n value: (...args: T) => void,\r\n options?: ActionOptions,\r\n): Action<T> => {\r\n return {\r\n run: (...args: T) => {\r\n isActionNow = true\r\n value(...args)\r\n isActionNow = false\r\n return this\r\n },\r\n name: getName(options?.name),\r\n onAction: options?.onAction,\r\n }\r\n}\r\n"],"names":["_this","this","recording","isNotifying","names","Set","requesters","states2notify","getHistoryValue","state","history","historyCursor","pushHistory","value","length","getName","name","has","console","error","defaultName","getComputed","isFunction","v","getComputedValue","prevState","hasParentUpdates","undefined","isDontNeedRecalc","depends","forEach","item","add","assert","isComputing","push","childs","delete","clear","reducer","initial","pop","e","message","getValue","lastRequester","at","setValue","newValue","getValueOfSetterFunction","invalidateSubtree","notifySubscribers","stack","st","it","subscribes","size","queueMicrotask","listner","startRecord","data","subscribe","computedState","parent","condtion","msg","Error","options","Array","from","publicApi","Object","defineProperty","set","_internal","computed","action","run","slice","call","arguments","onAction"],"mappings":"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"}

@@ -1,1 +0,1 @@

{"version":3,"file":"index.umd.js","sources":["../src/core.ts"],"sourcesContent":["import {\r\n ComputedInternal,\r\n Listner,\r\n StateType,\r\n Settings,\r\n StateVariants,\r\n Action,\r\n Options,\r\n ComputedInternalOptions,\r\n Nullable,\r\n StatlessFunc,\r\n GetStatlessFunc,\r\n HistoryInternal,\r\n State,\r\n Computed,\r\n Func,\r\n UnSubscribe,\r\n CommonInternal,\r\n StateInternal,\r\n SetterFunc,\r\n ActionOptions,\r\n} from './types.js'\r\n\r\nlet isNotifying = false\r\nlet isActionNow = false\r\nlet recording: Set<StateInternal> | undefined\r\n\r\nconst defaultName = 'Unnamed state'\r\nconst names = new Set()\r\nconst requesters: ComputedInternal[] = []\r\nconst states2notify = new Set<StateVariants>()\r\nconst settings: Settings = {\r\n historyLength: 5,\r\n}\r\n\r\nexport const getHistoryValue = (state: StateVariants): unknown => {\r\n return state.history[state.historyCursor]\r\n}\r\nconst pushHistory = <T extends HistoryInternal>(state: T, value: unknown) => {\r\n const cursorHistory = state.historyCursor\r\n state.historyCursor = (cursorHistory + 1) % state.history.length\r\n state.history[state.historyCursor] = value\r\n}\r\n\r\nconst getName = (name?: string): string => {\r\n if (name && names.has(name)) {\r\n console.error(`Name ${name} already used! Replaced to undefined`)\r\n return defaultName\r\n }\r\n if (name) {\r\n return name\r\n }\r\n return defaultName\r\n}\r\n\r\nexport const setSetting = (data: Partial<Settings>) => {\r\n Object.assign(settings, data)\r\n}\r\n\r\nconst getComputed = (state: CommonInternal | ComputedInternal) => {\r\n if ('reducer' in state) {\r\n return state\r\n }\r\n}\r\n\r\nconst isFunction = (v: unknown): v is Func => {\r\n return typeof v === 'function'\r\n}\r\n\r\nconst isDontNeedRecalc = (state: CommonInternal, prevState: unknown): boolean => {\r\n return state.hasParentUpdates === false && prevState !== undefined\r\n}\r\n\r\nconst getComputedValue = (state: ComputedInternal): unknown => {\r\n try {\r\n const prevState = getHistoryValue(state)\r\n\r\n if (isDontNeedRecalc(state, prevState)) {\r\n if (recording) {\r\n state.depends.forEach((item) => {\r\n recording?.add(item)\r\n })\r\n }\r\n return prevState\r\n }\r\n\r\n assert(state.isComputing, `Loops dosen't allows. Name: ${state.name ?? 'Unnamed state'}`)\r\n\r\n requesters.push(state)\r\n state.depends.forEach((item) => {\r\n item.childs.delete(state)\r\n })\r\n state.depends.clear()\r\n state.isComputing = true\r\n const value = state.reducer(prevState ?? state.initial)\r\n state.isComputing = false\r\n state.hasParentUpdates = false\r\n\r\n requesters.pop()\r\n pushHistory(state, value)\r\n\r\n return value\r\n } catch (e) {\r\n console.error((e as Error).message)\r\n return undefined\r\n }\r\n}\r\n\r\nconst getValue = (state: CommonInternal) => {\r\n const reducer = getComputed(state)\r\n try {\r\n const lastRequester = requesters.at(-1)\r\n if (lastRequester && !state.childs.has(lastRequester)) {\r\n state.childs.add(lastRequester)\r\n lastRequester.depends.add(state)\r\n }\r\n if (reducer) {\r\n return getComputedValue(reducer)\r\n }\r\n return getHistoryValue(state)\r\n } finally {\r\n if (recording && !reducer) {\r\n recording.add(state)\r\n }\r\n }\r\n}\r\n\r\nconst getValueOfSetterFunction = (state: CommonInternal, value: SetterFunc): unknown => {\r\n const prevValue = getHistoryValue(state)\r\n return value(prevValue)\r\n}\r\n\r\nconst setValue = (state: CommonInternal, value: unknown): void => {\r\n const newValue = isFunction(value) ? getValueOfSetterFunction(state, value) : value\r\n\r\n if (newValue === getHistoryValue(state)) {\r\n return\r\n }\r\n pushHistory(state, newValue)\r\n invalidateSubtree(state)\r\n notifySubscribers()\r\n}\r\n\r\n/**\r\n * Mark all subtree is non actual.\r\n * Collect all nodes to notify subscribers im microtask queue.\r\n */\r\nconst invalidateSubtree = (state: CommonInternal) => {\r\n const stack: CommonInternal[] = [state]\r\n\r\n while (stack.length) {\r\n const st = stack.pop()\r\n st.childs.forEach((it) => stack.push(it))\r\n st.hasParentUpdates = true\r\n if (st.subscribes.size) {\r\n states2notify.add(st)\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Notify all collected subscribers once in microtask queue\r\n */\r\nconst notifySubscribers = () => {\r\n if (isNotifying === false) {\r\n isNotifying = true\r\n queueMicrotask(() => {\r\n // Нужно обновить дерево\r\n states2notify.forEach((state) => {\r\n try {\r\n state.subscribes.forEach((listner) => {\r\n return listner(getValue(state))\r\n })\r\n } catch (e) {\r\n console.error('Error in subscriber function of:', state.name)\r\n }\r\n })\r\n states2notify.clear()\r\n isNotifying = false\r\n })\r\n }\r\n}\r\n\r\n/**\r\n * Start collecting all non computed states.\r\n *\r\n * Helper for render adapters.\r\n */\r\nexport const startRecord = () => {\r\n recording = new Set()\r\n}\r\n\r\n/**\r\n * Flush all collected non computed states.\r\n */\r\nexport const flushStates = (): Set<StateInternal> => {\r\n const data = recording\r\n recording = undefined\r\n return data\r\n}\r\n\r\nexport const subscribe = (state: CommonInternal | CommonInternal, listner: Listner): UnSubscribe => {\r\n /**\r\n * Если значение стейта ниразу не расчитывалось, его нужно обновить\r\n * Если подписываемся на вычисляемый стэйт, то нужно узнать всех родителей\r\n * Родители могут меняться, поэтому после каждого вычисления нужно обновлять зависимости дерева\r\n *\r\n * При отписке нужно оповестить всех на кого были опдписанты о том что мы отписались\r\n *\r\n */\r\n\r\n if (state.subscribes.has(listner)) {\r\n return () => ({})\r\n }\r\n\r\n const computedState = getComputed(state)\r\n // Нужно актуализировать в родилеях зависимость\r\n if (computedState) {\r\n getComputedValue(computedState)\r\n state.depends.forEach((parent) => parent.childs.add(state))\r\n }\r\n\r\n state.subscribes.add(listner)\r\n\r\n return () => {\r\n state.subscribes.delete(listner)\r\n if (state.subscribes.size === 0) {\r\n state.depends.forEach((parent) => parent.childs.delete(state))\r\n }\r\n }\r\n}\r\n\r\nconst assert = (condtion: boolean, msg: string) => {\r\n if (condtion) {\r\n throw new Error(msg)\r\n }\r\n}\r\n\r\n/**\r\n *\r\n * @param value - Reducer or value\r\n * @param name - name of state. For loggin or easy debug\r\n * @returns State<T>\r\n */\r\nexport function state<T extends StateType = StateType>(value: T, options?: Options): State<T> {\r\n assert(isFunction(value), 'Function not allowed in state')\r\n\r\n const data: CommonInternal = {\r\n childs: new Set(),\r\n depends: new Set(),\r\n history: Array.from({length: settings.historyLength}),\r\n historyCursor: -1,\r\n name: getName(options?.name),\r\n subscribes: new Set(),\r\n hasParentUpdates: undefined,\r\n }\r\n\r\n setValue(data, value)\r\n\r\n const publicApi = function () {\r\n return getValue(data)\r\n }\r\n\r\n Object.defineProperty(publicApi, 'name', {value: data.name})\r\n publicApi.subscribe = (listner: Listner) => subscribe(data, listner)\r\n publicApi.set = (value: T) => setValue(data, value)\r\n publicApi._internal = data\r\n\r\n return publicApi as State<T>\r\n}\r\n\r\nexport const computed = <\r\n T extends StateType = -1,\r\n S extends StatlessFunc<T> = StatlessFunc<T>,\r\n O extends Nullable<ComputedInternalOptions> = Nullable<ComputedInternalOptions>,\r\n>(\r\n value: GetStatlessFunc<T, S, O>,\r\n options?: O,\r\n): Computed<T> => {\r\n const data: ComputedInternal = {\r\n childs: new Set(),\r\n depends: new Set(),\r\n hasParentUpdates: true,\r\n history: Array.from({length: settings.historyLength}),\r\n historyCursor: -1,\r\n initial: options?.initial as ReturnType<typeof value> | undefined,\r\n isComputing: false,\r\n name: getName(options?.name),\r\n reducer: value,\r\n subscribes: new Set(),\r\n }\r\n\r\n const publicApi = function () {\r\n return getValue(data)\r\n }\r\n\r\n Object.defineProperty(publicApi, 'name', {value: data.name})\r\n publicApi.subscribe = (listner: Listner<T>) => subscribe(data, listner as Listner)\r\n publicApi._internal = data\r\n\r\n return publicApi as Computed<T>\r\n}\r\n\r\n/**\r\n * ## Action state\r\n *\r\n * @param value - Action function\r\n * @param name\r\n */\r\nexport const action = <T extends unknown[]>(\r\n value: (...args: T) => void,\r\n options?: ActionOptions,\r\n): Action<T> => {\r\n return {\r\n run: (...args: T) => {\r\n isActionNow = true\r\n value(...args)\r\n isActionNow = false\r\n return this\r\n },\r\n name: getName(options?.name),\r\n onAction: options?.onAction,\r\n }\r\n}\r\n"],"names":["_this","this","recording","isNotifying","names","Set","requesters","states2notify","getHistoryValue","state","history","historyCursor","pushHistory","value","length","getName","name","has","console","error","defaultName","getComputed","isFunction","v","getComputedValue","prevState","hasParentUpdates","undefined","isDontNeedRecalc","depends","forEach","item","add","assert","isComputing","push","childs","delete","clear","reducer","initial","pop","e","message","getValue","lastRequester","at","setValue","newValue","getValueOfSetterFunction","invalidateSubtree","notifySubscribers","stack","st","it","subscribes","size","queueMicrotask","listner","subscribe","computedState","parent","condtion","msg","Error","options","run","slice","call","arguments","onAction","data","Array","from","publicApi","Object","defineProperty","_internal","set"],"mappings":"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"}
{"version":3,"file":"index.umd.js","sources":["../src/core.ts"],"sourcesContent":["import {\r\n ComputedInternal,\r\n Listner,\r\n StateType,\r\n Settings,\r\n StateVariants,\r\n Action,\r\n Options,\r\n ComputedInternalOptions,\r\n Nullable,\r\n StatlessFunc,\r\n GetStatlessFunc,\r\n HistoryInternal,\r\n State,\r\n Computed,\r\n Func,\r\n UnSubscribe,\r\n CommonInternal,\r\n StateInternal,\r\n SetterFunc,\r\n ActionOptions,\r\n} from './types.js'\r\n\r\nlet isNotifying = false\r\nlet isActionNow = false\r\nlet recording: Set<StateInternal> | undefined\r\n\r\nconst defaultName = 'Unnamed state'\r\nconst names = new Set()\r\nconst requesters: ComputedInternal[] = []\r\nconst states2notify = new Set<StateVariants>()\r\nconst settings: Settings = {\r\n historyLength: 5,\r\n}\r\n\r\nexport const getHistoryValue = (state: StateVariants): unknown => {\r\n return state.history[state.historyCursor]\r\n}\r\nconst pushHistory = <T extends HistoryInternal>(state: T, value: unknown) => {\r\n const cursorHistory = state.historyCursor\r\n state.historyCursor = (cursorHistory + 1) % state.history.length\r\n state.history[state.historyCursor] = value\r\n}\r\n\r\nconst getName = (name?: string): string => {\r\n if (name && names.has(name)) {\r\n console.error(`Name ${name} already used! Replaced to undefined`)\r\n return defaultName\r\n }\r\n if (name) {\r\n return name\r\n }\r\n return defaultName\r\n}\r\n\r\nexport const setSetting = (data: Partial<Settings>) => {\r\n Object.assign(settings, data)\r\n}\r\n\r\nconst getComputed = (state: CommonInternal | ComputedInternal) => {\r\n if ('reducer' in state) {\r\n return state\r\n }\r\n}\r\n\r\nconst isFunction = (v: unknown): v is Func => {\r\n return typeof v === 'function'\r\n}\r\n\r\nconst isDontNeedRecalc = (state: CommonInternal, prevState: unknown): boolean => {\r\n return state.hasParentUpdates === false && prevState !== undefined\r\n}\r\n\r\nconst getComputedValue = (state: ComputedInternal): unknown => {\r\n try {\r\n const prevState = getHistoryValue(state)\r\n\r\n if (isDontNeedRecalc(state, prevState)) {\r\n if (recording) {\r\n state.depends.forEach((item) => {\r\n recording?.add(item)\r\n })\r\n }\r\n return prevState\r\n }\r\n\r\n assert(state.isComputing, `Loops dosen't allows. Name: ${state.name ?? 'Unnamed state'}`)\r\n\r\n requesters.push(state)\r\n state.depends.forEach((item) => {\r\n item.childs.delete(state)\r\n })\r\n state.depends.clear()\r\n state.isComputing = true\r\n const value = state.reducer(prevState ?? state.initial)\r\n state.isComputing = false\r\n state.hasParentUpdates = false\r\n\r\n requesters.pop()\r\n pushHistory(state, value)\r\n\r\n return value\r\n } catch (e) {\r\n console.error((e as Error).message)\r\n return undefined\r\n }\r\n}\r\n\r\nconst getValue = (state: CommonInternal) => {\r\n const reducer = getComputed(state)\r\n try {\r\n const lastRequester = requesters.at(-1)\r\n if (lastRequester && !state.childs.has(lastRequester)) {\r\n state.childs.add(lastRequester)\r\n lastRequester.depends.add(state)\r\n }\r\n if (reducer) {\r\n return getComputedValue(reducer)\r\n }\r\n return getHistoryValue(state)\r\n } finally {\r\n if (recording && !reducer) {\r\n recording.add(state)\r\n }\r\n }\r\n}\r\n\r\nconst getValueOfSetterFunction = (state: CommonInternal, value: SetterFunc): unknown => {\r\n const prevValue = getHistoryValue(state)\r\n return value(prevValue)\r\n}\r\n\r\nconst setValue = (state: CommonInternal, value: unknown): void => {\r\n const newValue = isFunction(value) ? getValueOfSetterFunction(state, value) : value\r\n\r\n if (newValue === getHistoryValue(state)) {\r\n return\r\n }\r\n pushHistory(state, newValue)\r\n invalidateSubtree(state)\r\n notifySubscribers()\r\n}\r\n\r\n/**\r\n * Mark all subtree is non actual.\r\n * Collect all nodes to notify subscribers im microtask queue.\r\n */\r\nconst invalidateSubtree = (state: CommonInternal) => {\r\n const stack: CommonInternal[] = [state]\r\n\r\n while (stack.length) {\r\n const st = stack.pop()\r\n st.childs.forEach((it) => stack.push(it))\r\n st.hasParentUpdates = true\r\n if (st.subscribes.size) {\r\n states2notify.add(st)\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Notify all collected subscribers once in microtask queue\r\n */\r\nconst notifySubscribers = () => {\r\n if (isNotifying === false) {\r\n isNotifying = true\r\n queueMicrotask(() => {\r\n // Нужно обновить дерево\r\n states2notify.forEach((state) => {\r\n try {\r\n state.subscribes.forEach((listner) => {\r\n return listner(getValue(state))\r\n })\r\n } catch (e) {\r\n console.error('Error in subscriber function of:', state.name)\r\n }\r\n })\r\n states2notify.clear()\r\n isNotifying = false\r\n })\r\n }\r\n}\r\n\r\n/**\r\n * Start collecting all non computed states.\r\n *\r\n * Helper for render adapters.\r\n */\r\nexport const startRecord = () => {\r\n recording = new Set()\r\n}\r\n\r\n/**\r\n * Flush all collected non computed states.\r\n */\r\nexport const flushStates = (): Set<StateInternal> => {\r\n const data = recording\r\n recording = undefined\r\n return data\r\n}\r\n\r\nexport const subscribe = (state: CommonInternal | CommonInternal, listner: Listner): UnSubscribe => {\r\n /**\r\n * Если значение стейта ниразу не расчитывалось, его нужно обновить\r\n * Если подписываемся на вычисляемый стэйт, то нужно узнать всех родителей\r\n * Родители могут меняться, поэтому после каждого вычисления нужно обновлять зависимости дерева\r\n *\r\n * При отписке нужно оповестить всех на кого были опдписанты о том что мы отписались\r\n *\r\n */\r\n\r\n if (state.subscribes.has(listner)) {\r\n return () => ({})\r\n }\r\n\r\n const computedState = getComputed(state)\r\n // Нужно актуализировать в родилеях зависимость\r\n if (computedState) {\r\n getComputedValue(computedState)\r\n state.depends.forEach((parent) => parent.childs.add(state))\r\n }\r\n\r\n state.subscribes.add(listner)\r\n\r\n return () => {\r\n state.subscribes.delete(listner)\r\n if (state.subscribes.size === 0) {\r\n state.depends.forEach((parent) => parent.childs.delete(state))\r\n }\r\n }\r\n}\r\n\r\nconst assert = (condtion: boolean, msg: string) => {\r\n if (condtion) {\r\n throw new Error(msg)\r\n }\r\n}\r\n\r\n/**\r\n *\r\n * @param value - Reducer or value\r\n * @param name - name of state. For loggin or easy debug\r\n * @returns State<T>\r\n */\r\nexport function state<T extends StateType = StateType>(value: T, options?: Options): State<T> {\r\n assert(isFunction(value), 'Function not allowed in state')\r\n\r\n const data: CommonInternal = {\r\n childs: new Set(),\r\n depends: new Set(),\r\n history: Array.from({length: settings.historyLength}),\r\n historyCursor: -1,\r\n name: getName(options?.name),\r\n subscribes: new Set(),\r\n hasParentUpdates: undefined,\r\n }\r\n\r\n setValue(data, value)\r\n\r\n const publicApi = function () {\r\n return getValue(data)\r\n }\r\n\r\n Object.defineProperty(publicApi, 'name', {value: data.name})\r\n publicApi.subscribe = (listner: Listner) => subscribe(data, listner)\r\n publicApi.set = (value: T) => setValue(data, value)\r\n publicApi._internal = data\r\n\r\n return publicApi as State<T>\r\n}\r\n\r\nexport const computed = <\r\n T extends StateType = -1,\r\n S extends StatlessFunc<T> = StatlessFunc<T>,\r\n O extends Nullable<ComputedInternalOptions> = Nullable<ComputedInternalOptions>,\r\n>(\r\n value: GetStatlessFunc<T, S, O>,\r\n options?: O,\r\n): Computed<T> => {\r\n const data: ComputedInternal = {\r\n childs: new Set(),\r\n depends: new Set(),\r\n hasParentUpdates: true,\r\n history: Array.from({length: settings.historyLength}),\r\n historyCursor: -1,\r\n initial: options?.initial as ReturnType<typeof value> | undefined,\r\n isComputing: false,\r\n name: getName(options?.name),\r\n reducer: value,\r\n subscribes: new Set(),\r\n }\r\n\r\n const publicApi = function () {\r\n return getValue(data)\r\n }\r\n\r\n Object.defineProperty(publicApi, 'name', {value: data.name})\r\n publicApi.subscribe = (listner: Listner<T>) => subscribe(data, listner as Listner)\r\n publicApi._internal = data\r\n\r\n return publicApi as Computed<T>\r\n}\r\n\r\n/**\r\n * Action state\r\n * @param value - Action function\r\n * @param name\r\n */\r\nexport const action = <T extends unknown[]>(\r\n value: (...args: T) => void,\r\n options?: ActionOptions,\r\n): Action<T> => {\r\n return {\r\n run: (...args: T) => {\r\n isActionNow = true\r\n value(...args)\r\n isActionNow = false\r\n return this\r\n },\r\n name: getName(options?.name),\r\n onAction: options?.onAction,\r\n }\r\n}\r\n"],"names":["_this","this","recording","isNotifying","names","Set","requesters","states2notify","getHistoryValue","state","history","historyCursor","pushHistory","value","length","getName","name","has","console","error","defaultName","getComputed","isFunction","v","getComputedValue","prevState","hasParentUpdates","undefined","isDontNeedRecalc","depends","forEach","item","add","assert","isComputing","push","childs","delete","clear","reducer","initial","pop","e","message","getValue","lastRequester","at","setValue","newValue","getValueOfSetterFunction","invalidateSubtree","notifySubscribers","stack","st","it","subscribes","size","queueMicrotask","listner","subscribe","computedState","parent","condtion","msg","Error","options","run","slice","call","arguments","onAction","data","Array","from","publicApi","Object","defineProperty","_internal","set"],"mappings":"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"}
{
"name": "@statx/core",
"version": "1.0.22",
"version": "1.0.27",
"private": false,

@@ -70,3 +70,3 @@ "description": "Extry tiny smart state manager",

},
"gitHead": "fcb5d6aeacb7fa771bd5075d26f3db848128cf18"
"gitHead": "7499f9feeba7c5d3f2181ee76c8cf06370cab2e0"
}