Extendiendo la aplicación

Agrega un nuevo módulo CRUD, permiso, ajuste, o tarea programada, siguiendo las propias convenciones de la aplicación.

En esta página

Extendiendo la aplicación

CBGenesis es una plataforma de lanzamiento, no un producto terminado. Estos son los mismos pasos que siguen sus propios módulos de Usuarios/Roles/Permisos/Configuración - úsalos como plantilla para cualquier cosa nueva.

Construyendo con un agente de IA

Si estás extendiendo cbGenesis con un agente de codificación de IA (Claude Code, Copilot, Cursor, o similar), apúntalo a .agents/skills-custom/ antes de que escriba cualquier código - estas skills codifican los pasos exactos de abajo como instrucciones legibles por máquina, con extractos de código reales de este código base, para que el agente no tenga que hacer ingeniería inversa explorando cada handler:

SkillCubre
cbgenesis-crud-resourceLa porción vertical completa de abajo - entidad, servicio, handler, ruta, vista, componente - de principio a fin.
cbgenesis-rbac-permissionsEl modelo de permisos resource:action, @secured, y las protecciones contra auto-acciones.
cbgenesis-csrf-frontendEl patrón obligatorio fetchWithCsrf() para cualquier solicitud de frontend que modifique datos.
cbgenesis-alpine-componentsLa forma de los componentes de Alpine.js, su registro, y la librería compartida utils/.
cbgenesis-testing-conventionsBaseIntegrationSpec, el mecanismo real de aislamiento por reversión de transacciones, y los helpers de fixtures.
cbgenesis-settings-configCuándo usar una variable de entorno frente al registro de ajustes respaldado por base de datos.

¿Una nueva convención que valga la pena que un agente (o un humano) no tenga que redescubrir por prueba y error? Agrégala como una nueva skill aquí en lugar de dejarla como conocimiento tribal en la descripción de un PR. Consulta Diseñado para el desarrollo asistido por IA para saber por qué esto importa y una comparación medida de antes/después.

Agregar un nuevo módulo CRUD

1
Crea la entidad

En app/models/<domain>/, extendiendo BaseEntity — consulta Base de datos y ORM.

2
Crea el servicio

Extendiendo BaseService, marcado singleton threadSafe — consulta el patrón de servicio.

3
Crea el handler

Extendiendo BaseSecureHandler, con una anotación @secured — consulta Handlers y enrutamiento. Heredar esa base significa que cada acción POST/PUT/DELETE que agregues queda verificada automáticamente por CSRF; no hay nada que activar, pero tus formularios y componentes Alpine deben enviar rc.csrf.

4
Agrega rutas

En app/config/Router.bx, cerca del marcador // @app_routes@.

5
Crea vistas

En app/views/<domain>/, reutilizando los parciales existentes de _components/ui/.

6
Crea un componente Alpine

En resources/assets/js/components/<domain>/, y luego regístralo en App.js — consulta Frontend.

7
Agrega SCSS

En resources/assets/scss/views/, importado desde app.scss.

8
Escribe pruebas

Specs unitarias en tests/specs/unit/<domain>/, más una spec de integración en tests/specs/integration/ para las rutas que agregaste — consulta Pruebas.

Agregar un nuevo permiso

1
Siembra el slug

Agrega el slug resource:action a resources/database/seeds/AdminData.bx y asígnalo a los roles apropiados.

2
Protege el handler

@secured( "resource:action,resource:admin" ) — la coma significa OR. Consulta Seguridad y permisos.

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

para que la interfaz nunca ofrezca algo que el handler rechazaría.

4
Vuelve a sembrar

box migrate seed run contra una base de datos existente - o concede el permiso a un rol directamente desde la página de administración de Roles.

Agregar un ajuste

Agrega una nueva clave al struct DEFAULTS en SettingService.bx. preFlightCheck() la siembra automáticamente en el siguiente arranque, y aparece en la página de administración /settings sin necesidad de más conexiones — consulta Configuración.

Personalizando los layouts

Los layouts viven en app/layouts/. La selección ocurre por handler, típicamente en preHandler:

function preHandler( event, rc, prc ){
    event.setLayout( "Admin" );
}

Agregar una tarea programada

Registra las tareas en app/config/Scheduler.bx, junto a las tres que ya se ejecutan ahí - consulta Arquitectura para ver qué hacen:

task( "My Task" )
    .call( () => getInstance( "MyService" ).doWork() )
    .everyDayAt( "03:45" )
    .onOneServer()
    .withNoOverlaps();

onOneServer() y withNoOverlaps() importan en el momento en que despliegas más de una instancia: sin ellos, cada instancia ejecuta la tarea según su propio calendario. Pon la lógica real de purga/limpieza en el servicio (doWork() arriba), no en línea dentro del closure, para que se mantenga comprobable de forma unitaria.

Sobrescribiendo la configuración de módulos

Las configuraciones de módulos en app/config/modules/ extienden los valores predeterminados propios del módulo. Sobrescribe cualquier clave ahí — los cambios surten efecto en el siguiente ?fwreinit.

Editar esta página Descargar Markdown Última actualización Oct 1, 2026, 2:02:30 PM