Estender a Aplicação
Adicione um novo módulo CRUD, permissão, definição, ou tarefa agendada, seguindo as próprias convenções da aplicação.
Nesta página
Estender a Aplicação
O CBGenesis é uma plataforma de lançamento, não um produto acabado. Estes são os mesmos passos que os seus próprios módulos Users/Roles/Permissions/Settings seguem - use-os como template para qualquer coisa nova.
Construir com um agente de IA
Se está a estender o cbGenesis com um agente de IA de programação (Claude Code, Copilot, Cursor, ou semelhante), aponte-o para .agents/skills-custom/ antes de escrever qualquer código - estas skills codificam exatamente os passos abaixo como instruções legÃveis por máquina, com excertos de código reais desta base de código, para que o agente não tenha de os descobrir por engenharia reversa explorando cada handler:
| Skill | Cobre |
|---|---|
cbgenesis-crud-resource | A fatia vertical completa abaixo - entidade, serviço, handler, rota, vista, componente - de ponta a ponta. |
cbgenesis-rbac-permissions | O modelo de permissões resource:action, o @secured, e as proteções contra auto-ação. |
cbgenesis-csrf-frontend | O padrão obrigatório fetchWithCsrf() para qualquer pedido de frontend que altere estado. |
cbgenesis-alpine-components | A forma dos componentes Alpine.js, o seu registo, e a biblioteca utils/ partilhada. |
cbgenesis-testing-conventions | BaseIntegrationSpec, o verdadeiro mecanismo de isolamento por reversão de transação, e os auxiliares de fixtures. |
cbgenesis-settings-config | Quando utilizar uma variável de ambiente em vez do registo de definições guardado na base de dados. |
Encontrou uma nova convenção que valha a pena um agente (ou um humano) não ter de redescobrir por tentativa e erro? Adicione-a aqui como uma nova skill, em vez de a deixar como conhecimento tribal numa descrição de PR. Veja ConstruÃdo para o Desenvolvimento Assistido por IA para saber porque isto importa, e uma comparação medida de antes/depois.
Adicionar um novo módulo CRUD
Em app/models/<domain>/, estendendo BaseEntity — veja Base de Dados e ORM.
Estendendo BaseService, marcado como singleton threadSafe — veja o padrão de serviço.
Estendendo BaseSecureHandler, com uma anotação @secured — veja Handlers e Rotas. Herdar dessa base significa que qualquer ação POST/PUT/DELETE que adicionar é verificada automaticamente por CSRF; não há nada a ativar manualmente, mas os seus formulários e componentes Alpine têm de enviar rc.csrf.
Em app/config/Router.bx, perto do marcador // @app_routes@.
Em app/views/<domain>/, reutilizando os partials existentes em _components/ui/.
Em resources/assets/js/components/<domain>/, e depois registe-o em App.js — veja Frontend.
Em resources/assets/scss/views/, importado a partir de app.scss.
Specs unitárias em tests/specs/unit/<domain>/, mais uma spec de integração em tests/specs/integration/ para as rotas que adicionou — veja Testes.
Adicionar uma nova permissão
Adicione o slug resource:action a resources/database/seeds/AdminData.bx e atribua-o à (s) função(ões) apropriada(s).
@secured( "resource:action,resource:admin" ) — a vÃrgula significa OU. Veja Segurança e Permissões.
<bx:if prc.authUser.hasPermission( "resource:action,resource:admin" )>
para que a interface nunca ofereça algo que o handler recusaria.
box migrate seed run contra uma base de dados existente - ou conceda a permissão a uma função diretamente a partir da página de administração de Funções.
Adicionar uma definição
Adicione uma nova chave à struct DEFAULTS em SettingService.bx. preFlightCheck() semeia-a automaticamente no próximo arranque, e ela aparece na página de administração /settings sem qualquer ligação adicional — veja Configuração.
Personalizar layouts
Os layouts residem em app/layouts/. A seleção acontece por handler, tipicamente em preHandler:
function preHandler( event, rc, prc ){
event.setLayout( "Admin" );
}
Adicionar uma tarefa agendada
Registe tarefas em app/config/Scheduler.bx, ao lado das três que já lá são executadas - veja Arquitetura para saber o que fazem:
task( "My Task" )
.call( () => getInstance( "MyService" ).doWork() )
.everyDayAt( "03:45" )
.onOneServer()
.withNoOverlaps();
onOneServer() e withNoOverlaps() importam a partir do momento em que implanta mais do que uma instância: sem eles, cada instância executa a tarefa segundo o seu próprio calendário. Coloque a lógica real de purga/limpeza no serviço (doWork() acima), e não diretamente na closure, para que se mantenha testável de forma unitária.
Sobrepor a configuração de módulos
As configurações de módulos em app/config/modules/ estendem as predefinições do próprio módulo. Sobreponha aà qualquer chave — as alterações têm efeito no próximo ?fwreinit.
Por que as skills personalizadas existem, e uma comparação medida de tokens/chamadas a ferramentas.
As convenções completas de handlers/rotas sobre as quais esta secção se apoia.
Os padrões de entidade e serviço em profundidade.
Lance o que construiu.