import { DEFAULT_WATCH_OPTION, DEFAULT_CREATE_OPTION } from '@/helper'; import { makeReference } from '@/core/ref'; import { runner } from '@/connectors/runner'; import type { Renew, StoreType, StateRefStore, StoreRenderList, ManualSyncStore, } from '@/types'; /** * createStore - The argument is the initial value of the state * * Can work with primitive types, or you can work with object types. * The return value is the "watch" function. * * example> * const watch = createStore(7) * // const watch = createStore<{name: string; age: number;}>({ name: 'brown', age: 38 }) * const stateRef = watch(stateRef => { * console.log(stateRef.value)); * }); */ export function createStore(orignalValue: V) { const { watch } = create(orignalValue, { autoSync: true }); return watch; } export function createStoreManualSync(orignalValue: V): ManualSyncStore { return create(orignalValue, { autoSync: false }); } function create(orignalValue: V, userCreateOption?: { autoSync?: boolean }) { const storeRenderList: StoreRenderList = new Map(); const cacheMap = new WeakMap>, StateRefStore>(); const { autoSync } = Object.assign( {}, DEFAULT_CREATE_OPTION, userCreateOption || {} ); const rootValue: StoreType = { root: orignalValue }; const watch = ( renew: Renew> = () => {}, userOption?: { cache?: boolean; editable?: boolean } ): StateRefStore => { const watchOption = Object.assign( {}, DEFAULT_WATCH_OPTION, userOption || { editable: autoSync } ); const { cache, editable } = watchOption; /** * Caching */ if (cache && renew && cacheMap.has(renew)) { return cacheMap.get(renew)!; } /** * Make the value a stateRef. */ return makeReference({ renew, rootValue, storeRenderList, cacheMap, autoSync, editable, }); }; return { watch, updateRef: watch(() => {}, { editable: true }), sync: () => { runner(storeRenderList); }, }; }