UNPKG

zustand-lite

Version:

Zustand Lite builds upon zustand, by auto-generating selectors and simplifying API even more.

109 lines (103 loc) 5.67 kB
import { StoreApi as StoreApi$1 } from 'zustand'; import { DevtoolsOptions, PersistOptions } from 'zustand/middleware'; type State = Record<PropertyKey, unknown>; type EqualityChecker<S> = (state: S, newState: S) => boolean; type Prettify<T> = { [K in keyof T]: T[K]; } & {}; type Override<T, U> = Prettify<Omit<T, keyof U> & U>; type Augments<T, U, Base> = Base & Override<T, U>; type StoreLib<S> = Omit<StoreApi$1<S>, 'setState' | 'getState'>; type GetBase<S extends State> = () => Readonly<S>; type SetBase<S extends State> = StoreApi$1<S>['setState']; type UseBase<S extends State> = UseRecordBase<S>; type OverrideGet<T, U, S extends State> = Augments<T, U, GetBase<S>>; type OverrideSet<T, U, S extends State> = Augments<T, U, SetBase<S>>; type OverrideUse<T, U, S extends State> = Augments<T, U, UseBase<S>>; type GetRecord<S extends Record<string, unknown>> = GetBase<S>; type SetRecord<S extends Record<string, unknown>> = SetBase<S> & { [K in keyof S]-?: (value: S[K]) => any; }; type StoreApiEncapsulated<S extends State = {}, Getters = {}, Setters = {}, ExtraMW = {}> = { api: StoreApi$1<S> & ExtraMW; get: OverrideGet<GetRecord<S>, Getters, S>; set: OverrideSet<SetRecord<S>, Setters, S>; use: OverrideUse<UseRecord<S>, Getters, S>; }; type StoreApi<S extends State = {}, Getters = {}, Setters = {}, ExtraMW = {}> = { api: StoreLib<S> & ExtraMW; get: OverrideGet<GetRecord<S>, Getters, S>; set: OverrideSet<SetRecord<S>, Setters, S>; use: OverrideUse<UseRecord<S>, Getters, S>; composePlugin<P extends (store: StoreApi<S, Getters, Setters, ExtraMW>) => StoreApi<any, any, any, ExtraMW>>(plugin: P): P extends (store: StoreApi<S, Getters, Setters, ExtraMW>) => StoreApi<infer S2, infer G2, infer A2, ExtraMW> ? StoreApi<Override<S, S2>, // merge state Override<Getters, G2>, // merge getters (aware of new S) Override<Setters, A2>, // merge setters (aware of new S) ExtraMW> : never; extendByState<NS extends State>(patch: NoOverlappingKeys<S, NS>): StoreApi<S & NS, Getters, Setters, ExtraMW>; extendByState<NS extends State, Builder extends ByStateBuilder<NS, S, Getters>>(builder: ByStateBuilder<NS, S, Getters>): StoreApi<S & ReturnType<Builder>, Getters, Setters, ExtraMW>; extendGetters<Builder extends GettersBuilder<S, Getters>>(builder: Builder): StoreApi<S, Override<Getters, ReturnType<Builder>>, Setters, ExtraMW>; extendSetters<Builder extends SettersBuilder<S, Getters, Setters>>(builder: Builder): StoreApi<S, Getters, Override<Setters, ReturnType<Builder>>, ExtraMW>; restrictState(): StoreApiEncapsulated<S, Getters, Setters, ExtraMW>; restrictState<Key extends keyof S>(publicState: Key[]): StoreApiEncapsulated<Omit<S, Key>, Getters, Setters, ExtraMW>; }; type GettersBuilder<S extends State, Getters> = (args: { get: OverrideGet<GetRecord<S>, Getters, S>; }) => Record<string, AnyFn>; type SettersBuilder<S extends State, Getters = {}, Setters = {}> = (args: { api: StoreLib<S>; get: OverrideGet<GetRecord<S>, Getters, S>; set: OverrideSet<SetRecord<S>, Setters, S>; }) => Record<string, AnyFn>; type ByStateBuilder<NS extends State, S extends State, Getters = {}> = (args: { get: OverrideGet<GetRecord<S>, Getters, S>; }) => NoOverlappingKeys<S, NS>; type UseRecordBase<S> = { <K extends readonly (keyof S)[]>(selector: K, equality?: EqualityChecker<Pick<S, K[number]>>): Readonly<Pick<S, K[number]>>; <R>(selector: (state: S) => R, equality?: EqualityChecker<R>): R; (selector?: undefined, equality?: EqualityChecker<Readonly<S>>): Readonly<S>; }; type UseRecord<S> = UseRecordDeep<S> & UseRecordBase<S>; type AnyFn = (...args: any[]) => any; type UseRecordDeep<S> = { [K in keyof S]-?: S[K] extends Record<string, any> ? IsOptional<S, K> extends false ? ((equalityFn?: EqualityChecker<S[K]>) => S[K]) & UseRecordDeep<S[K]> : never : (equalityFn?: EqualityChecker<S[K]>) => S[K]; }; type IsOptional<S, K extends keyof S> = undefined extends S[K] ? {} extends Pick<S, K> ? true : false : false; type NoOverlappingKeys<Old, New> = keyof Old & keyof New extends never ? New : never; type MWConfiguration = { devtools?: true | Omit<DevtoolsOptions, 'store'>; persist?: true | Omit<PersistOptions<any>, 'name'>; }; type StorePersist<S> = { persist: { clearStorage: () => void; getOptions: () => Partial<PersistOptions<S, S>>; hasHydrated: () => boolean; onFinishHydration: (fn: (state: S) => void) => () => void; onHydrate: (fn: (state: S) => void) => () => void; read: () => S | undefined; rehydrate: () => Promise<void> | void; setOptions: (options: Partial<PersistOptions<S, S>>) => void; }; }; type GlobalConfig = { appName: string; logging: boolean; }; /** * Identity helper that provides a typed `store` param and preserves the plugin's return type. */ declare function definePlugin<F extends (store: StoreApi) => StoreApi>(fn: F): <S extends State, G, A, MW>(store: StoreApi<S, G, A, MW>) => ReturnType<F>; declare function setGlobalConfig(newConfig: Partial<GlobalConfig>): void; declare function createStore<S extends State, ExtraMW extends MWConfiguration = {}>(initialState: S, options?: { name?: string; middlewares?: ExtraMW; }): StoreApi<S, GetRecord<S>, SetRecord<S>, ExtraMW extends { persist: any; } ? StorePersist<S> : {}>; /** * Basic plugin example, that extends store with custom setter. */ declare const withReset: <S extends State, G, A, MW>(store: StoreApi<S, G, A, MW>) => StoreApi<{}, {}, { reset: () => void; }, {}>; export { createStore, definePlugin, setGlobalConfig, withReset };