UNPKG

@stacksjs/stx

Version:

A performant UI Framework. Powered by Bun.

324 lines 10.4 kB
/** * Register a store globally. */ export declare function registerStore<T>(name: string, store: Store<T>): void; /** * Get a registered store. */ export declare function getStore<T>(name: string): Store<T> | undefined; /** * Check if a store is registered. */ export declare function hasStore(name: string): boolean; /** * Get all registered store names. */ export declare function getStoreNames(): string[]; /** * Clear all registered stores. */ export declare function clearStores(): void; /** * Create a reactive store. */ export declare function createStore<T>(initialValue: T, options?: StoreOptions<T>): Store<T>; /** * Create a readonly store from a getter function. */ export declare function createReadonlyStore<T>(getter: () => T, options?: { name?: string }): Omit<Store<T>, 'set' | 'update' | 'reset'>; /** * Create a computed value derived from stores. */ export declare function computed<T, S extends readonly Store<any>[]>(stores: S, compute: (...values: { [K in keyof S]: S[K] extends Store<infer V> ? V : never }) => T, options?: ComputedOptions): Store<T>; /** * Create a typed action for a store. */ export declare function createAction<T, P extends unknown[], R>(store: Store<T>, name: string, handler: (state: T, ...params: P) => T | Promise<T>): (...params: P) => R extends Promise<unknown> ? Promise<void> : void; /** * Create multiple actions for a store. */ export declare function createActions<T, A extends Record<string, (state: T, ...args: any[]) => T>>(store: Store<T>, actions: A): { [K in keyof A]: A[K] extends (state: T, ...args: infer P) => T ? (...args: P) => void : never }; /** * Create a selector that derives a value from a store. */ export declare function createSelector<T, R>(store: Store<T>, selector: (state: T) => R, options?: { equals?: (a: R, b: R) => boolean }): Store<R>; /** * Create a selector with memoization. */ export declare function createMemoizedSelector<T, R>(store: Store<T>, selector: (state: T) => R, deps: (state: T) => unknown[]): Store<R>; /** * Logging middleware for debugging. */ export declare function loggerMiddleware<T>(name?: string): StoreMiddleware<T>; /** * Validation middleware. */ export declare function validationMiddleware<T>(validate: (value: T) => boolean | string): StoreMiddleware<T>; /** * Immer-like middleware for immutable updates. */ export declare function immerMiddleware<T extends object>(): StoreMiddleware<T>; /** * Throttle middleware. */ export declare function throttleMiddleware<T>(ms: number): StoreMiddleware<T>; /** * Use a store in a template context. * Returns a reactive reference that auto-updates. */ export declare function useStore<T>(nameOrStore: string | Store<T>): T; /** * Create a store directive for use in templates. */ export declare function createStoreDirective(storeName: string): { name: string hasEndTag: boolean handler: () => string }; /** * Serialize all stores for SSR hydration. */ export declare function serializeStores(): string; /** * Hydrate stores from serialized state. */ export declare function hydrateStores(serialized: string): void; /** * Generate hydration script for SSR. */ export declare function generateHydrationScript(): string; /** * Initialize DevTools integration. */ export declare function initDevTools(): void; /** * Define a store with state, getters, and actions. * * @example * ```typescript * // stores/counter.ts * import { defineStore } from 'stx' * * export const counterStore = defineStore('counter', { * state: { * count: 0, * name: 'Counter' * }, * getters: { * doubleCount: (state) => state.count * 2, * displayName: (state) => `${state.name}: ${state.count}` * }, * actions: { * increment() { this.count++ }, * decrement() { this.count-- }, * incrementBy(amount: number) { this.count += amount }, * async fetchCount() { * const response = await fetch('/api/count') * this.count = await response.json() * } * }, * persist: true // or { storage: 'local', key: 'my-counter' } * }) * ``` * * Usage in components: * ```html * <script client> * import { counterStore } from '@stores' * * // Access state * console.log(counterStore.count) // 0 * * // Use getters * console.log(counterStore.doubleCount) // 0 * * // Call actions * counterStore.increment() * counterStore.incrementBy(5) * * // Subscribe to changes * counterStore.$subscribe((state) => { * console.log('Count changed:', state.count) * }) * * // Reset to initial state * counterStore.$reset() * </script> * ``` */ export declare function defineStore<S extends object, G extends Record<string, (state: S) => any> = Record<string, never>, A extends Record<string, (...args: any[]) => any> = Record<string, never>>(id: string, options: DefineStoreOptions<S, G, A>): DefinedStoreWithGettersAndActions<S, G, A>; /** * Get a defined store by name. * Used internally by the @stores import transformation. */ export declare function getDefinedStore<S extends object = any>(name: string): DefinedStoreWithGettersAndActions<S, any, any> | undefined; /** * Get all defined store names. */ export declare function getDefinedStoreNames(): string[]; /** * Check if a store is defined. */ export declare function hasDefinedStore(name: string): boolean; /** * Generate client-side runtime code for store imports. * Uses the stx runtime to avoid exposing window.* to developers. */ export declare function generateStoreImportRuntime(): string; /** * Transform import statements from @stores to runtime code. * * Transforms: * ```js * import { appStore, chatStore } from '@stores' * ``` * * Into: * ```js * const appStore = stx.useStore('appStore'); * const chatStore = stx.useStore('chatStore'); * ``` * * The stx runtime is injected automatically and abstracts away window.* access. */ export declare function transformStoreImports(code: string): string; /** * Generate store registration code for the client. * * @example * ```js * // In your stores file (e.g., stores/index.ts) * import { defineStore, registerStoresClient } from 'stx' * * export const appStore = defineStore('app', { ... }) * export const chatStore = defineStore('chat', { ... }) * * // Register for client-side @stores imports * if (typeof window !== 'undefined') { * registerStoresClient({ appStore, chatStore }) * } * ``` */ export declare function registerStoresClient(stores: Record<string, DefinedStoreWithGettersAndActions<any, any, any>>): void; /** Store options */ export declare interface StoreOptions<T> { name?: string persist?: PersistOptions devtools?: boolean middleware?: StoreMiddleware<T>[] equals?: (a: T, b: T) => boolean } /** Persistence options */ export declare interface PersistOptions { storage?: 'local' | 'session' | 'memory' key?: string serialize?: (value: unknown) => string deserialize?: (value: string) => unknown paths?: string[] debounce?: number } /** Store interface */ export declare interface Store<T> { get: () => T set: (value: T | ((prev: T) => T)) => void subscribe: (subscriber: Subscriber<T>) => Unsubscribe update: (updater: Partial<T> | ((prev: T) => Partial<T>)) => void reset: () => void name?: string destroy: () => void } /** Computed options */ export declare interface ComputedOptions { equals?: <T>(a: T, b: T) => boolean } /** Action definition */ export declare interface ActionDefinition<T, P extends unknown[], R> { name: string handler: (store: Store<T>, ...params: P) => R } /** Global store state */ export declare interface GlobalState { stores: Map<string, Store<unknown>> subscriptions: Map<string, Set<Subscriber<unknown>>> } /** * Store definition options for defineStore */ export declare interface DefineStoreOptions<S, G extends Record<string, (state: S) => any>, A extends Record<string, (...args: any[]) => any>> { state: S | (() => S) getters?: G actions?: A persist?: PersistOptions | boolean devtools?: boolean } /** * Store instance returned by defineStore */ export declare interface DefinedStore<S, G extends Record<string, (state: S) => any>, A extends Record<string, (...args: any[]) => any>> { $state: S $subscribe: (callback: Subscriber<S>) => Unsubscribe $reset: () => void $patch: (partial: Partial<S> | ((state: S) => void)) => void _store: Store<S> $id: string } /** * State Management Module * * Provides reactive state management for stx templates with support for * both simple stores and complex global state management. * * ## Features * * 1. **Reactive Stores** - Simple observable stores with auto-subscriptions * 2. **Computed Values** - Derived state that auto-updates * 3. **Actions** - Structured state mutations * 4. **Persistence** - LocalStorage/SessionStorage integration * 5. **DevTools** - State inspection and time-travel debugging * 6. **Server State** - Sync state between server and client * * ## Usage * * ```typescript * import { createStore, computed, action } from 'stx/state-management' * * const counter = createStore({ count: 0 }) * * // Subscribe to changes * counter.subscribe(state => console.log(state.count)) * * // Update state * counter.set({ count: counter.get().count + 1 }) * ``` * * In templates: * ```html * <script> * import { useStore } from 'stx/state-management' * const { count } = useStore('counter') * </script> * <p>Count: {{ count }}</p> * ``` * * @module state-management */ /** Subscription callback */ export type Subscriber<T> = (value: T, previousValue: T | undefined) => void /** Unsubscribe function */ export type Unsubscribe = () => void /** Store middleware */ export type StoreMiddleware<T> = ( set: (value: T) => void, get: () => T, store: Store<T> ) => (nextSet: (value: T) => void) => (value: T) => void // Type helper for getters declare type StoreGetters<S, G extends Record<string, (state: S) => any>> = { [K in keyof G]: ReturnType<G[K]> } // Type helper for actions declare type StoreActions<A extends Record<string, (...args: any[]) => any>> = { [K in keyof A]: A[K] } // Full store type combining state, getters, and actions export type DefinedStoreWithGettersAndActions<S, G extends Record<string, (state: S) => any>, A extends Record<string, (...args: any[]) => any>> = DefinedStore<S, G, A> & StoreGetters<S, G> & StoreActions<A>