import { Accessor } from 'solid-js';

type CallArgs = any[] | Function;
interface Plugin<T> {
    /** BeforeInit() */
    BI(initState: T): T;
    /** BeforeUpdate() */
    BU(newState: T): T;
    /** AfterChange() */
    AC(oldState: Readonly<T>, newState: T, actionName?: string, args?: CallArgs): void;
}
interface Observer<T> {
    sub(fn: SubFn<T>): Sub;
    select<O>(fn: SelectFn<T, O>): Observer<O>;
    sanp(): Readonly<T>;
    destroy(): void;
}
interface SmalProxy<T, A> {
    snap(): T;
    set mut(v: Partial<T>);
    get mut(): (fn: (v: T) => void, actionName?: string) => void;
    actions: Readonly<A>;
}
interface StoreProxy<T, A, AA> extends SmalProxy<T, A> {
    sub(fn: SubFn<T>): Sub;
    select<O>(fn: (value: Readonly<T>) => O): Observer<O>;
    async: Readonly<AA>;
}
type ExcludeKeys = {
    async?: never;
    actions?: never;
    snap?: never;
    sub?: never;
    mut?: never;
};
type PluginBuilder = (<T extends object>(proxy: StoreProxy<T, any, any>) => Plugin<T>) | null;
type Store$1<T, A, AA> = StoreProxy<T, A, AA> & T;
type SubFn<T> = (value: Readonly<T>) => void;
type SelectFn<T, O> = (value: Readonly<T>) => O;
type Sub = {
    destroy(): void;
};
type VoidFn = ((...args: any) => undefined);
type AsyncFn = ((...args: any) => Promise<void>);
interface StoreDefiniton<T extends object, A, AA> {
    value: T & object & ExcludeKeys;
    actions?: A & ThisType<T & {
        actions: Readonly<A>;
    }> & Record<string, VoidFn>;
    async?: AA & ThisType<SmalProxy<T, A>> & Record<string, AsyncFn>;
    plugin?: PluginBuilder;
}

interface SolidExtension<T> {
    use(): [Accessor<T>, (newValeu: Partial<T>) => void];
    useOne<K extends keyof T>(property: K): [Accessor<T[K]>, (newValue: T[K]) => void];
    select<O>(fn: SelectFn<T, O>): Accessor<O>;
}
type Store<T, A, AA> = Store$1<T, A, AA> & {
    solid: SolidExtension<T>;
};
declare const newStore: <T extends Object, A, AA>(store: StoreDefiniton<T, A, AA>) => Store<T, A, AA>;

export { type AsyncFn, type Plugin, type Store, type Sub, type SubFn, type VoidFn, newStore };
