Desktop Kit
Soporte para aplicaciones de escritorio con Tauri. Expone un DesktopDriver que se registra en el Core y actua como puente entre la logica de tu App de Iskra y las APIs nativas de Tauri (ventanas, IPC, menus).
Inicio Rapido
Sección titulada «Inicio Rapido»import { App } from '@iskra-bun/core';import { DesktopDriver } from '@iskra-bun/desktop-kit';
const app = new App({ name: 'MiAppDeEscritorio' });
app.register(new DesktopDriver());
await app.start();// Al arrancar solo registra un warning: todavia no hay integracion con Tauri.El DesktopDriver implementa la interfaz Driver del Core, asi que participa del ciclo de vida estandar: se inicializa en app.start() y se libera en app.stop().
DesktopDriver
Sección titulada «DesktopDriver»El driver guarda una referencia a la App durante init() y queda listo para reenviar mensajes entre el dominio y la capa nativa de Tauri.
import { DesktopDriver } from '@iskra-bun/desktop-kit';
const driver = new DesktopDriver();
// driver.name → 'DesktopDriver'// driver.init(app) → guarda la App y prepara el puente// driver.start() → activa el puente y loguea el arranque
app.register(driver);| Miembro | Tipo | Descripcion |
|---|---|---|
name |
string |
Identificador del driver ('DesktopDriver'). |
init(app) |
Promise<void> |
Recibe la App y guarda la referencia interna. |
start() |
Promise<void> |
Activa el puente de Tauri y emite el log de arranque. |
Ventanas (Window)
Sección titulada «Ventanas (Window)»La gestion de ventanas se hace con la API de Tauri (@tauri-apps/api). El DesktopDriver te da el punto de enganche; desde tus handlers podes controlar la ventana actual.
import { getCurrentWindow } from '@tauri-apps/api/window';
const appWindow = getCurrentWindow();
await appWindow.setTitle('Iskra Desktop');await appWindow.maximize();await appWindow.setResizable(false);Reaccionar a eventos de la ventana desde el bus de la App:
app.on('window:focus', async (ctx) => { ctx.logger.info('La ventana recupero el foco');});
const appWindow = getCurrentWindow();await appWindow.onFocusChanged(({ payload: focused }) => { app.emit('window:focus', { focused });});IPC (comunicacion con el backend Rust)
Sección titulada «IPC (comunicacion con el backend Rust)»Tauri expone comandos Rust al frontend mediante invoke. Envolve esas llamadas en servicios de tu App para mantener el dominio desacoplado de Tauri.
import { invoke } from '@tauri-apps/api/core';
// Llamar a un comando Rust registrado en el backend de Tauriconst usuarios = await invoke<Usuario[]>('listar_usuarios', { activos: true });Registrar el servicio en el contenedor de DI del Core para reutilizarlo:
class DesktopBridge { // El comando Rust pregunta donde guardar con el dialogo nativo. async guardarArchivo(contenido: string) { return invoke('guardar_archivo', { contenido }); }}
app.context.set('desktopBridge', new DesktopBridge());
// En cualquier handlerconst bridge = app.context.get('desktopBridge');await bridge.guardarArchivo('Hola Iskra');No le pases a un comando una ruta que venga del webview: un script que llegue a la pagina (un string inyectado, una dependencia comprometida) podria leer o escribir cualquier archivo del usuario, como ~/.ssh/id_ed25519. Que el comando Rust elija el archivo con el dialogo nativo (tauri-plugin-dialog) y lo lea o escriba ahi, como hace abrir_archivo en la plantilla desktop-app. Declara cada comando en build.rs (tauri_build::Attributes::new().app_manifest(AppManifest::new().commands(&[...]))) y concedelo en una capability (allow-<comando>): si no, cualquier webview puede invocarlo.
Escuchar eventos emitidos desde Rust y reenviarlos al bus de Iskra:
import { listen } from '@tauri-apps/api/event';
await listen<{ progreso: number }>('descarga:progreso', (evento) => { app.emit('descarga:progreso', evento.payload);});Los menus nativos se construyen con la API de menu de Tauri. Conecta cada item a un evento de la App para procesarlo con tus handlers.
import { Menu, MenuItem } from '@tauri-apps/api/menu';
const itemAcercaDe = await MenuItem.new({ text: 'Acerca de', action: () => app.emit('menu:acerca-de', {}),});
const menu = await Menu.new({ items: [itemAcercaDe] });await menu.setAsAppMenu();
app.on('menu:acerca-de', async (ctx) => { ctx.logger.info('Abrir dialogo Acerca de');});Configuracion
Sección titulada «Configuracion»El DesktopDriver no recibe opciones propias: toda la configuracion nativa (tamano de ventana, permisos, iconos) vive en tauri.conf.json, el archivo de configuracion de Tauri.
{ "productName": "Iskra Desktop", "app": { "windows": [ { "title": "Iskra Desktop", "width": 1024, "height": 768, "resizable": true } ] }}El nombre logico de tu App de Iskra se sigue manejando desde el Core:
const app = new App({ name: 'Iskra Desktop', logger: { level: 'info' } });Ejemplo Completo
Sección titulada «Ejemplo Completo»import { App } from '@iskra-bun/core';import { DesktopDriver } from '@iskra-bun/desktop-kit';import { getCurrentWindow } from '@tauri-apps/api/window';import { invoke } from '@tauri-apps/api/core';
const app = new App({ name: 'Iskra Desktop' });app.register(new DesktopDriver());
app.on('archivo:abrir', async (ctx) => { // abrir_archivo abre el dialogo nativo y lee en Rust el archivo elegido. const archivo = await invoke<{ ruta: string; contenido: string } | null>('abrir_archivo'); if (archivo) ctx.logger.info({ bytes: archivo.contenido.length }, 'Archivo cargado');});
async function main() { await app.start();
const ventana = getCurrentWindow(); await ventana.setTitle('Iskra Desktop');
app.emit('archivo:abrir', {});}
main().catch((err) => app.logger.error({ err }, 'Fallo al arrancar'));Para una plantilla lista para usar, mira templates/desktop-app. Si tu app tambien apunta a moviles, revisa @iskra-bun/mobile-kit y la plantilla universal-app.