# Acadenice Patches Liste des patches custom appliques sur le fork Acadenice de Docmost. Ce document est maintenu manuellement pour faciliter le rebase upstream. Repo upstream : `github.com/docmost/docmost` Branche fork : `acadenice/main` ## Conventions - Chaque patch est commit isole avec scope `feat(rebrand)` / `feat(custom)` / etc. - Les modifications in-line de fichiers upstream sont documentees ici avec rationale. - Les nouveaux fichiers (extensions Tiptap custom, hooks, etc.) vont dans des emplacements dedies pour minimiser les conflits de rebase. --- ## Patch 012 — R3.5.1 backend graph endpoint GET /api/acadenice/graph **Date** : 2026-05-08 **Scope** : knowledge graph backend — nodes + edges from acadenice_backlink table **Rationale** : expose workspace link-graph as JSON for the R3.5.2 frontend (Obsidian-style graph view). Reads the `acadenice_backlink` table populated by R3.2. ### Architecture - Source de verite : table `acadenice_backlink` (indexee par R3.2 sur chaque save). - Permission filter : meme join space_members / visibility='public' que BacklinkService. - BFS iteratif en memoire (apres chargement des edges) pour les graphes centres (pageId). - Cache Redis TTL 60s par cle composite. Invalidation sur evenement `acadenice.page.content.updated` (meme event que R3.2). - Truncation a 1000 nodes pour les workspaces larges (top-inDegree + flag `truncated: true`). ### Endpoint `GET /api/acadenice/graph?workspaceId=X&spaceId=Y&pageId=Z&depth=N&types=wikilink,mention,database_embed&includeOrphans=false` - `workspaceId` : ignore — resolu depuis le JWT pour eviter les fuites cross-workspace - `spaceId` : optionnel, filtre les nodes au space - `pageId` : optionnel, centre le graphe + BFS depth hops - `depth` : 1-5, default 2 - `types` : filtre par type de lien (defaut: tous les 3) - `includeOrphans` : default false ### Reponse ```ts { nodes: Array<{ id, label, type, spaceId, spaceName, icon, isOrphan, metrics: { inDegree, outDegree } }>, edges: Array<{ id, source, target, type, weight }>, meta: { totalNodes, totalEdges, workspaceId, rootPageId?, depth?, truncated } } ``` ### Fichiers crees | Fichier | Role | |---------|------| | `apps/server/src/core/acadenice/graph/graph.module.ts` | NestJS module (R3.5.1) | | `apps/server/src/core/acadenice/graph/dto/graph.dto.ts` | Zod schemas + interfaces response | | `apps/server/src/core/acadenice/graph/services/graph.service.ts` | buildGraph, BFS, Redis cache | | `apps/server/src/core/acadenice/graph/controllers/graph.controller.ts` | GET /api/acadenice/graph | | `apps/server/src/core/acadenice/graph/spec/graph.service.spec.ts` | Tests service (21 tests) | | `apps/server/src/core/acadenice/graph/spec/graph.controller.spec.ts` | Tests controller (14 tests) | ### Fichiers modifies (patches upstream) | Fichier | Modification | |---------|-------------| | `apps/server/src/core/core.module.ts` | +AcadeniceGraphModule import + declaration | ### Tests - 35 tests total (21 service + 14 controller) - Service : full graph, edge weight, BFS depth=1/2, spaceId filter, types filter, permission filter, truncation@1000, orphans inclus/exclus, inDegree/outDegree, cache hit, cache invalidation, bfsReachable unit, buildCacheKey, error resilience - Controller : routing, params parsing (depth/spaceId/pageId/types/includeOrphans), validation errors (bad UUID, depth>5, depth<1), workspace isolation ### Strategies techniques - SQL : GROUP BY (source_page_id, target_page_id, link_type) avec COUNT(*) pour weight. Double join pages/spaces (source ET target) avec permission check inline. - BFS : iteratif avec Set visited. Graphe non-oriente (in+out edges). Cap MAX_NODES=1000. - Cache key : `acadenice:graph::::::` - Invalidation : pattern `acadenice:graph::*` via KEYS + DEL. Acceptable pour TTL=60s. --- ## Patch 011 — R3.4 dual editor (WYSIWYG + markdown source) **Date** : 2026-05-08 **Scope** : toggle WYSIWYG <-> raw markdown source, custom-node round-trip **Rationale** : permet aux utilisateurs power-users d'editer le source markdown directement, avec une conversion aller-retour complete preservant les nodes Acadenice custom (database-view, wikilink, mention). ### Architecture - Source de verite : Tiptap JSON (persiste en DB). Le markdown est une vue. - Mode persist : localStorage `acadenice:editor-mode:` par page. - Switch lossy : modal de confirmation listant les elements alteres. - Save : en mode markdown, le doc Tiptap est maintenu sync (setContent) a chaque keystroke pour que le mecanisme save Docmost natif reste fonctionnel. ### Syntaxe custom nodes en markdown | Node | Syntaxe markdown | |------|-----------------| | `database-view` | `[[!db tableId=X viewId=Y viewType=Z]]` | | `wikilink` | `[[Page Title]]` ou `[[Page Title\|alias]]` | | `mention` | `@(displayName)` | Choix : tokens entre `[[...]]` pour etre lisibles et reversibles. Le prefixe `!db` distingue les database-view des wikilinks. Les mentions encodent le userId (UUID) pour eviter la necessite d'une resolution serveur au re-parse. ### Fichiers crees | Fichier | Role | |---------|------| | `apps/client/src/features/acadenice/dual-editor/services/custom-node-serializers.ts` | Registre des serializers custom (databaseView, wikilink, mention) | | `apps/client/src/features/acadenice/dual-editor/services/markdown-converter.ts` | `tiptapToMarkdown` + `markdownToTiptap` — converter custom sans dep externe | | `apps/client/src/features/acadenice/dual-editor/hooks/use-editor-mode.ts` | Jotai atom `editorModeAtom` + `useEditorMode` hook + `initEditorMode` | | `apps/client/src/features/acadenice/dual-editor/components/mode-toggle-button.tsx` | Bouton toggle (IconCode / IconEye) dans la toolbar | | `apps/client/src/features/acadenice/dual-editor/components/markdown-editor.tsx` | Textarea monospace auto-resize (Tab -> 2 espaces) | | `apps/client/src/features/acadenice/dual-editor/components/dual-editor.tsx` | Wrapper WYSIWYG / markdown avec modal warning lossy | | `apps/client/src/features/acadenice/dual-editor/__tests__/markdown-converter.test.ts` | 61 tests round-trip (JSON->MD->JSON et MD->JSON->MD) | | `apps/client/src/features/acadenice/dual-editor/__tests__/custom-node-serializers.test.ts` | 12 tests unitaires serializers | | `apps/client/src/features/acadenice/dual-editor/__tests__/use-editor-mode.test.ts` | 4 tests persistence localStorage | ### Fichiers modifies (patches upstream) | Fichier | Modification | |---------|-------------| | `apps/client/src/features/editor/full-editor.tsx` | +import DualEditor + wrap `` avec `` | | `apps/client/public/locales/en-US/translation.json` | +8 cles `dual_editor.*` | | `apps/client/public/locales/fr-FR/translation.json` | +8 cles `dual_editor.*` traduits | ### Nouvelles dependances requises Aucune. Le converter est custom TypeScript pur. L'editeur markdown utilise une `