@stacksjs/stx
Version:
A performant UI Framework. Powered by Bun.
324 lines • 10.4 kB
TypeScript
/**
* 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>