Ir al contenido

Sistema de plugins

Los plugins extienden Keirost sin tocar el core: campos y tablas nuevas, lógica de negocio en hooks, endpoints HTTP, módulos de UI, widgets de dashboard, tools de IA y temas. Se activan por empresa (tenant).

Capacidad API del contexto Referencia
Añadir campos a tablas del ERP migration.addCustomField Migraciones
Crear tablas propias migration.createTable Migraciones
Reaccionar a eventos (facturas, pagos, envíos…) hooks.register / documents.on* Catálogo de hooks
Exponer endpoints HTTP app.get / app.post PluginContext
Lógica de negocio transaccional factuApi FactuAPI
Consultar la BD directamente db.public / db.forTenant PluginContext
Módulos y páginas en el ERP manifest.jsonui Manifest y UI
Widgets en el dashboard ui.dashboardWidgets / widgets.registerDashboard Manifest y UI
Tools para el chat de IA aiTools.register PluginContext
Temas visuales ui.themes Manifest y UI
  • Directoriomi-plugin/
    • index.ts exporta init() — migraciones, hooks, endpoints
    • manifest.json metadatos y UI declarativa
    • Directorioui/
      • Page.tsx componentes React (opcional)
    • package.json con @openfactu/plugin-sdk

El punto de entrada es una función init que recibe el PluginContext:

import type { PluginContext } from '@openfactu/plugin-sdk';
export const init = async (context: PluginContext) => {
// context: { app, migration, hooks, documents, factuApi, db, widgets, aiTools }
};
// type PluginInit = (context: PluginContext) => void | Promise<void>;
  1. Carga — al arrancar, el servidor recorre plugins/ y ejecuta el init() de cada plugin (las migraciones son idempotentes).
  2. Activación por tenant — cada empresa activa o desactiva el plugin de forma independiente; con el plugin desactivado sus hooks no se ejecutan y su UI no se carga. Ver Activación por empresa.
  3. Hot reload — en desarrollo, al guardar un archivo se limpian los hooks, se re-ejecuta init() y el frontend se actualiza por WebSocket sin refrescar. Ver Desarrollo remoto.

El mismo documento se nombra de tres formas según la API — es la principal fuente de confusión al escribir plugins:

Documento DocType
(factuApi.create)
DocumentType
(eventos de hook)
CoreTableName
(tablas, documents.on*)
Factura de venta SINV salesInvoice SalesInvoice
Factura de compra PINV purchaseInvoice PurchaseInvoice
Pedido de venta SO salesOrder SalesOrder
Pedido de compra PO purchaseOrder PurchaseOrder
Albarán de venta SDN salesDeliveryNote SalesDeliveryNote
Albarán de compra PDN purchaseDeliveryNote PurchaseDeliveryNote
Ventana de terminal
npm install --save-dev @openfactu/plugin-sdk

@openfactu/plugin-sdk (v0.4.0) es type-only: exporta los tipos (PluginContext, HookContext, PluginManifest, HookEvent, CoreTableName…) pero ninguna implementación — el runtime lo inyecta el servidor al cargar el plugin. Peer dependencies: react ^19, react-dom ^19, lucide-react >=0.400.

GET /api/plugins/available
POST /api/plugins/:pluginId/activate
POST /api/plugins/:pluginId/deactivate
POST /api/plugins/:pluginId/reload
POST /api/plugins/upload
POST /api/plugins/:pluginId/push