UNPKG

mute8

Version:
1 lines 10.1 kB
{"version":3,"sources":["../mute8.ts"],"names":["O","J","toJson","deepClone","obj","freeze","assign","entries","defineProperty","MUT_FN_NAME","defaultPlugin","v","Subject","_Subject","state","plugin","fn","id","update","actionName","args","newFinal","key","value","observer","StoreCore","_StoreCore","d","asyncProxy","buildActionProxy","_","actionsProxy","name","core","f","p","ext","extension","bigProxy","store","actions","proxy","aProxy","buildProxy","newStore"],"mappings":"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","sourcesContent":["// Utils\nconst O = Object;\nconst J = JSON;\nconst toJson = J.stringify\nconst deepClone = (obj: object) => J.parse(toJson(obj))\nconst freeze = O.freeze\nconst assign = O.assign;\nconst entries = O.entries;\nconst defineProperty = O.defineProperty;\nconst MUT_FN_NAME = \"mut\"\n\nexport type CallArgs = any[] | Function;\nexport interface Plugin<T> {\n /** BeforeInit() */\n BI(initState: T): T\n /** BeforeUpdate() */\n BU(newState: T): T\n /** AfterChange() */\n AC(oldState: Readonly<T>, newState: T, actionName?: string, args?: CallArgs): void\n}\nconst defaultPlugin: <T>() => Plugin<T> = () => ({\n BI: (v) => v,\n BU: (v) => v,\n AC: () => { }\n})\n\nclass Subject<T> {\n private id: number = 0; // subscription id\n private c: Record<number, SubFn<T>> = {} // subscription container\n private s: Readonly<T> // current state\n private p: Plugin<T> // plugin\n private ps: Sub | null // parent sub (Observer only)\n\n constructor(\n state: T,\n plugin?: Plugin<T> // plugins not allowed for Observer\n ) {\n this.p = plugin ?? defaultPlugin()\n this.s = freeze(this.p.BI(state))\n }\n\n destroy() {\n this.ps?.destroy()\n this.ps = null\n }\n\n sanp(): Readonly<T> {\n return this.s\n }\n\n sub(fn: SubFn<T>): Sub {\n const id = this.id++\n this.c[id] = fn\n return {\n destroy: () => delete this.c[id]\n }\n }\n\n mut(update: Partial<T>, actionName?: string, args?: CallArgs): void {\n // for Observer always full update\n let newFinal: T = update as T;\n if (!this.ps) {\n newFinal = this.p.BU(assign(deepClone(this.s), update))\n }\n\n if (toJson(this.s) !== toJson(newFinal)) {\n this.p.AC(this.s, newFinal, actionName, args)\n this.s = freeze(newFinal)\n // notify subscribers\n O.keys(this.c).forEach(id => this.c[id](this.s))\n }\n }\n\n set<K extends keyof T>(key: K & string | typeof MUT_FN_NAME, value: T[K] | Partial<T>): void {\n const actionName = \"set.\" + key;\n const v = (key === MUT_FN_NAME ? value : { [key]: value }) as Partial<T>;\n this.mut(v, actionName, [value])\n }\n\n select<O>(fn: SelectFn<T, O>): Observer<O> {\n const observer = new Subject(fn(this.sanp()))\n observer.ps = this.sub((v) => observer.mut(fn(v)))\n return observer;\n }\n}\n\ninterface Observer<T> {\n sub(fn: SubFn<T>): Sub\n select<O>(fn: SelectFn<T, O>): Observer<O>\n sanp(): Readonly<T>\n destroy(): void\n}\n\nclass StoreCore<T extends object, A, AA> {\n private readonly p: StoreProxy<T, A, AA>;\n readonly s: Subject<T>\n\n constructor(d: StoreDefiniton<T, A, AA>) {\n this.s = new Subject(d.value)\n const asyncProxy = buildActionProxy(d.async ?? {} as AA, (_, fn) => {\n return async (...args: any[]) => await fn.bind(this.p)(...args)\n })\n const actionsProxy = buildActionProxy(d.actions ?? {} as A, (name, fn) => {\n return (...args: any[]) => this.mut(v => fn.bind(v)(...args), name, args)\n })\n // init proxy\n const core = this;\n this.p = {\n snap: () => core.s.sanp(),\n sub: (v) => core.s.sub(v),\n select: (f) => core.s.select(f),\n actions: actionsProxy,\n async: asyncProxy,\n /** @ts-ignore */\n set mut(v: Partial<T>) { core.s.set(MUT_FN_NAME, v) },\n /** @ts-ignore */\n get mut() { return core.mut.bind(core) }\n }\n\n // init plugin\n const p = d.plugin?.(this.p) ?? defaultPlugin()\n this.s = new Subject(d.value, p)\n }\n\n private mut(fn: (v: T) => void, actionName?: string, args?: any[]): void {\n const state = deepClone(this.s.sanp())\n fn(state)\n this.s.mut(state, actionName, args ?? fn)\n }\n\n static build<T extends object, A, AA>(\n state: StoreDefiniton<T, A, AA>,\n ext?: ProxyExtension<T, A, AA>\n ): Store<T, A, AA> {\n const core = new StoreCore(state)\n const extension = !ext ? {} : { [ext.name]: ext.init(core as StoreCore<any, any, any>) } as {}\n const bigProxy = assign(extension, core.p)\n\n // build store representation (proxy)\n const store = {}\n for (const [key, _] of entries(state.value)) {\n defineProperty(store, key, {\n get() { return core.s.sanp()[key] },\n set(v) { core.s.set(key as any, v) }\n })\n }\n defineProperty(store, MUT_FN_NAME, {\n get() { return core.mut.bind(core) },\n set(v) { core.s.set(MUT_FN_NAME, v) }\n })\n return freeze(assign(store, bigProxy)) as Store<T, A, AA>\n }\n\n}\n\nconst buildActionProxy = <T>(actions: T, proxy: (fnName: string, fn: Function) => Function): T => {\n const aProxy: Record<string, Function> = {}\n entries(actions as object).forEach(([name, fn]) => aProxy[name] = proxy(name, fn))\n return freeze(aProxy) as T\n}\n\n// Proxy\ninterface SmalProxy<T, A> {\n snap(): T\n set mut(v: Partial<T>)\n get mut(): (fn: (v: T) => void, actionName?: string) => void\n actions: Readonly<A>\n}\nexport interface StoreProxy<T, A, AA> extends SmalProxy<T, A> {\n sub(fn: SubFn<T>): Sub\n select<O>(fn: (value: Readonly<T>) => O): Observer<O>\n async: Readonly<AA>\n}\nexport interface ProxyExtension<T extends object, A, AA> {\n name: string,\n init(core: StoreCore<T, A, AA>): object\n}\n\n// Use Only for internal ProxyExtension\nexport const buildProxy = StoreCore.build;\ntype ExcludeKeys = { async?: never, actions?: never, snap?: never, sub?: never, mut?: never }\n// Public\nexport type PluginBuilder = (<T extends object>(proxy: StoreProxy<T, any, any>) => Plugin<T>) | null\nexport type Store<T, A, AA> = StoreProxy<T, A, AA> & T\nexport type SubFn<T> = (value: Readonly<T>) => void\nexport type SelectFn<T, O> = (value: Readonly<T>) => O\nexport type Sub = { destroy(): void }\n\nexport type VoidFn = ((...args: any) => undefined)\nexport type AsyncFn = ((...args: any) => Promise<void>);\nexport interface StoreDefiniton<T extends object, A, AA> {\n value: T & object & ExcludeKeys\n actions?: A & ThisType<T> & Record<string, VoidFn>\n async?: AA & ThisType<SmalProxy<T, A>> & Record<string, AsyncFn>\n plugin?: PluginBuilder\n}\nexport const newStore = <T extends object, A, AA>(state: StoreDefiniton<T, A, AA>) => {\n return buildProxy(state) as Store<T, A, AA>\n}\n"]}