UNPKG

permix

Version:

Permix is a lightweight, framework-agnostic, type-safe permissions management library for JavaScript applications on the client and server sides.

76 lines (74 loc) • 2.27 kB
'use client'; import { createCheck } from "../core/index.mjs"; import * as React from "react"; import { jsx } from "react/jsx-runtime"; //#region src/react/hooks.ts const Context = React.createContext(null); function usePermixContext() { const context = React.useContext(Context); if (!context) throw new Error("[Permix]: Looks like you forgot to wrap your app with <PermixProvider>"); return context; } /** * Access Permix check and readiness state inside a React component. * * @link https://permix.letstri.dev/docs/integrations/react */ function usePermix(permix) { const { permix: instance, isReady } = usePermixContext(); const subscribe = React.useCallback((onChange) => instance.hook("setup", () => { queueMicrotask(onChange); }), [instance]); const getRules = React.useCallback(() => instance.getRules() ?? permix.getRules(), [instance, permix]); const rules = React.useSyncExternalStore(subscribe, getRules, getRules); return { check: React.useMemo(() => createCheck(getRules), [getRules, rules]), isReady }; } //#endregion //#region src/react/components.tsx /** * Provides Permix context to the React component tree. * * @link https://permix.letstri.dev/docs/integrations/react */ function PermixProvider({ children, permix }) { const [context, setContext] = React.useState(() => ({ permix, isReady: permix.isReady() })); React.useEffect(() => { const syncReady = () => { queueMicrotask(() => { setContext((c) => ({ ...c, isReady: permix.isReady() })); }); }; return permix.hook("ready", syncReady); }, [permix]); return /* @__PURE__ */ jsx(Context.Provider, { value: context, children }); } function PermixHydrate({ children, state }) { const { permix } = usePermixContext(); React.useMemo(() => { permix.hydrate(state); }, [permix, state]); return children; } function createComponents(permix) { function Check({ children, path, data, otherwise = null, reverse = false }) { const { check } = usePermix(permix); const hasPermission = check(...[path, data]); return reverse ? hasPermission ? otherwise : children : hasPermission ? children : otherwise; } Check.displayName = "Check"; return { Check }; } //#endregion export { PermixHydrate, PermixProvider, createComponents, usePermix };