UNPKG

stunk

Version:

Stunk is a lightweight, framework-agnostic state management library for JavaScript and TypeScript. It uses chunk-based state units for efficient updates, reactivity, and performance optimization in React, Vue, Svelte, and Vanilla JS/TS applications.

176 lines (164 loc) 6.77 kB
type Subscriber<T> = (newValue: T) => void; type Middleware<T> = (value: T, next: (newValue: T) => void) => void; type NamedMiddleware<T> = { name?: string; fn: Middleware<T>; }; interface Chunk<T> { /** Get the current value of the chunk. */ get: () => T; /** Set a new value for the chunk & Update existing value efficiently. */ set: (newValueOrUpdater: T | ((currentValue: T) => T)) => void; /** Subscribe to changes in the chunk. Returns an unsubscribe function. */ subscribe: (callback: Subscriber<T>) => () => void; /** Create a derived chunk based on this chunk's value. */ derive: <D>(fn: (value: T) => D) => Chunk<D>; /** Reset the chunk to its initial value. */ reset: () => void; /** Destroy the chunk and all its subscribers. */ destroy: () => void; } /** * Batch multiple chunk updates into a single re-render. * Useful for updating multiple chunks at once without causing multiple re-renders. */ declare function batch(callback: () => void): void; declare function chunk<T>(initialValue: T, middleware?: (Middleware<T> | NamedMiddleware<T>)[]): Chunk<T>; type AsyncChunkOpt<T, E extends Error> = { initialData?: T | null; onError?: (error: E) => void; retryCount?: number; retryDelay?: number; }; type InferAsyncData<T> = T extends AsyncChunk<infer U, Error> ? U : never; type CombinedData<T extends Record<string, AsyncChunk<any>>> = { [K in keyof T]: InferAsyncData<T[K]> | null; }; type CombinedState<T extends Record<string, AsyncChunk<any>>> = { loading: boolean; error: Error | null; errors: Partial<{ [K in keyof T]: Error; }>; data: CombinedData<T>; }; interface AsyncState<T, E extends Error> { loading: boolean; error: E | null; data: T | null; lastFetched?: number; } interface RefreshConfig { /** Time in milliseconds after which data becomes stale */ staleTime?: number; /** Time in milliseconds to cache data before considering it expired */ cacheTime?: number; /** Auto-refresh interval in milliseconds */ refetchInterval?: number; } interface AsyncChunkOptExtended<T, E extends Error> extends AsyncChunkOpt<T, E> { refresh?: RefreshConfig; /** Enable/disable the fetcher - useful for conditional fetching */ enabled?: boolean; } interface AsyncChunk<T, E extends Error = Error> extends Chunk<AsyncState<T, E>> { /** Reload the data from the source. */ reload: () => Promise<void>; /** Smart refresh - respects stale time */ refresh: () => Promise<void>; /** Mutate the data directly. */ mutate: (mutator: (currentData: T | null) => T) => void; /** Reset the state to the initial value. */ reset: () => void; /** Clean up intervals and timeouts */ cleanup: () => void; } declare function asyncChunk<T, E extends Error = Error>(fetcher: () => Promise<T>, options?: AsyncChunkOptExtended<T, E>): AsyncChunk<T, E>; declare function asyncChunk<T, E extends Error = Error, P extends any[] = []>(fetcher: (...params: P) => Promise<T>, options?: AsyncChunkOptExtended<T, E>): AsyncChunk<T, E> & { /** Reload with new parameters */ reload: (...params: P) => Promise<void>; /** Smart refresh with parameters */ refresh: (...params: P) => Promise<void>; /** Set parameters for future calls */ setParams: (...params: P) => void; }; type ChunkValue<T> = T extends Chunk<infer U> ? U : never; type DependencyValues<T extends Chunk<any>[]> = { [K in keyof T]: T[K] extends Chunk<any> ? ChunkValue<T[K]> : never; }; interface Computed<T> extends Chunk<T> { /** * Checks if the computed value needs to be recalculated due to dependency changes. * @returns True if the computed value is dirty, false otherwise. */ isDirty: () => boolean; /** Manually forces recalculation of the computed value from its dependencies. */ recompute: () => void; } declare function computed<TDeps extends Chunk<any>[], TResult>(dependencies: [...TDeps], computeFn: (...args: DependencyValues<TDeps>) => TResult): Computed<TResult>; interface SelectOptions { /** * Configuration options for selector functions. * @property {boolean} [useShallowEqual] - When true, performs a shallow equality check * on the derived selector results to prevent unnecessary updates. */ useShallowEqual?: boolean; } /** * Creates a derived read-only chunk based on a selector function. * @param sourceChunk The source chunk to derive from. * @param selector A function that extracts part of the source value. * @param options Optional settings for shallow equality comparison. * @returns A read-only derived chunk. */ declare function select<T, S>(sourceChunk: Chunk<T>, selector: (value: T) => S, options?: SelectOptions): Chunk<S>; declare function isValidChunkValue(value: unknown): boolean; declare function isChunk<T>(value: unknown): value is Chunk<T>; declare function once<T>(fn: () => T): () => T; declare function combineAsyncChunks<T extends Record<string, AsyncChunk<any>>>(chunks: T): Chunk<CombinedState<T>>; declare const logger: Middleware<any>; declare const nonNegativeValidator: Middleware<number>; interface ChunkWithHistory<T> extends Chunk<T> { /** * Reverts to the previous state (if available). */ undo: () => void; /** * Moves to the next state (if available). */ redo: () => void; /** * Returns true if there is a previous state to revert to. */ canUndo: () => boolean; /** * Returns true if there is a next state to move to. */ canRedo: () => boolean; /** * Returns an array of all the values in the history. */ getHistory: () => T[]; /** * Clears the history, keeping only the current value. */ clearHistory: () => void; } declare function withHistory<T>(baseChunk: Chunk<T>, options?: { maxHistory?: number; }): ChunkWithHistory<T>; interface PersistOptions<T> { key: string; storage?: Storage; serialize?: (value: T) => string; deserialize?: (value: string) => T; } declare function withPersistence<T>(baseChunk: Chunk<T>, options: PersistOptions<T>): Chunk<T>; declare const index_logger: typeof logger; declare const index_nonNegativeValidator: typeof nonNegativeValidator; declare const index_withHistory: typeof withHistory; declare const index_withPersistence: typeof withPersistence; declare namespace index { export { index_logger as logger, index_nonNegativeValidator as nonNegativeValidator, index_withHistory as withHistory, index_withPersistence as withPersistence }; } export { type Chunk, type Middleware, asyncChunk, batch, chunk, combineAsyncChunks, computed, isChunk, isValidChunkValue, index as middleware, once, select };