Skip to main content

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 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.
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:
  1. Arrancar el servidor Express embebido — en producción, usa child_process.fork para levantar el servidor compilado desde resources/server/dist/index.js dentro del paquete ASAR.
  2. Crear la ventana principal (BrowserWindow) — carga el renderer desde el bundle de Vite (apps/renderer/dist/index.html) en producción, o desde localhost:5173 en desarrollo.
  3. 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.
En modo de desarrollo, el servidor Express no se inicia desde Electron — se asume que ya corre en localhost:3001 en una terminal separada.

Proceso principal (main.js)

El archivo apps/electron/main.js coordina toda la aplicación:
  • startServer() — en producción, usa fork para iniciar server/dist/index.js como proceso hijo. Pasa BRANCH_ID, NODE_ENV=production y SQLITE_PATH (usando app.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 un BrowserWindow de 1280×800 con contextIsolation: true, nodeIntegration: false y sandbox: true para máxima seguridad. La ventana no se muestra hasta estar completamente lista (ready-to-show).
  • loadRenderer(win) — en desarrollo intenta conectar a Vite en localhost:5173 hasta 30 veces con reintentos cada 500 ms; en producción carga el index.html compilado 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-maximize y window-close desde el renderer.

Preload script

El archivo preload.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étodoTipoDescripción
getBranchId()invokeID de la sucursal activa
getAppVersion()invokeVersión de la aplicación
getUserDataPath()invokeRuta de datos del usuario en el SO
minimizeWindow()sendMinimiza la ventana principal
maximizeWindow()sendMaximiza o restaura la ventana
closeWindow()sendCierra la ventana principal
printTicket(data)invokeEnvía un ticket a la impresora térmica POS
getPrinters()invokeLista las impresoras disponibles en el sistema
getServerStatus()invokeConsulta si el servidor Express embebido está listo
onServerReady(cb)listenerNotifica cuando el servidor Express está disponible
onSyncStatus(cb)listenerNotifica cambios en el estado de sincronización offline
getSyncPendientes()invokeCantidad de registros pendientes de sincronizar con Supabase

Comunicación IPC

El directorio apps/electron/ipc/ contiene los handlers de IPC del proceso principal:
  • printer.ipc.js — maneja print-ticket y get-printers. Usa electron-pos-printer si está disponible; si no, entra en modo simulado y registra el ticket en consola sin fallar.
  • server.ipc.js — exporta waitForServer(win), que hace polling al endpoint /health del servidor Express hasta que responde con HTTP 200 (máximo 20 intentos cada 500 ms). Una vez listo, envía el evento server-ready al renderer. También maneja get-server-status desde el renderer.
wait-on se usa en el script dev:electron del package.json raíz para esperar a que tanto Vite (http://localhost:5173) como el servidor Express (http://localhost:3001/health) estén disponibles antes de lanzar Electron. Esto evita errores de pantalla en blanco durante el arranque en desarrollo.

Construir para producción

Antes de empaquetar con electron-builder, compila el servidor TypeScript y el renderer React:
1

Compilar el servidor

pnpm build:server
Ejecuta tsc en apps/server y copia el esquema SQL de SQLite al directorio dist/. La salida queda en apps/server/dist/.
2

Compilar el renderer

pnpm build:renderer
Vite genera el bundle estático en apps/renderer/dist/. Este directorio es cargado por Electron en producción.
3

Empaquetar con electron-builder

Desde apps/electron/, ejecuta el comando para la plataforma objetivo:
pnpm --filter @ferred/electron build:win
El instalador generado se guarda en dist-electron/ en la raíz del monorepo.
La configuración de electron-builder en apps/electron/package.json incluye:
PlataformaFormatoArquitectura
WindowsNSIS installerx64
macOSDMGx64, arm64
LinuxAppImagex64
El servidor compilado (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.

Build docs developers (and LLMs) love