Ferred puede empaquetarse como aplicación nativa de escritorio usando ElectronJS, permitiendo al personal de la ferretería operar el sistema sin un navegador y sin exponer puertos a la red local. El servidor Express, la base de datos SQLite y la interfaz React se distribuyen como un único ejecutable instalable.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Carlos-Gnd/FERRED-Inventario-y-Ventas/llms.txt
Use this file to discover all available pages before exploring further.
Ferred funciona tanto como aplicación web (desplegada en Netlify en ferred.netlify.app) como aplicación de escritorio empaquetada con Electron — exactamente con el mismo código fuente. La diferencia está en cómo se sirve el renderer y dónde corre el servidor.
Cómo funciona Electron en Ferred
En la versión de escritorio, el proceso principal de Electron (main.js) es responsable de:
- Arrancar el servidor Express embebido — en producción, usa
child_process.forkpara levantar el servidor compilado desderesources/server/dist/index.jsdentro del paquete ASAR. - Crear la ventana principal (
BrowserWindow) — carga el renderer desde el bundle de Vite (apps/renderer/dist/index.html) en producción, o desdelocalhost:5173en desarrollo. - Gestionar el ciclo de vida — al cerrar la aplicación, el proceso del servidor se termina limpiamente y el ícono de la bandeja del sistema se destruye.
localhost:3001 en una terminal separada.
Proceso principal (main.js)
El archivoapps/electron/main.js coordina toda la aplicación:
startServer()— en producción, usaforkpara iniciarserver/dist/index.jscomo proceso hijo. PasaBRANCH_ID,NODE_ENV=productionySQLITE_PATH(usandoapp.getPath('userData')) al entorno del proceso hijo para que el servidor guarde la base de datos SQLite en la carpeta de datos del usuario del sistema operativo.createWindow()— crea unBrowserWindowde 1280×800 concontextIsolation: true,nodeIntegration: falseysandbox: truepara máxima seguridad. La ventana no se muestra hasta estar completamente lista (ready-to-show).loadRenderer(win)— en desarrollo intenta conectar a Vite enlocalhost:5173hasta 30 veces con reintentos cada 500 ms; en producción carga elindex.htmlcompilado directamente desde el sistema de archivos.createTray()— crea un ícono en la bandeja del sistema con un menú que muestra la sucursal activa y permite abrir o cerrar la aplicación.- IPC básico — responde a
get-branch-id,get-app-version,get-user-data-path,window-minimize,window-maximizeywindow-closedesde el renderer.
Preload script
El archivopreload.js actúa como puente seguro entre el proceso principal y el renderer. Usa contextBridge.exposeInMainWorld para exponer una API llamada window.electronAPI con métodos específicos — sin exponer ipcRenderer completo al renderer.
Los métodos disponibles incluyen:
| Método | Tipo | Descripción |
|---|---|---|
getBranchId() | invoke | ID de la sucursal activa |
getAppVersion() | invoke | Versión de la aplicación |
getUserDataPath() | invoke | Ruta de datos del usuario en el SO |
minimizeWindow() | send | Minimiza la ventana principal |
maximizeWindow() | send | Maximiza o restaura la ventana |
closeWindow() | send | Cierra la ventana principal |
printTicket(data) | invoke | Envía un ticket a la impresora térmica POS |
getPrinters() | invoke | Lista las impresoras disponibles en el sistema |
getServerStatus() | invoke | Consulta si el servidor Express embebido está listo |
onServerReady(cb) | listener | Notifica cuando el servidor Express está disponible |
onSyncStatus(cb) | listener | Notifica cambios en el estado de sincronización offline |
getSyncPendientes() | invoke | Cantidad de registros pendientes de sincronizar con Supabase |
Comunicación IPC
El directorioapps/electron/ipc/ contiene los handlers de IPC del proceso principal:
printer.ipc.js— manejaprint-ticketyget-printers. Usaelectron-pos-printersi está disponible; si no, entra en modo simulado y registra el ticket en consola sin fallar.server.ipc.js— exportawaitForServer(win), que hace polling al endpoint/healthdel servidor Express hasta que responde con HTTP 200 (máximo 20 intentos cada 500 ms). Una vez listo, envía el eventoserver-readyal renderer. También manejaget-server-statusdesde el renderer.
Construir para producción
Antes de empaquetar con electron-builder, compila el servidor TypeScript y el renderer React:Compilar el servidor
tsc en apps/server y copia el esquema SQL de SQLite al directorio dist/. La salida queda en apps/server/dist/.Compilar el renderer
apps/renderer/dist/. Este directorio es cargado por Electron en producción.apps/electron/package.json incluye:
| Plataforma | Formato | Arquitectura |
|---|---|---|
| Windows | NSIS installer | x64 |
| macOS | DMG | x64, arm64 |
| Linux | AppImage | x64 |
apps/server/dist/**) se incluye automáticamente en el paquete como recurso extra en resources/server/dist/, desde donde main.js lo levanta con fork al arrancar la aplicación.