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:

SkillCobre
cbgenesis-crud-resourceA fatia vertical completa abaixo - entidade, serviço, handler, rota, vista, componente - de ponta a ponta.
cbgenesis-rbac-permissionsO modelo de permissões resource:action, o @secured, e as proteções contra auto-ação.
cbgenesis-csrf-frontendO padrão obrigatório fetchWithCsrf() para qualquer pedido de frontend que altere estado.
cbgenesis-alpine-componentsA forma dos componentes Alpine.js, o seu registo, e a biblioteca utils/ partilhada.
cbgenesis-testing-conventionsBaseIntegrationSpec, o verdadeiro mecanismo de isolamento por reversão de transação, e os auxiliares de fixtures.
cbgenesis-settings-configQuando 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

1
Criar a entidade

Em app/models/<domain>/, estendendo BaseEntity — veja Base de Dados e ORM.

2
Criar o serviço

Estendendo BaseService, marcado como singleton threadSafe — veja o padrão de serviço.

3
Criar o handler

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.

4
Adicionar rotas

Em app/config/Router.bx, perto do marcador // @app_routes@.

5
Criar vistas

Em app/views/<domain>/, reutilizando os partials existentes em _components/ui/.

6
Criar um componente Alpine

Em resources/assets/js/components/<domain>/, e depois registe-o em App.js — veja Frontend.

7
Adicionar SCSS

Em resources/assets/scss/views/, importado a partir de app.scss.

8
Escrever testes

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

1
Semear o slug

Adicione o slug resource:action a resources/database/seeds/AdminData.bx e atribua-o à(s) função(ões) apropriada(s).

2
Proteger o handler

@secured( "resource:action,resource:admin" ) — a vírgula significa OU. Veja Segurança e Permissões.

3
Restringir a vista
<bx:if prc.authUser.hasPermission( "resource:action,resource:admin" )>

para que a interface nunca ofereça algo que o handler recusaria.

4
Semear novamente

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.

Editar esta página Baixar Markdown Última atualização Oct 1, 2026, 2:02:30 PM