Arquitectura
Iskra sigue una arquitectura hexagonal (Ports & Adapters) que separa la logica de negocio de los detalles de infraestructura.
Capas del Framework
Sección titulada «Capas del Framework»┌─────────────────────────────────────────────────┐│ Tu Aplicacion ││ (handlers, servicios, dominio) │├─────────────────────────────────────────────────┤│ Capa de Plugins ││ (extensiones opcionales del framework) │├─────────────────────────────────────────────────┤│ Capa de Drivers ││ WebPlugin │ DbDriver │ SocketDriver │ KV │ … │├─────────────────────────────────────────────────┤│ @iskra-bun/core ││ App │ EventBus │ Logger │ Config │ DI │ Errors│└─────────────────────────────────────────────────┘Interfaces Fundamentales
Sección titulada «Interfaces Fundamentales»Cada kit del framework expone un Driver que se registra en la App:
interface Driver { name: string; init(app: App): Promise<void> | void; start?(): Promise<void> | void; stop?(): Promise<void> | void;}El ciclo de vida es: register() → init() → start() → stop().
Los plugins son extensiones livianas que no tienen ciclo de vida completo:
interface Plugin { name: string; install(app: App): Promise<void> | void;}Feature (Web Kit)
Sección titulada «Feature (Web Kit)»Las features son modulos del Kernel web con resolucion de dependencias:
interface Feature { name: string; dependencies?: string[]; peerDependencies?: string[]; initialize(kernel: Kernel): Promise<void>; routes?(app: Hono): void; shutdown?(): Promise<void>;}Drivers vs Plugins
Sección titulada «Drivers vs Plugins»- Un Driver tiene ciclo de vida completo (
init/start/stop) y se registra conapp.register(driver). Úsalo cuando manejes un recurso que se abre y se cierra: un servidor HTTP, una conexión de base de datos, un servidor WebSocket. - Un Plugin es liviano y se instala de inmediato con
app.use(plugin)a través deinstall(app). Úsalo para extender el comportamiento sin administrar un recurso de larga duración.
Inyeccion de Dependencias
Sección titulada «Inyeccion de Dependencias»Iskra usa app.context, un Map cuyas claves se tipan con AppContextRegistry (ver Core), como contenedor de DI:
// Un driver se registra en el contextoapp.context.set('db', dbDriver);
// Otro componente lo consume, tipado: DbDriver | undefinedconst db = app.context.get('db');Sistema de Eventos
Sección titulada «Sistema de Eventos»La comunicacion entre componentes se hace via el event bus (basado en mitt). Los payloads estan tipados para los eventos declarados en AppEvents:
// Escucharapp.on('order:created', async (ctx) => { const order = ctx.payload; ctx.logger.info({ order }, 'Orden creada');});
// Emitirapp.emit('order:created', { id: 1, total: 150 });Jerarquia de Errores
Sección titulada «Jerarquia de Errores»Todos los errores del framework extienden de IskraError:
IskraError├── ConfigError├── DriverError├── PluginError├── LifecycleError├── HttpError (web-kit)│ ├── ValidationError│ ├── AuthError│ ├── ForbiddenError│ ├── NotFoundError│ └── ConflictError├── ConnectionError (db-kit)├── QueryError (db-kit)├── MigrationError (db-kit)├── QueueError (worker-kit)├── JobError (worker-kit)├── SocketConnectionError (socket-kit)└── SocketMessageError (socket-kit)Cada error tiene code, context (metadata) y soporte para cause (encadenamiento).