Skip to content

Architecture.es

Doug Blank edited this page Oct 5, 2026 · 3 revisions

🌐 English · Deutsch · Français · 简体中文

Arquitectura

Gramps Connect es un frontend de React (app/) que se comunica con un backend gramps-web-api a través de su API REST: no bifurca ni sustituye a gramps-web-api, es un cliente distinto para el mismo servidor. Dos mecanismos permiten que ese frontend resulte rápido y colaborativo a la vez: una caché local primero (local-first) y una ligera capa de sincronización en vivo por sondeo, montada sobre un endpoint que gramps-web-api ya incluye.

Caché local primero

Una compilación WASM de SQLite se ejecuta dentro del navegador, reflejando los datos del servidor en tablas locales y guardándolos en OPFS (el sistema de archivos privado del propio navegador), de modo que una visita posterior puede omitir la red por completo. Los datos se obtienen mediante los endpoints rápidos /api/<type>/query/ de gramps-web-api, que delegan el trabajo en SQL —los mismos endpoints a los que se compilan las condiciones de GOQL y las cláusulas where= de los Gramplets—, en lugar de paginar respuestas REST completas objeto por objeto.

La recompensa es lo que describe la Descripción general: una vez que ha visto una parte de su árbol, volver a navegar, ordenar y buscar en esa parte es instantáneo, incluso en árboles con decenas de miles de personas, donde este tipo de búsqueda podría tardar más de un minuto contra un backend REST simple sin índices.

Por eso también la versión de escritorio con admin/admin fijo y un despliegue real en servidor pueden compartir exactamente el mismo código de frontend sin casos especiales: a la caché solo le importa que está hablando con una /api/ con la forma de gramps-web-api, no quién la aloja.

Una trampa que conviene conocer: la caché del navegador se identifica por un nombre de archivo fijo por vista, no por la URL del backend ni por el ID del árbol. Cambiar el backend al que apunta, o volver a importar o recrear un árbol en el mismo backend, puede dejar un perfil del navegador sirviendo filas en caché obsoletas sin invalidación automática: la única comprobación que se hace es la compatibilidad del esquema, no la identidad de los datos. Si alguna vez los datos parecen obsoletos tras cambiar de backend, bórrelos manualmente: DevTools → Application → Storage → clear site data (o específicamente OPFS).

Sincronización en vivo

El cliente consulta periódicamente, a intervalos cortos, el endpoint existente GET /api/transactions/history/ de gramps-web-api (el registro de auditoría/deshacer de ediciones de objetos que ya incluye, no algo añadido para esto). Por cada objeto que ese endpoint indica como modificado, Gramps Connect vuelve a obtenerlo y actualiza solo esa fila en la caché local.

Es deliberadamente simple: no hace falta ninguna conexión persistente al estilo WebSocket ni captura de cambios específica de Postgres, solo un GET autenticado normal con un temporizador, así que funciona con cualquier backend gramps-web-api, no solo con uno basado en Postgres. Así es como funciona en realidad que «otra persona corrige una fecha y su pantalla se actualiza sola» (véase la Descripción general), y también es como los entornos de prueba de desarrollo pueden ejercitar la sincronización sin necesitar una instancia real de Postgres: incluso los que usan SQLite simple la admiten, porque es solo un sondeo.

Lo que la sincronización en vivo todavía no hace: no hay capa de presencia (quién está viendo o editando qué en este momento) ni un navegador de historial para el usuario; véase Hoja de ruta y limitaciones conocidas.

Organización del repositorio

  • app/: el cliente React de producción: las diez vistas de tipos de objeto (persona, familia, evento, lugar, repositorio, fuente, cita, objeto multimedia, nota, etiqueta; véase Modelo de datos y edición), el filtrado con where_expr/GOQL, una caché SQLite WASM guardada en OPFS y la sincronización en vivo, detrás de una capa de almacén basada en useSyncExternalStore (app/src/store/) con @tanstack/react-virtual para el desplazamiento.
  • dev-fixtures/: backends gramps-web-api reales contra los que ejecutar app/ localmente; no forman parte del producto distribuido, simplemente hacen posible el desarrollo local sin configurar un servidor a mano. Consulte Desarrollo para ver las tres variantes (layer2-local-cache/api-fixture, api-fixture-example y layer3-sync/api-fixture) y para qué sirve cada una.
  • packages/gramps-date/: una adaptación a TypeScript del modelo Date de Gramps, la conversión de calendarios y la presentación de fechas según la configuración regional, usada por app/ para poder mostrar o construir una estructura Date de Gramps sin un lento viaje de ida y vuelta por objeto a través del presentador de fechas en Python del propio Gramps para cada fila de una tabla. Gestiona la conversión de cinco calendarios (gregoriano, juliano, republicano francés, islámico y sueco; el hebreo y el persa se muestran correctamente, pero aún no se pueden validar al introducirlos, porque su conversión SDN necesita más maquinaria), la introducción y validación estructurada de fechas, y una presentación con configuraciones regionales conectables (registerLocale(); hoy solo se incluye el inglés). Es una traducción de Python a TypeScript de los propios gramps/gen/lib/date.py/gcalendar.py/_datedisplay.py del núcleo de Gramps, contrastada con la implementación real en Python en su propio conjunto de pruebas; consulte su README para conocer toda la historia de su procedencia y su licencia (es código GPL-2.0-or-later incorporado a este proyecto AGPL-3.0-or-later, igual que ya hace la adaptación gcalendar.js de gramps-web).
  • standalone/: la compilación de gramps-connect-desktop basada en PyInstaller: un lanzador en Python (launcher.py) que empaqueta el frontend compilado de app/ con gramps-web-api y SQLite en una única aplicación con ventana nativa (o, en su defecto, en el navegador). Véase Instalación.
  • deploy/: el despliegue multiusuario en contenedores (app/ + gramps-web-api + Postgres + Caddy + Redis/Celery). Véase Despliegue.
  • gramplet_examples/ y gramplet-store/: Gramplets de ejemplo y el contenido fuente del catálogo de la tienda de Gramplets integrada en la aplicación. Véase Gramplets.

Un espacio de trabajo npm en la raíz (packages/*, app) une app/ y packages/gramps-date como dependencias reales del espacio de trabajo. Los endpoints rápidos /query/ de los que depende app/ están en el propio gramps-web-api (un repositorio aparte, ampliado en el sitio y compatible con versiones anteriores) mediante gramps-object-query-language, la implementación de GOQL, no en este repositorio.

Los complementos ejecutan Python en el navegador

Los Gramplets —los complementos de la aplicación— se ejecutan con Pyodide (CPython compilado a WebAssembly) directamente en la pestaña del navegador, sobre wheels compiladas localmente de gramps.gen.lib (el propio modelo de datos de Gramps, de modo que el código Python de un Gramplet ve objetos Person/Family/... reales, no una reimplementación). Nada se ejecuta en el servidor y no se instala nada en su equipo; consulte Desarrollo para ver cómo se compilan esas wheels, y Gramplets para ver cómo se compone la API aislada (people(), filter(), db, row(), html(), ...).

Clone this wiki locally