npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@anpdgovbr/rbac-react

v0.3.0

Published

Hooks e HOC React para RBAC no cliente (UX).

Readme

@anpdgovbr/rbac-react

npm version TypeScript React License: MIT

Hooks e HOCs React para RBAC — Integração client-side do sistema de autorização ANPD.

✨ Características

  • ⚛️ React 18+ — Hooks modernos e Server Components friendly
  • 🔄 SWR Integration — Cache inteligente com revalidação automática
  • 🎭 HOC Pattern — Proteção declarativa de componentes
  • 🎯 Type Safety — Totalmente tipado com TypeScript
  • 🚀 Performance — Otimizado para re-renders mínimos

📦 Instalação

npm install @anpdgovbr/rbac-react@beta

Peer Dependencies:

npm install react@^18 swr@^2

🎯 Uso Básico

1. Provider de Contexto

Configure o provider no nível raiz da aplicação:

import { PermissionsProvider } from "@anpdgovbr/rbac-react"

function App() {
  // Permissões podem vir do SSR, API, ou outros sources
  const permissionsMap = useServerPermissions() // seu hook customizado

  return (
    <PermissionsProvider value={permissionsMap}>
      <Dashboard />
    </PermissionsProvider>
  )
}

2. Hook de Permissões

import { usePermissions } from "@anpdgovbr/rbac-react"

function Dashboard() {
  const { permissoes, loading, error } = usePermissions({
    endpoint: "/api/permissoes", // opcional
    initial: preloadedPermissions, // opcional
  })

  if (loading) return <Loading />
  if (error) return <Error />

  return <div>Dashboard com permissões: {JSON.stringify(permissoes)}</div>
}

3. Hook de Verificação

import { usePode } from "@anpdgovbr/rbac-react"

function ReportsPanel() {
  const { pode, loading } = usePode()

  if (loading) return <Skeleton />

  return (
    <div>
      {pode("Exibir", "Relatorios") && <ReportsViewer />}
      {pode("Criar", "Relatorios") && <CreateReportButton />}
      {pode("Editar", "Relatorios") && <EditReportsPanel />}
    </div>
  )
}

4. HOC de Proteção

import { withPermissao } from "@anpdgovbr/rbac-react"

// Componente original
function AdminPanel() {
  return (
    <div>
      <h1>Painel Administrativo</h1>
      <UserManagement />
      <SystemSettings />
    </div>
  )
}

// Versão protegida
export default withPermissao(
  AdminPanel,
  "Acessar",
  "PainelAdmin",
  { redirect: true } // ou false para mostrar "Acesso negado"
)

🔧 API Completa

PermissionsProvider

Provider de contexto para injetar permissões pré-resolvidas.

interface PermissionsProviderProps {
  children: React.ReactNode
  value: PermissionsMap
}

Uso típico com SSR:

// pages/_app.tsx ou app/layout.tsx
export default function RootLayout({
  children,
  permissions,
}: {
  children: React.ReactNode
  permissions: PermissionsMap
}) {
  return <PermissionsProvider value={permissions}>{children}</PermissionsProvider>
}

usePermissions(options?)

Hook para obter permissões via contexto ou endpoint.

interface PermissionsClientOptions {
  endpoint?: string // padrão: "/api/permissoes"
  fetcher?: (url: string) => Promise<unknown>
  initial?: PermissionsMap
}

interface UsePermissionsReturn {
  permissoes: PermissionsMap
  loading: boolean
  error?: Error
}

Estratégias de carregamento:

  1. Contexto — Se PermissionsProvider estiver presente, usa o valor do contexto
  2. Initial — Se initial for fornecido, usa como fallback
  3. Endpoint — Faz fetch via SWR se contexto não estiver disponível

usePode()

Hook para verificação reativa de permissões.

interface UsePodeReturn {
  pode: (acao: Action, recurso: Resource) => boolean
  loading: boolean
}

Exemplo avançado:

function ConditionalUI() {
  const { pode, loading } = usePode()

  const actions = useMemo(
    () => [
      { key: "view", show: pode("Exibir", "Docs"), label: "Ver Documentos" },
      { key: "edit", show: pode("Editar", "Docs"), label: "Editar Documentos" },
      { key: "delete", show: pode("Excluir", "Docs"), label: "Excluir Documentos" },
    ],
    [pode]
  )

  if (loading) return <ActionsLoading />

  return (
    <ActionsList>
      {actions
        .filter((action) => action.show)
        .map((action) => (
          <ActionButton key={action.key}>{action.label}</ActionButton>
        ))}
    </ActionsList>
  )
}

withPermissao(Component, acao, recurso, options?)

HOC para proteção declarativa de componentes.

interface WithPermissaoOptions {
  redirect?: boolean // padrão: true
}

function withPermissao<TProps extends object>(
  Component: React.ComponentType<TProps>,
  acao: Action,
  recurso: Resource,
  options?: WithPermissaoOptions
): React.FC<TProps>

Comportamentos:

  • redirect: true — Retorna null (não renderiza nada)
  • redirect: false — Mostra mensagem "Acesso negado"
  • Durante loading — Retorna null

Nota importante sobre uso em páginas (Next App Router):

withPermissao é um HOC client-side pensado para proteger componentes e melhorar a UX. Ele não executa checagem server-side nem faz redirects no servidor. Se usado diretamente como export default de uma page.tsx (client component), pode ocorrer mismatch/hydration quando o servidor renderiza conteúdo diferente do cliente.

Recomendação: para proteger páginas inteiras utilize o helper server-side checkPermission do pacote @anpdgovbr/rbac-next (veja o README do rbac-next). O padrão é chamar checkPermission em um Server Component e, em caso de sucesso, renderizar um componente cliente protegido (carregado dinamicamente).


ℹ️ Desenvolvimento local com submódulos

Durante o desenvolvimento local com submódulos, este pacote pode depender de versões locais dos outros pacotes rbac-* (veja __local_dev_note__ em package.json). Há também TODO: (TEMP) em alguns arquivos para facilitar testes com mocks. Antes de publicar, reverta file: para as dependências publicadas e remova os fallbacks temporários.

🧪 Padrões de Uso

Proteção Multi-nível

// Layout protegido
const AdminLayout = withPermissao(BaseLayout, "Acessar", "AreaAdmin")

// Seções específicas
const UserManagement = withPermissao(UsersList, "Gerenciar", "Usuarios")

const SystemSettings = withPermissao(SettingsPanel, "Configurar", "Sistema")

Composição com Outros Hooks

function useAdminPermissions() {
  const { pode } = usePode()

  return useMemo(
    () => ({
      canManageUsers: pode("Gerenciar", "Usuarios"),
      canViewReports: pode("Exibir", "Relatorios"),
      canConfigureSystem: pode("Configurar", "Sistema"),
    }),
    [pode]
  )
}

Loading States Customizados

function ProtectedComponent() {
  const { permissoes, loading } = usePermissions()

  if (loading) {
    return <CustomSkeleton />
  }

  // Resto do componente...
}

🔧 Desenvolvimento

# Build
npm run build

# Type checking
npm run typecheck

# Testes
npm test

📚 Documentação Relacionada

📄 Licença

MIT © 2024 ANPD (Agência Nacional de Proteção de Dados)