{"version":3,"sources":["../src/PermissionContext.tsx","../src/hooks/usePermission.tsx","../src/hooks/useAuthorized.tsx","../src/components/AllowedAccess.tsx","../src/core/access.ts","../src/PermissionProvider.tsx"],"names":["useMemo","React"],"mappings":"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","file":"index.mjs","sourcesContent":["import { createContext } from \"react\";\nimport type { AccessQuery } from \"./core/access\";\n\nexport interface IUserPayload<\n    Role extends string = string,\n    Permission extends string = string\n> {\n    id: string | number;\n    roles?: Role[];\n    permissions?: Permission[];\n}\n\nexport interface PermissionAuthContext {\n    /** The currently set user, or `null` when no user is set. */\n    user: IUserPayload | null;\n    /** Sets (or replaces) the current user. */\n    setUser: (user: IUserPayload) => void;\n    /** Clears the current user (e.g. on logout). */\n    clearUser: () => void;\n    /** Synchronous authorization check. */\n    can: (query: AccessQuery) => boolean;\n    /**\n     * Promise-based authorization check. Kept for backwards compatibility;\n     * resolves synchronously since checks are performed in memory.\n     */\n    isAuthorized: (\n        roleNames?: string[] | string,\n        permissionNames?: string[] | string,\n        options?: Pick<AccessQuery, \"requireAll\" | \"check\">\n    ) => Promise<boolean>;\n    /** Retained for backwards compatibility; always `false` (checks are instant). */\n    isLoading: boolean;\n}\n\nconst notInitialized = (): never => {\n    throw new Error(\n        \"PermissionProvider is missing. Wrap your application with <PermissionProvider> before using permission features.\"\n    );\n};\n\nconst PermissionContext = createContext<PermissionAuthContext>({\n    user: null,\n    setUser: notInitialized,\n    clearUser: notInitialized,\n    can: notInitialized,\n    isAuthorized: notInitialized,\n    isLoading: false,\n});\n\nexport default PermissionContext;","import { useContext } from \"react\";\nimport PermissionContext from \"../PermissionContext\";\n\nconst usePermission = () => useContext(PermissionContext);\n\nexport default usePermission;","import { useMemo } from \"react\";\n\nimport usePermission from \"./usePermission\";\nimport type { AccessQuery } from \"../core/access\";\n\n/**\n * Synchronously resolves whether the current user satisfies an access query.\n * Recomputes automatically when the user or the query changes.\n *\n * @example\n * const canEdit = useAuthorized({ permissions: \"post:edit\" });\n */\nconst useAuthorized = <\n    Role extends string = string,\n    Permission extends string = string\n>(\n    query: AccessQuery<Role, Permission>\n): boolean => {\n    const { can } = usePermission();\n    const { roles, permissions, requireAll, check } = query;\n    const rolesKey = JSON.stringify(roles ?? null);\n    const permissionsKey = JSON.stringify(permissions ?? null);\n\n    return useMemo(\n        () => can({ roles, permissions, requireAll, check }),\n        // `can` identity changes whenever the current user changes.\n        // eslint-disable-next-line react-hooks/exhaustive-deps\n        [can, rolesKey, permissionsKey, requireAll, check]\n    );\n};\n\nexport default useAuthorized;\n","import * as React from \"react\";\n\nimport useAuthorized from \"../hooks/useAuthorized\";\nimport type { IUserPayload } from \"../PermissionContext\";\n\nexport interface HasAccessProps<\n  Role extends string = string,\n  Permission extends string = string\n> {\n  roles?: Role[] | Role;\n  permissions?: Permission[] | Permission;\n  /** Require every listed role AND permission instead of ANY. */\n  requireAll?: boolean;\n  /** Custom predicate for rules roles/permissions can't express. */\n  check?: (user: IUserPayload) => boolean;\n  /** Rendered when the user is NOT authorized. */\n  renderAuthFailed?: React.ReactNode;\n  /**\n   * @deprecated Checks are now synchronous, so there is no loading phase.\n   * Kept for backwards compatibility; it is ignored.\n   */\n  isLoading?: React.ReactNode;\n  /**\n   * Content shown when authorized. May also be a render-prop function that\n   * receives the boolean result, letting you render both states inline.\n   */\n  children?: React.ReactNode | ((isAllowed: boolean) => React.ReactNode);\n}\n\nconst AllowedAccess = <\n  Role extends string = string,\n  Permission extends string = string\n>({\n  roles,\n  permissions,\n  requireAll,\n  check,\n  renderAuthFailed = null,\n  children,\n}: HasAccessProps<Role, Permission>): React.ReactElement | null => {\n  const isAllowed = useAuthorized<Role, Permission>({\n    roles,\n    permissions,\n    requireAll,\n    check,\n  });\n\n  if (typeof children === \"function\") {\n    return <>{children(isAllowed)}</>;\n  }\n\n  if (isAllowed) {\n    return <>{children}</>;\n  }\n\n  return <>{renderAuthFailed}</>;\n};\n\nexport default AllowedAccess;\n","import type { IUserPayload } from \"../PermissionContext\";\n\n/**\n * A single access requirement that can be evaluated against a user.\n *\n * Matching semantics:\n * - By default (`requireAll` omitted / false) access is granted when the user\n *   matches ANY of the provided roles OR ANY of the provided permissions OR the\n *   custom `check` predicate returns `true` (logical OR across every supplied\n *   criterion).\n * - When `requireAll` is `true`, every supplied criterion must pass: the user\n *   must have ALL listed roles AND ALL listed permissions AND satisfy `check`.\n *\n * Roles and permissions support `*` wildcards (e.g. a granted `user:*` matches a\n * required `user:read`, and a granted `*` matches everything).\n */\nexport interface AccessQuery<\n    Role extends string = string,\n    Permission extends string = string\n> {\n    roles?: Role[] | Role;\n    permissions?: Permission[] | Permission;\n    /** Require every listed role AND permission (AND semantics) instead of ANY. */\n    requireAll?: boolean;\n    /** Custom predicate for rules that roles/permissions can't express. */\n    check?: (user: IUserPayload) => boolean;\n}\n\n/** Normalizes a value that may be a single item, an array, or undefined. */\nexport const toArray = <T>(value?: T[] | T): T[] => {\n    if (value === undefined || value === null) {\n        return [];\n    }\n    return Array.isArray(value) ? value : [value];\n};\n\n/**\n * Returns `true` when a granted role/permission pattern matches a required one.\n * Supports `*` wildcards on the granted side, matching per `:`-delimited segment.\n *\n *   matchesPattern(\"*\", \"anything\")          -> true\n *   matchesPattern(\"user:read\", \"user:read\") -> true\n *   matchesPattern(\"user:*\", \"user:read\")    -> true\n *   matchesPattern(\"user:read\", \"user:*\")    -> false (wildcards only granted-side)\n */\nexport const matchesPattern = (granted: string, required: string): boolean => {\n    if (granted === required || granted === \"*\") {\n        return true;\n    }\n    if (granted.indexOf(\"*\") === -1) {\n        return false;\n    }\n\n    const grantedSegments = granted.split(\":\");\n    const requiredSegments = required.split(\":\");\n\n    for (let i = 0; i < grantedSegments.length; i++) {\n        if (grantedSegments[i] === \"*\") {\n            return true;\n        }\n        if (grantedSegments[i] !== requiredSegments[i]) {\n            return false;\n        }\n    }\n\n    return grantedSegments.length === requiredSegments.length;\n};\n\n/** Whether any granted entry matches the required entry (wildcard-aware). */\nconst grantedMatches = (granted: string[], required: string): boolean =>\n    granted.some((entry) => matchesPattern(entry, required));\n\n/**\n * Pure, synchronous authorization check. This is the single source of truth used\n * by the provider, the `can` helper, the `useAuthorized` hook and `AllowedAccess`.\n */\nexport const isUserAuthorized = (\n    user: IUserPayload | null | undefined,\n    query: AccessQuery\n): boolean => {\n    if (!user) {\n        return false;\n    }\n\n    const { requireAll = false, check } = query;\n    const roles = toArray(query.roles);\n    const permissions = toArray(query.permissions);\n\n    const userRoles = user.roles ?? [];\n    const userPermissions = user.permissions ?? [];\n\n    const results: boolean[] = [];\n\n    if (roles.length > 0) {\n        results.push(\n            requireAll\n                ? roles.every((role) => grantedMatches(userRoles, role))\n                : roles.some((role) => grantedMatches(userRoles, role))\n        );\n    }\n\n    if (permissions.length > 0) {\n        results.push(\n            requireAll\n                ? permissions.every((permission) =>\n                      grantedMatches(userPermissions, permission)\n                  )\n                : permissions.some((permission) =>\n                      grantedMatches(userPermissions, permission)\n                  )\n        );\n    }\n\n    if (typeof check === \"function\") {\n        results.push(check(user));\n    }\n\n    if (results.length === 0) {\n        return false;\n    }\n\n    return requireAll ? results.every(Boolean) : results.some(Boolean);\n};\n","import React, {\n    PropsWithChildren,\n    useCallback,\n    useMemo,\n    useState,\n} from \"react\";\n\n//context\nimport PermissionContext, { IUserPayload } from \"./PermissionContext\";\nimport { AccessQuery, isUserAuthorized } from \"./core/access\";\n\nconst PermissionProvider = ({ children }: PropsWithChildren) => {\n    const [user, setUserState] = useState<IUserPayload | null>(null);\n\n    const setUser = useCallback((newUser: IUserPayload) => {\n        setUserState(newUser);\n    }, []);\n\n    const clearUser = useCallback(() => {\n        setUserState(null);\n    }, []);\n\n    const can = useCallback(\n        (query: AccessQuery): boolean => isUserAuthorized(user, query),\n        [user]\n    );\n\n    const isAuthorized = useCallback(\n        (\n            roleNames?: string[] | string,\n            permissionNames?: string[] | string,\n            options?: Pick<AccessQuery, \"requireAll\" | \"check\">\n        ): Promise<boolean> =>\n            Promise.resolve(\n                isUserAuthorized(user, {\n                    roles: roleNames,\n                    permissions: permissionNames,\n                    ...options,\n                })\n            ),\n        [user]\n    );\n\n    const value = useMemo(\n        () => ({\n            user,\n            setUser,\n            clearUser,\n            can,\n            isAuthorized,\n            isLoading: false,\n        }),\n        [user, setUser, clearUser, can, isAuthorized]\n    );\n\n    return (\n        <PermissionContext.Provider value={value}>\n            {children}\n        </PermissionContext.Provider>\n    );\n};\n\nexport default PermissionProvider;"]}