type CheckFunctionParams<Definition extends PermixDefinition, K extends keyof Definition> = Definition[K]['dataRequired'] extends true ? [
    entity: K,
    action: 'all' | Definition[K]['action'] | Definition[K]['action'][],
    data: Definition[K]['dataType']
] : [
    entity: K,
    action: 'all' | Definition[K]['action'] | Definition[K]['action'][],
    data?: Definition[K]['dataType']
];
type CheckFunctionObject<Definition extends PermixDefinition, K extends keyof Definition> = Definition[K]['dataRequired'] extends true ? {
    entity: K;
    action: 'all' | Definition[K]['action'] | Definition[K]['action'][];
    data: Definition[K]['dataType'];
} : {
    entity: K;
    action: 'all' | Definition[K]['action'] | Definition[K]['action'][];
    data?: Definition[K]['dataType'];
};
interface CheckContext<Definition extends PermixDefinition> {
    entity: keyof Definition;
    actions: Definition[keyof Definition]['action'][];
}

declare function createTemplate<T, Definition extends PermixDefinition>(rules: PermixRules<Definition> | ((param: T) => PermixRules<Definition>)): (param: T) => PermixRules<Definition>;

declare function createHooks<Definition extends PermixDefinition>(): {
    hook: <K extends "setup" | "ready" | "hydrate">(name: K, fn: {
        setup: (state: PermixRules<Definition>) => void;
        ready: () => void;
        hydrate: () => void;
    }[K]) => () => void;
    hookOnce: <K extends "setup" | "ready" | "hydrate">(name: K, fn: {
        setup: (state: PermixRules<Definition>) => void;
        ready: () => void;
        hydrate: () => void;
    }[K]) => void;
    removeHook: <K extends "setup" | "ready" | "hydrate">(name: K, fn: {
        setup: (state: PermixRules<Definition>) => void;
        ready: () => void;
        hydrate: () => void;
    }[K]) => void;
    callHook: <K extends "setup" | "ready" | "hydrate">(name: K, ...args: Parameters<{
        setup: (state: PermixRules<Definition>) => void;
        ready: () => void;
        hydrate: () => void;
    }[K]>) => void;
    clearHook: <K extends "setup" | "ready" | "hydrate">(name: K) => void;
    clearAllHooks: () => void;
};
type PermixDefinition<T extends Record<string, {
    action: string;
    dataType?: unknown;
    dataRequired?: boolean;
}> = Record<string, {
    action: string;
    dataType?: unknown;
    dataRequired?: boolean;
}>> = T;
type PermixStateJSON<Definition extends PermixDefinition = PermixDefinition> = {
    [Key in keyof Definition]: {
        [Action in Definition[Key]['action']]: boolean;
    };
};
type PermixRules<Definition extends PermixDefinition = PermixDefinition> = {
    [Key in keyof Definition]: {
        [Action in Definition[Key]['action']]: boolean | (Definition[Key]['dataRequired'] extends true ? ((data: Definition[Key]['dataType']) => boolean) : ((data: Definition[Key]['dataType'] | undefined) => boolean));
    };
};
declare function checkWithRules<Definition extends PermixDefinition, K extends keyof Definition>(state: PermixRules<Definition> | null, ...[entity, action, data]: CheckFunctionParams<Definition, K>): boolean;
/**
 * Interface for the Permix permission manager
 * @example
 * ```ts
 * const permix = createPermix<{
 *   post: {
 *     dataType: { id: string }
 *     action: 'create' | 'read'
 *   }
 * }>()
 * ```
 */
