1.0.0 • Published 1 month ago
@shield-acl/react v1.0.0
@shield-acl/react
Características
- 🎨 Componentes Declarativos: Can, Cannot, CanAny, CanAll para renderização condicional
- 🪝 Hooks Modernos: useCan, usePermissions, useACL e muitos outros
- ⚡ Performance Otimizada: Memoização inteligente e re-renders mínimos
- 🎯 TypeScript First: Totalmente tipado com IntelliSense completo
- 🔄 React 19 Ready: Compatível com React 16.8+ até React 19
- 🧩 Extensível: Sistema de componentes e hooks customizáveis
Instalação
npm install @shield-acl/react @shield-acl/core
# ou
yarn add @shield-acl/react @shield-acl/core
# ou
pnpm add @shield-acl/react @shield-acl/core
Uso Rápido
1. Setup do Provider
import { ACL } from '@shield-acl/core'
import { ACLProvider } from '@shield-acl/react'
// Criar instância do ACL
const acl = new ACL()
// Definir roles
acl.defineRole({
name: 'admin',
permissions: [{ action: '*', resource: '*' }]
})
acl.defineRole({
name: 'user',
permissions: [
{ action: 'read', resource: 'posts' },
{ action: 'create', resource: 'posts' }
]
})
// Wrap sua aplicação
function App() {
const [user] = useState({
id: 1,
roles: ['user']
})
return (
<ACLProvider acl={acl} user={user}>
<YourApp />
</ACLProvider>
)
}
2. Componentes de Renderização Condicional
import { Can, Cannot, CanAny, CanAll } from '@shield-acl/react'
function PostList() {
return (
<div>
{/* Renderiza apenas se pode ler posts */}
<Can action="read" resource="posts">
<PostGrid />
</Can>
{/* Renderiza se NÃO pode deletar */}
<Cannot action="delete" resource="posts">
<p>Você não tem permissão para deletar posts</p>
</Cannot>
{/* Renderiza se tem QUALQUER uma das permissões */}
<CanAny permissions={[
{ action: 'create', resource: 'posts' },
{ action: 'edit', resource: 'posts' }
]}>
<EditButton />
</CanAny>
{/* Renderiza se tem TODAS as permissões */}
<CanAll permissions={[
{ action: 'read', resource: 'users' },
{ action: 'manage', resource: 'roles' }
]}>
<AdminPanel />
</CanAll>
</div>
)
}
3. Hooks
import { useCan, usePermissions, useACL } from '@shield-acl/react'
function PostEditor({ post }) {
// Hook básico
const canEdit = useCan('edit', 'posts', {
resource: { authorId: post.authorId }
})
// Múltiplas permissões
const permissions = usePermissions()
const canModerate = permissions.some(p =>
p.action === 'moderate' && p.resource === 'posts'
)
// Acesso direto ao ACL
const { engine, user } = useACL()
if (!canEdit) {
return <p>Sem permissão para editar</p>
}
return <Editor post={post} />
}
API Completa
Componentes
<Can>
Renderiza children apenas se o usuário tem a permissão.
<Can
action="edit"
resource="posts"
context={{ authorId: userId }}
fallback={<NoPermission />}
>
<EditForm />
</Can>
<Cannot>
Renderiza children apenas se o usuário NÃO tem a permissão.
<Cannot action="delete" resource="posts">
<p>Você não pode deletar posts</p>
</Cannot>
<CanAny>
Renderiza se o usuário tem QUALQUER uma das permissões.
<CanAny permissions={[
{ action: 'create', resource: 'posts' },
{ action: 'edit', resource: 'posts' }
]}>
<ActionButton />
</CanAny>
<CanAll>
Renderiza se o usuário tem TODAS as permissões.
<CanAll permissions={[
{ action: 'read', resource: 'analytics' },
{ action: 'export', resource: 'reports' }
]}>
<ExportButton />
</CanAll>
Hooks Principais
useCan(action, resource?, context?)
Verifica uma permissão específica.
const canDelete = useCan('delete', 'posts')
const canEdit = useCan('edit', 'posts', { resource: post })
usePermissions()
Retorna todas as permissões do usuário atual.
const permissions = usePermissions()
const isAdmin = permissions.some(p => p.action === '*')
useACL()
Acesso direto ao engine ACL e usuário.
const { engine, user, setUser } = useACL()
useEvaluate(action, resource?, context?)
Retorna resultado detalhado da avaliação.
const result = useEvaluate('publish', 'posts')
// { allowed: true, reason: 'Matched role permission', matchedRule: {...} }
Hooks Avançados
useCanMultiple(permissions)
Verifica múltiplas permissões de uma vez.
const results = useCanMultiple([
{ action: 'read', resource: 'posts' },
{ action: 'create', resource: 'comments' }
])
// { 'read:posts': true, 'create:comments': false }
useCanAny(permissions)
Verifica se tem QUALQUER uma das permissões.
const canEditContent = useCanAny([
{ action: 'edit', resource: 'posts' },
{ action: 'edit', resource: 'pages' }
])
useCanAll(permissions)
Verifica se tem TODAS as permissões.
const isFullAdmin = useCanAll([
{ action: 'manage', resource: 'users' },
{ action: 'manage', resource: 'roles' }
])
useRoleHierarchy()
Obtém a hierarquia completa de roles do usuário.
const hierarchy = useRoleHierarchy()
// ['user', 'moderator', 'admin']
usePermissionChange(callback, dependencies)
Monitora mudanças nas permissões.
usePermissionChange(() => {
console.log('Permissões mudaram!')
}, ['posts'])
Componentes Utilitários
HOC withCan
const ProtectedButton = withCan(Button, {
action: 'delete',
resource: 'posts',
fallback: <DisabledButton />
})
PermissionClass
<PermissionClass
action="publish"
resource="posts"
className="can-publish"
deniedClassName="cannot-publish"
>
<article className="post">...</article>
</PermissionClass>
Performance
Memoização Automática
Todos os hooks são otimizados com memoização:
// Só re-renderiza se o resultado mudar
const canEdit = useCan('edit', 'posts')
// Context é memoizado profundamente
const canDelete = useCan('delete', 'posts', {
resource: { id: post.id, authorId: post.authorId }
})
Batch Updates
Mudanças no usuário ou permissões são batched:
// Uma única re-renderização
setUser({
...user,
roles: ['admin'],
permissions: [...]
})
Testes
# Rodar testes
pnpm test
# Coverage
pnpm test:coverage
# Watch mode
pnpm test:watch
Documentação Adicional
- Documentação Completa dos Hooks - Guia detalhado de todos os hooks disponíveis
- Roadmap de Implementação - Status de desenvolvimento dos hooks
Compatibilidade
- React 16.8+ (precisa de hooks)
- React 17.x
- React 18.x
- React 19.x (totalmente compatível)
- TypeScript 4.5+
Licença
MIT © Anderson D. Rosa
1.0.0
1 month ago