UNPKG

preact-missing-hooks

Version:

A lightweight, extendable collection of missing React-like hooks for Preact — plus fresh, powerful new ones designed specifically for modern Preact apps.

103 lines (102 loc) 4.22 kB
/** Flexible user object; your app can use any shape. */ export type RBACUser = Record<string, unknown>; /** Get auth state (user + optional roles/capabilities). Used by custom source. */ export interface RBACAuthState { user?: RBACUser | null; roles?: string[]; capabilities?: string[]; } /** Pluggable source for current user (and optionally roles/capabilities). */ export type RBACUserSource = { type: "localStorage"; key: string; } | { type: "sessionStorage"; key: string; } | { type: "api"; fetch: () => Promise<RBACUser>; } | { type: "memory"; getUser: () => RBACUser | null; } | { type: "custom"; getAuth: () => RBACAuthState | Promise<RBACAuthState>; }; /** Role definition: name + condition to grant this role based on user. */ export interface RBACRoleDefinition { role: string; condition: (user: RBACUser | null) => boolean; } /** Role name -> list of capability strings. Use '*' for full access. */ export type RBACRoleCapabilities = Record<string, string[]>; /** Optional override: get capabilities directly (e.g. from API) instead of deriving from roles. */ export type RBACCapabilitiesOverride = { type: "localStorage"; key: string; } | { type: "sessionStorage"; key: string; } | { type: "api"; fetch: () => Promise<string[]>; }; export interface UseRBACOptions { /** Where to get the current user (and optionally roles/capabilities if type is 'custom'). */ userSource: RBACUserSource; /** Role definitions: each role has a condition(user) to determine if the user has that role. */ roleDefinitions: RBACRoleDefinition[]; /** Capabilities per role. User gets union of capabilities for all their roles. Use '*' for admin. */ roleCapabilities: RBACRoleCapabilities; /** Optional: fetch capabilities directly (overrides role-derived capabilities when provided). */ capabilitiesOverride?: RBACCapabilitiesOverride; } export interface UseRBACReturn { /** Current user from source, or null. */ user: RBACUser | null; /** Resolved roles for the current user. */ roles: string[]; /** Resolved capabilities (union of role capabilities, or from override). */ capabilities: string[]; /** True when user/roles/capabilities have been resolved (or failed). */ isReady: boolean; /** Error from source (e.g. API or parse). */ error: Error | null; /** Check if the user has the given role. */ hasRole: (role: string) => boolean; /** Check if the user has the given capability (or '*' ). */ hasCapability: (capability: string) => boolean; /** Alias for hasCapability. */ can: (capability: string) => boolean; /** Re-fetch user/roles/capabilities from source. */ refetch: () => Promise<void>; /** Helpers to persist auth to storage (for frontend-only flows). */ setUserInStorage: (user: RBACUser | null, storage: "localStorage" | "sessionStorage", key: string) => void; setRolesInStorage: (roles: string[], storage: "localStorage" | "sessionStorage", key: string) => void; setCapabilitiesInStorage: (capabilities: string[], storage: "localStorage" | "sessionStorage", key: string) => void; } /** * Frontend-only role-based access control hook. Define roles with conditions, * assign capabilities per role, and plug in user source (localStorage, sessionStorage, API, or custom). * Supports full flexibility: frontend-only with storage or pluggable API. * * @param options - userSource, roleDefinitions, roleCapabilities, optional capabilitiesOverride * @returns user, roles, capabilities, hasRole, hasCapability, can, isReady, error, refetch, and storage helpers * * @example * ```tsx * const { hasRole, can, roles, setUserInStorage } = useRBAC({ * userSource: { type: 'localStorage', key: 'user' }, * roleDefinitions: [ * { role: 'admin', condition: (u) => u?.role === 'admin' }, * { role: 'editor', condition: (u) => u?.role === 'editor' || u?.role === 'admin' }, * ], * roleCapabilities: { * admin: ['*'], * editor: ['posts:edit', 'posts:create'], * }, * }); * if (can('posts:edit')) { ... } * ``` */ export declare function useRBAC(options: UseRBACOptions): UseRBACReturn;