interface Permix<Definition extends PermixDefinition> {
    /**
     * Check if an action is allowed for an entity using current permissions.
     *
     * @link https://permix.letstri.dev/docs/guide/check
     *
     * @example
     * ```ts
     * // Single action check
     * permix.check('post', 'create') // returns true if allowed
     *
     * // Multiple actions check
     * permix.check('post', ['create', 'read']) // returns true if both actions are allowed
     *
     * // With data
     * permix.check('post', 'read', { id: '123' }) // returns true if allowed exactly with this post
     *
     * // All actions check
     * permix.check('post', 'all') // returns true if ALL actions are allowed
     * ```
     */
    check: <K extends keyof Definition>(...args: CheckFunctionParams<Definition, K>) => boolean;
    /**
     * Similar to `check`, but returns a Promise that resolves once `setup` is called.
     * This ensures permissions are ready before checking them.
     *
     * @link https://permix.letstri.dev/docs/guide/check
     *
     * @example
     * ```ts
     * // Wait for permissions to be ready
     * const canCreate = await permix.checkAsync('post', 'create') // Promise<true>
     *
     * // Multiple actions
     * const canCreateAndRead = await permix.checkAsync('post', ['create', 'read'])
     *
     * // Even if you call setup after checking
     * permix.setup({ post: { create: true } })
     * const canCreate = await permix.checkAsync('post', 'create') // Promise<true>
     * ```
     */
    checkAsync: <K extends keyof Definition>(...args: CheckFunctionParams<Definition, K>) => Promise<boolean>;
    /**
     * Set up permissions.
     *
     * @link https://permix.letstri.dev/docs/guide/setup
     *
     * @example
     * ```ts
     * // Direct permissions object
     * permix.setup({
     *   post: { create: true, read: false }
     * })
     * ```
     */
    setup: <Rules extends PermixRules<Definition>>(callback: Rules) => void;
    /**
     * Register event handler.
     *
     * @link https://permix.letstri.dev/docs/guide/events
     *
     * @returns Function to remove the hook
     *
     * @example
     * ```ts
     * permix.on('setup', () => {
     *   console.log('Permissions were updated')
     * })
     * ```
     */
    hook: ReturnType<typeof createHooks<Definition>>['hook'];
    /**
     * Similar to `hook`, but will be called only once.
     *
     * @link https://permix.letstri.dev/docs/guide/events
     *
     * @returns Function to remove the hook
     *
     * @example
     * ```ts
     * permix.hookOnce('setup', () => {
     *   console.log('Permissions were updated')
     * })
     * ```
     */
    hookOnce: ReturnType<typeof createHooks<Definition>>['hookOnce'];
    /**
     * Define permissions in different place to setup them later.
     *
     * @link https://permix.letstri.dev/docs/guide/template
     *
     * @example
     * ```ts
     * // Some file where you want to define setup without permix instance
     * import { permix } from './permix'
     *
     * const adminPermissions = permix.template({
     *   post: {
     *     create: true,
     *     read: false
     *   }
     * })
     *
     * // Now you can use setup
     * permix.setup(adminPermissions)
     * ```
     */
    template: <T = void>(...params: Parameters<typeof createTemplate<T, Definition>>) => ReturnType<typeof createTemplate<T, Definition>>;
    /**
     * Check if the setup was called.
     *
     * @link https://permix.letstri.dev/docs/guide/ready
     *
     * @example
     * ```ts
     * const isReady = permix.isReady()
     * ```
     */
    isReady: () => boolean;
    /**
     * Similar to `isReady`, but returns a Promise that resolves once `setup` is called.
     *
     * @link https://permix.letstri.dev/docs/guide/ready
     *
     * @example
     * ```ts
     * const isReady = await permix.isReadyAsync()
     * ```
     */
    isReadyAsync: () => Promise<boolean>;
    /**
     * Dehydrate the Permix instance.
     *
     * @link https://permix.letstri.dev/docs/guide/hydration
     *
     * @example
     * ```ts
     * const state = permix.dehydrate()
     * ```
     */
    dehydrate: () => PermixStateJSON<Definition>;
    /**
     * Hydrate the Permix instance.
     *
     * @link https://permix.letstri.dev/docs/guide/hydration
     *
     * @example
     * ```ts
     * const state = permix.dehydrate()
     * permix.hydrate(state)
     * ```
     */
    hydrate: (state: PermixStateJSON<Definition>) => void;
}
/**
 * Create a Permix instance
 *
 * @link https://permix.letstri.dev/docs/guide/instance
 *
 * @example
 * ```ts
 * const permix = createPermix<{
 *   post: {
 *     dataType: { id: string }
 *     action: 'create' | 'read'
 *   },
 *   user: {
 *     dataType: { id: string }
 *     action: 'create' | 'read'
 *   }
 * }>()
 *
 * permix.setup({
 *   post: { create: false },
 *   user: { read: true }
 * })
 *
 * console.log(permix.check('post', 'create')) // false
 * console.log(permix.check('user', 'read')) // true
 * ```
 */
declare function createPermix<Definition extends PermixDefinition>(initial?: PermixRules<Definition>): Permix<Definition>;
declare function getRules<Definition extends PermixDefinition>(permix: Permix<Definition>): PermixRules<Definition>;

export { checkWithRules as c, createPermix as d, getRules as g };
export type { CheckContext as C, PermixDefinition as P, Permix as a, PermixStateJSON as b, PermixRules as e, CheckFunctionObject as f, CheckFunctionParams as h };
