UNPKG

@medamajs/compose

Version:

Composable state management extension for medama with support for hierarchical state layers, dynamic composition, and parallel state synchronization

180 lines (162 loc) 6.01 kB
import type { ReadState, SubscribeToState } from 'medama'; import type { CompositeState, CStateG, ExtendedWithStringAliases, LayerPupils, LayerPupilsPreventInference, Merge, PickOriginalNumericKeys, RevealLayersInStateRecursively, } from './auxiliaryTypes'; import type { Normalize } from './type-helpers/Normalize'; /** * Function to create partial state update for composite state. * Used in setState to generate changes based on current values. * * @template State The type of composite state object * @template SChange The type of changes to apply to layers */ export type SetterForCompositeState< State extends CStateG, SChange extends RevealLayersInStateRecursively<State>, > = (state: State) => SChange; /** * Function to update composite state with partial changes. * Accepts either direct state changes or setter function. * * @template State The type of composite state object */ export type SetCompositeState<State extends CStateG> = < SChange extends RevealLayersInStateRecursively<State>, >( stateChange: SChange | SetterForCompositeState<State, SChange> ) => SChange; /** * Function to reset composite state to initial values. * Optionally accepts new initial state for layers. * * @template State The type of composite state object */ export type ResetCompositeState<State extends CStateG> = ( initState?: RevealLayersInStateRecursively<State> ) => void; /** * Function to create new composite state with additional layers. * Returns new instance combining existing and new layers. * Supports both complete and partial initial state for new layers. * * @template State The current composite state type */ export type AddLayers<State extends CStateG> = { <AddedState extends CStateG, Init extends RevealLayersInStateRecursively<State & AddedState>>( layers: LayerPupils<AddedState>, initState?: Init ): Normalize<CompositeMedama<Normalize<State & Merge<AddedState, Init>>>>; /** * Overload that requires explicit generic AddedState parameter. * Prevents type inference from arguments to ensure type safety. */ <AddedState extends CStateG>( layers: LayerPupilsPreventInference<AddedState>, initState?: RevealLayersInStateRecursively<State & AddedState> ): Normalize<CompositeMedama<Normalize<State & AddedState>>>; }; /** * Function to create new composite state without specified layers. * Returns new instance excluding requested layers. * Accepts either single layer key or array of keys. * * @template State The current composite state type * @template K The type of layer keys to exclude */ export type DeleteLayers<State extends CStateG> = <K extends string | number | symbol>( layersToDelete: | PickOriginalNumericKeys<K, keyof State> | (K[] & PickOriginalNumericKeys<K, keyof State>[]) ) => Normalize<CompositeMedama<Normalize<Omit<State, ExtendedWithStringAliases<K>>>>>; /** * Core interface for interacting with composite state. * Extends basic state operations to work with layered state structure. * * @template State The type of composite state object */ export type CompositePupil<State extends CStateG> = { /** * Function to create subscription for selector value changes. * Runs subscription function during initial setup. * Returns methods to manage subscription lifecycle. */ subscribeToState: SubscribeToState<CompositeState<State>>; /** * Function to read current value from state using selector. * Returns memoized result if dependencies haven't changed. */ readState: ReadState<CompositeState<State>>; /** * Function to update composite state with partial changes. * Accepts either direct state changes or setter function. */ setState: SetCompositeState<CompositeState<State>>; /** * Function to reset composite state to initial values. * Optionally accepts new initial state for layers. */ resetState: ResetCompositeState<CompositeState<State>>; }; /** * Extended interface for composite state management. * Adds layer manipulation methods on top of basic state operations. * * @template State The type of composite state object */ export type CompositeMedama<State extends CStateG> = CompositePupil<State> & { /** * Core interface for interacting with composite state. * Extends basic state operations to work with layered state structure. */ pupil: CompositePupil<State>; /** * Function to create new composite state with additional layers. * Returns new instance combining existing and new layers. * Supports both complete and partial initial state for new layers. */ addLayers: AddLayers<State>; /** * Function to create new composite state without specified layers. * Returns new instance excluding requested layers. * Accepts either single layer key or array of keys. */ deleteLayers: DeleteLayers<State>; }; /** * Factory function type for creating composite state instances. * Supports both complete and partial initial state for layers. * * @template State The type of composite state to be created * @template Init The type of initial state values */ export type ComposeMedama = { <State extends CStateG, Init extends RevealLayersInStateRecursively<State>>( layers: LayerPupils<State>, initState?: Init ): Normalize<CompositeMedama<Merge<State, Init>>>; /** * Overload that requires explicit generic State parameter. * Prevents type inference from arguments to ensure type safety. */ <State extends CStateG>( layers: LayerPupilsPreventInference<State>, initState?: RevealLayersInStateRecursively<State> ): Normalize<CompositeMedama<State>>; }; /** * Type guard to check if a state object is composite. * Used to ensure type safety when working with layered state. * * @template State The type of state object to check */ export type IsComposite = <State extends object>( state: State ) => state is State extends CStateG ? CompositeState<State> : never; export type { CompositeState };