Guia do Desenvolvedor - CAKeysama/ReTool GitHub Wiki
Guia do Desenvolvedor
Como estender o ReTool seguindo o padrão já existente. A visão geral das camadas está em Arquitetura.
Convenções
- Idioma: nomes do domínio, mensagens e comentários em português (
Dispositivo,solicitarAlteracaoCargo,ErroPermissao). - Estilo: estilos inline com as variáveis CSS de
src/index.css(var(--color-primary),var(--spacing-md),var(--radius)) e as classes.btn,.btn-primary,.btn-icon,.input-field,.input-label,.card. Não há framework de CSS. - Componentes de apoio:
Feedback.tsx:Aviso,EstadoCarregando,EstadoErro;Badges.tsx:Pill,RoleBadge,SituacaoBadge;Tabs.tsx:TabseEmptyState;AccessibleModal.tsx: modal acessível;BulkActionModal.tsx: ações em massa.
- Commits: no estilo Conventional Commits, em português (
feat(escopo): ...,fix(...),refactor(...),style(...),docs(...)). - Branches:
main(estável),deve branches de funcionalidade (feat/...).
Onde colocar cada coisa
| Quero… | Onde | Observações |
|---|---|---|
| Nova tela | src/pages/ e uma rota em src/App.tsx |
Dentro de ProtectedLayout; restrinja com RoleRoute se preciso. Adicione o link em src/components/Layout.tsx (barra lateral e navegação inferior) |
| Novo componente | src/components/ (components/admin/ se for só da Administração) |
Reaproveite Feedback, Badges e Tabs |
| Lógica de tela com estado | src/presentation/hooks/use*Controller.ts |
Ex.: useDispositivosController, useHistoricoAuditoriaController |
| Nova entidade ou regra pura | src/domain/entities/ |
Sem dependência do Firebase; é onde os testes são mais baratos |
| Acesso ao Firestore | src/data/repositories/Firestore*Repository.ts, com o contrato em src/domain/repositories/ |
|
| Serviço externo (Storage, Functions) | src/data/services/ |
|
| Fluxo com várias etapas (gravar + notificar + auditar) | src/application/usecases/ |
Receba os repositórios pelo construtor (ver os casos de uso de acesso) |
| Expor a operação para as telas | AuthContext (contas e acesso) ou ReToolContext (dados industriais) |
Cheque a permissão na função do contexto |
| Operação que exige Admin SDK | retool/functions/src/index.ts |
Veja abaixo |
Nova operação de dados
- Método no repositório.
- Função no contexto, que:
- confere a permissão (ex.:
if (!canEditar) { announce('Acesso negado...'); return; }); - chama o repositório;
- chama
registrarAuditoria(...)após o sucesso.
- confere a permissão (ex.:
- Regra correspondente em
firestore.rules. Sem ela, a operação é negada no servidor. - Testes: domínio e repositório com
firebaseMock; regras emsrc/tests/rules/firestore.rules.test.ts.
Permissões
Para uma nova permissão de cargo:
- adicione o campo em
RoleConfige preenchaROLES_CONFIGeCONVIDADO_CONFIG(semprefalse), emsrc/domain/entities/user.ts; - exponha o campo no
AuthContext(can...) e emusePermissions(); - aplique a mesma regra em
firestore.rules(e emstorage.rules, se envolver arquivos); - atualize a matriz em
src/tests/domain/entities/user.test.tse a tabela em Usuários, Cargos e Permissões.
Um novo cargo exige ainda:
- ajustar
UserRoleeperfisOperacionais()nas regras (Firestore e Storage); - ajustar
PERFIS_OPERACIONAISna Cloud Function; - ajustar
TRANSICOES_REUTILIZACAO.
Auditoria
Para um novo tipo de evento:
- Em
src/domain/entities/auditLog.ts:- adicione o token em
AuditLogAcao; - adicione o rótulo em
ROTULO_ACAO; - coloque o token em uma categoria de
ACOES_POR_CATEGORIA. O testeauditLog.test.tsfalha se uma ação ficar sem categoria ou em duas.
- adicione o token em
- Registre com
registrarAuditoria(...)(ReToolContext),registrarAuditoriaSemFalhar(...)(casos de uso) ouauditRepo.registrarLog(...). - Preencha
acao,acaoDescricao,tipoEntidade,entidadeIde, se útil,conteudo/dadosAnteriores. Useresultado: 'negado'ou'falha'quando for o caso. - Nunca coloque senha, token ou hash nos dados. A sanitização remove esses campos, mas não conte com ela.
- Para um novo recurso, atualize
AuditLogTipoEntidadeeROTULO_TIPO_ENTIDADE.
Para um novo filtro no Histórico de Ações:
- adicione o campo em
FiltrosAuditoriae emfiltrosDeIgualdade(), e o nome do campo emCAMPOS_FILTRO_AUDITORIA(a ordem define a ordem nos índices), emFirestoreAuditLogRepository.ts; - prefira igualdade (
==). Evite novosin, que multiplicam as sub-consultas; - rode
npm test: oFirestoreAuditLogRepository.indices.test.tsmostra a lista de índices esperada. Atualizefirestore.indexes.jsonaté o teste passar; - adicione o controle em
HistoricoAcoesPanel.tsxe a combinação emhistoricoAuditoria.consultas.test.ts; - publique os índices (ver Build e Deploy).
Notificações
- Adicione o tipo em
NotificacaoTipo(src/domain/entities/notificacao.ts). - Crie a notificação no caso de uso ou no contexto com
id: idNotificacao(tipo, entidadeId, destinatarioUid). Envolva emtry/catch: falhar ao notificar não deve derrubar a operação. Para avisar a Administração, usenotificarAdministradores(...). - Adicione o ramo do tipo no
allow createdematch /notifications/{notifId}, emfirestore.rules, validando remetente e destinatário. - Em
src/components/NotificationsMenu.tsx, defina o selo de status (statusDaNotificacao), a ação ao clicar (abrir) e, se exigir decisão, a regra de "aguardando ação" (exigeAcao). - Cubra o novo tipo em
firestore.rules.test.ts.
Consultas ao Firestore e índices
- Consultas só com igualdade, ou só com ordenação e intervalo em um campo, usam índices automáticos.
- Igualdade combinada com
orderByou intervalo em outro campo exige índice composto. Declare-o emfirestore.indexes.jsone publique. - O emulador não acusa índice ausente; só a nuvem acusa. Cubra combinações novas com um teste como o de índices do histórico.
- Evite combinar vários
in: o Firestore multiplica as expansões e tem limite de filtros por consulta. - Assinaturas em tempo real (
onSnapshot) devem ser abertas só para contas operacionais. Veja como oReToolContextusaisOperacional.
Cloud Functions
- Crie a função em
retool/functions/src/index.tscomonCall. A região vem desetGlobalOptions. - Refaça a autorização no servidor lendo
users/{request.auth.uid}. O Admin SDK ignora as regras. - Registre a auditoria com o Admin SDK, seguindo os mesmos campos (
categoria,resultado,dataHoraServidor). - No cliente, crie o método em
src/data/services/(httpsCallable(functions, 'nome')) e exponha pelo contexto. - Teste nos emuladores em
src/tests/funcoes/(npm run test:funcoes). - O deploy exige o plano Blaze.
Testes e build
Antes de abrir um PR:
npm test
npm run test:rules
npm run test:funcoes
npx tsc --noEmit -p .
npm run build
Os dois comandos de emulador pedem Java; os detalhes estão em Testes.
Scripts auxiliares
| Script | Para quê | Como usar |
|---|---|---|
scripts/emuladores.mjs |
Sobe os emuladores (npm run emuladores) e roda os testes que dependem deles |
Pelos scripts npm |
scripts/semearEmulador.mjs |
Cria contas de demonstração nos emuladores | node scripts/semearEmulador.mjs, com os emuladores no ar |
scripts/criarFormularioBugReTool.js |
Cria o formulário de reporte de bugs no Google Forms | Cole no Google Apps Script e execute criarFormularioBugReTool; os links saem no console |
scripts/criarIssuesGitHub.js |
Cria labels e as issues do backlog inicial, com milestones, no GitHub | node scripts/criarIssuesGitHub.js, com o gh autenticado (gh auth login) |
O botão "Encontrou algum bug?" da Home abre o formulário já publicado.