Skip to content

Architecture.fr

Doug Blank edited this page Sep 22, 2026 · 1 revision

🌐 English · Deutsch

Architecture

Gramps Connect est un frontend React (app/) qui parle à un backend gramps-web-api via son API REST — il ne fork pas et ne remplace pas gramps-web-api, c'est un client différent pour le même serveur. Deux mécanismes rendent possible pour ce frontend de sembler à la fois rapide et collaboratif : un cache local, et une requête légère de synchronisation en direct superposée à un endpoint que gramps-web-api fournit déjà.

Cache local

Un build WASM de SQLite s'exécute dans le navigateur, reflétant les données du serveur dans des tables locales et les conservant dans OPFS (le propre système de fichiers privé du navigateur) pour qu'une visite répétée puisse complètement éviter le réseau. Les données sont récupérées via les endpoints rapides /api/<type>/query/ de gramps-web-api, avec traitement SQL poussé côté serveur — les mêmes endpoints vers lesquels compilent les conditions GOQL et les clauses where= des Gramplets — plutôt qu'en paginant à travers des réponses REST complètes par objet.

Le gain est ce que décrit l'Aperçu : une fois qu'une partie de l'arbre a été consultée, parcourir, trier et rechercher dans cette partie redeviennent instantanés ensuite, même sur des arbres avec des dizaines de milliers de personnes, où ce genre de recherche peut sinon prendre bien plus d'une minute contre un backend REST simple et non indexé.

C'est aussi pourquoi la version pour ordinateur à admin/admin fixe et un vrai déploiement serveur peuvent partager exactement le même code frontend sans traitement spécial : le cache se soucie seulement de parler à un /api/ de forme gramps-web-api, pas de qui l'héberge.

Un piège à connaître : le cache côté navigateur est indexé par un nom de fichier fixe par vue, pas par URL de backend ou ID d'arbre. Changer de backend visé, ou réimporter/recréer un arbre contre le même backend, peut laisser un profil de navigateur servir des lignes en cache obsolètes sans invalidation automatique — la seule vérification effectuée porte sur la compatibilité de schéma, pas l'identité des données. Si les données semblent un jour obsolètes après un changement de backend, les effacer manuellement : DevTools → Application → Storage → effacer les données du site (ou spécifiquement OPFS).

Synchronisation en direct

Le client interroge l'endpoint déjà existant GET /api/transactions/history/ de gramps-web-api (le journal d'audit/annulation des modifications d'objets qu'il fournit déjà, rien d'ajouté pour l'occasion) à intervalle court. Pour chaque objet que cet endpoint signale comme modifié, Gramps Connect récupère à nouveau et met à jour seulement cette ligne dans le cache local.

C'est délibérément simple : aucune connexion persistante de type WebSocket ni de capture de changement de données spécifique à Postgres n'est requise, juste un simple GET authentifié sur une minuterie — cela fonctionne donc contre n'importe quel backend gramps-web-api, pas seulement un avec Postgres derrière. C'est ainsi que « quelqu'un d'autre corrige une date et votre écran se met à jour tout seul » (voir Aperçu) fonctionne réellement, et c'est aussi ainsi que les fixtures de développement peuvent exercer la synchronisation sans avoir besoin d'une véritable instance Postgres — même les fixtures en pur SQLite le prennent en charge, puisque ce n'est qu'une requête.

Ce que la synchronisation en direct ne fait pas encore : il n'y a pas de couche de présence (qui consulte ou modifie quoi en ce moment) ni de navigateur d'historique côté utilisateur — voir Feuille de route et limitations connues.

Organisation du dépôt

  • app/ — le client React de production : les dix vues de type d'objet (personne, famille, événement, lieu, dépôt, source, citation, media, note, étiquette — voir Modèle de données et édition), le filtrage where_expr/GOQL, un cache WASM SQLite conservé dans OPFS, et la synchronisation en direct, derrière une couche de store basée sur useSyncExternalStore (app/src/store/) avec @tanstack/react-virtual pour le défilement.
  • dev-fixtures/ — de véritables backends gramps-web-api pour faire tourner app/ localement contre eux ; pas partie du produit livré, juste ce qui rend le développement local possible sans configurer un serveur à la main. Voir Développement pour les trois variantes (layer2-local-cache/api-fixture, api-fixture-example, et layer3-sync/api-fixture) et à quoi chacune sert.
  • packages/gramps-date/ — un portage TypeScript du propre modèle Date de Gramps, de la conversion de calendrier, et de l'affichage de date sensible à la locale, utilisé par app/ pour pouvoir rendre ou construire une structure Date de Gramps sans un aller-retour réseau lent par objet via le propre afficheur de date Python de Gramps pour chaque ligne d'un tableau. Il gère la conversion de calendrier pour cinq calendriers (grégorien, julien, révolutionnaire français, islamique, suédois — hébreu et persan s'affichent correctement mais ne peuvent pas encore être validés à la saisie, puisque leur conversion SDN a besoin de plus de machinerie), la saisie et la validation de date structurée, et l'affichage connectable par locale (registerLocale() ; seul l'anglais est fourni aujourd'hui). C'est une traduction des propres gramps/gen/lib/date.py/gcalendar.py/_datedisplay.py du cœur de Gramps, de Python vers TypeScript, vérifiée par recoupement avec la véritable implémentation Python dans sa propre suite de tests — voir son propre README pour l'histoire complète de provenance et de licence (c'est du code GPL-2.0-or-later intégré dans ce projet AGPL-3.0-or-later, de la même façon que le propre portage gcalendar.js de gramps-web le fait déjà).
  • standalone/ — le build basé sur PyInstaller de gramps-connect-desktop : un lanceur Python (launcher.py) qui regroupe le frontend construit de app/ avec gramps-web-api et SQLite en une seule application à fenêtre native (ou repli navigateur). Voir Installation.
  • deploy/ — le déploiement conteneurisé multi-utilisateur (app/
    • gramps-web-api + Postgres + Caddy + Redis/Celery). Voir Déploiement.
  • gramplet_examples/ et gramplet-store/ — des Gramplets d'exemple et le contenu source du catalogue de la boutique de Gramplets intégrée à l'application. Voir Gramplets.

Un workspace npm de premier niveau (packages/*, app) relie app/ et packages/gramps-date comme de véritables dépendances de workspace. Les endpoints rapides /query/ dont dépend app/ vivent en réalité dans gramps-web-api lui-même (un dépôt séparé, étendu directement dedans, rétrocompatible), via gramps-object-query-language, la propre implémentation de GOQL — pas dans ce dépôt.

Les extensions exécutent du Python dans le navigateur

Les Gramplets — les extensions de l'application — s'exécutent sous Pyodide (CPython compilé en WebAssembly) directement dans l'onglet de navigateur, contre des wheels construits localement de gramps.gen.lib (le propre modèle de données de Gramps, de sorte que le code Python d'un Gramplet voit de vrais objets Person/Family/…, pas une réimplémentation). Aucune exécution côté serveur et rien d'installé sur votre machine — voir Développement pour comment ces wheels sont construits, et Gramplets pour comment l'API en bac à sable (people(), filter(), db, row(), html(), …) est assemblée.

Clone this wiki locally