documentatie
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
# Architectuur van racket-wiki
|
||||
|
||||
Deze documentatieset beschrijft de architectuur van racket-wiki zoals die in versie 0.2.94 bestaat. Zij is tegelijk een wegwijzer voor onderhoud: iedere pagina maakt onderscheid tussen bestaand gedrag, bekende grenzen en regels voor verdere ontwikkeling.
|
||||
Deze documentatieset beschrijft de architectuur van racket-wiki zoals die in versie 0.2.122 bestaat. Zij is tegelijk een wegwijzer voor onderhoud: iedere pagina maakt onderscheid tussen bestaand gedrag, bekende grenzen en regels voor verdere ontwikkeling.
|
||||
|
||||
{{cmap:racket-wiki-architectuur}}
|
||||
|
||||
## Architectuur in één alinea
|
||||
|
||||
racket-wiki is een kleine, zelf gehoste webapplicatie. Eén Racket-proces levert de HTTP-server, authenticatie, autorisatie, setup, databaseaanroepen en statische bestanden. PostgreSQL bevat de duurzame toestand: gebruikers, sessies, pagina's, onveranderlijke paginaversies, conceptmaps, CMap-versies, bijlagen en beheerinstellingen. De browser bevat de interactieve applicatie, Markdown-editor en CMap-editor. De grens tussen browser en backend is een JSON/HTTP-API. Normaal gebruik vereist geen externe CDN of afzonderlijke applicatieservice.
|
||||
racket-wiki is een kleine, zelf gehoste webapplicatie. Eén Racket-proces levert de HTTP-server, authenticatie, autorisatie, setup, databaseaanroepen en statische bestanden. PostgreSQL bevat de duurzame toestand: gebruikers, sessies, pagina's, onveranderlijke paginaversies, conceptmaps, CMap-versies, gedeelde conceptdefinities, opgeslagen SVG-weergaven, bijlagen en beheerinstellingen. De browser bevat de interactieve applicatie, Markdown-editor en modulaire CMap-editor. De grens tussen browser en backend is een JSON/HTTP-API. Normaal gebruik vereist geen externe CDN of afzonderlijke applicatieservice.
|
||||
|
||||
## Leeswijzer
|
||||
|
||||
@@ -37,11 +37,13 @@ De huidige vorm rust op een klein aantal bewuste keuzes:
|
||||
5. Markdown wordt in de browser gerenderd en daarna met DOMPurify gesaneerd.
|
||||
6. Browserbibliotheken worden tijdens setup vastgepind en lokaal geserveerd.
|
||||
7. Pagina-adressen bestaan uit een namespace en stabiele slug. Deze set gebruikt de namespace `racket-wiki`.
|
||||
8. Conceptmaps blijven native CMap-documenten. `{{cmap:...}}` sluit een read-only weergave in Markdown in zonder het CMap-formaat tot Mermaid te reduceren.
|
||||
8. Conceptmaps blijven native CMap-documenten. `{{cmap:...}}` sluit een opgeslagen SVG-weergave als linkbare afbeelding in Markdown in zonder het CMap-formaat tot Mermaid te reduceren.
|
||||
9. CMap-structuur, gedeelde conceptinhoud en afgeleide SVG-weergave hebben afzonderlijke opslagcontracten. De SVG is geen onderdeel van het bewerkbare CMap-JSON-document.
|
||||
10. De CMap-editor gebruikt native ES-modules met expliciete model-, controller-, view- en workspacegrenzen. De workspace coördineert alleen editorcallbacks, dialogen en DOM-events.
|
||||
|
||||
## Kwaliteitsbeeld
|
||||
|
||||
De architectuur past goed bij een persoonlijke of teamwiki: weinig processen, een duidelijke databasebron en volledige historie. De sterkste punten zijn de transactionele inhoudsopslag, eenvoudige deployment en lokale frontend-assets. De voornaamste ontwikkelpunten zijn de omvang van `server.rkt` en `static/js/wiki.js`, het ontbreken van een volwaardige geautomatiseerde testsuite en een nieuwe databaseverbinding per opslagbewerking.
|
||||
De architectuur past goed bij een persoonlijke of teamwiki: weinig processen, een duidelijke databasebron en volledige historie. De sterkste punten zijn de transactionele inhoudsopslag, eenvoudige deployment, lokale frontend-assets en de afgebakende CMap-editor. De voornaamste ontwikkelpunten zijn de omvang van `server.rkt` en `static/js/wiki.js`, beperkte backend- en browsertestdekking en een nieuwe databaseverbinding per opslagbewerking.
|
||||
|
||||
Deze punten zijn geen reden voor een voorafgaande grote herbouw. De ontwikkelregel is: meet eerst, isoleer het concrete probleem en splits een module wanneer een wijziging daar aantoonbaar eenvoudiger of beter testbaar door wordt.
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ De database bevat zowel de huidige toestand als de auditgeschiedenis. De browser
|
||||
| `attachment_references` | Huidige en historische verwijzingen vanuit paginaversies |
|
||||
| `concept_maps` | Actuele titel, JSONB-document en versieteller per CMap |
|
||||
| `concept_map_versions` | Expliciete CMap-snapshots en maximaal vijf handmatige opslagversies per CMap |
|
||||
| `cmap_renders` | Opgeslagen SVG-weergave per CMap en documentversie, voor Markdown-embeds |
|
||||
| `concept_definitions` | Wiki-brede inhoud per stabiele `conceptId`; plaatsing en opmaak blijven in het CMap-document |
|
||||
| `people` | Wiki-breed register van actieve en inactieve namen voor getypeerde persoonstags |
|
||||
| `password_reset_tokens` | Gehashte, tijdelijke en eenmalige herstelcodes |
|
||||
@@ -41,7 +42,7 @@ Een paginaopslag is één atomaire transactie:
|
||||
6. Vervang huidige bijlageverwijzingen en leg historische verwijzingen voor de nieuwe versie vast.
|
||||
7. Commit alles, of niets.
|
||||
|
||||
Een CMap-opslag volgt voor de actuele projectie hetzelfde kernpatroon: rij vergrendelen, versienummer vergelijken en actuele JSONB bijwerken. In dezelfde transactie worden de aangeleverde inhoudelijke velden op `conceptId` in `concept_definitions` gezet. Een `conceptId` is een kale, lowercase en globaal unieke UUID; hij bevat bewust geen CMap-slug. De getrimde, hoofdletterongevoelige conceptnaam is wiki-breed uniek; een tweede plaatsing met dezelfde naam krijgt direct de bestaande id. Het opgeslagen CMap-document bevat zelf geen inhoudelijke kopie: `items[]` bewaart alleen structuur en opmaak en `concepts[]` bevat uitsluitend `{id}`-verwijzingen. `concept_definitions` is de enige persistente bron voor naam, samenvatting, aspecten, personen, koppelingen, afbeelding en toelichtingspagina. Bij uitlezen hydrateert de server die verwijzingen voor de editor. Ieder item behalve een verbindingszin is een plaatsing van een concept; `submap`, `page` en `concept` zijn lokale structurele rollen en geen afzonderlijke conceptsoorten. Positie, afmetingen, kleuren, typografie en structurele rol kunnen per plaatsing verschillen. De CMap zelf houdt haar stabiele, leesbare `concept_maps.slug`; die slug identificeert de kaart en staat los van de concept-UUID's. Autosave verhoogt wel het optimistische versienummer, maar maakt geen historieregel. Een expliciete opslag voegt een volledige toestand aan `concept_map_versions` toe en verwijdert oudere handmatige versies boven de grens van vijf. Benoemde snapshots vallen niet onder die grens.
|
||||
Een CMap-opslag volgt voor de actuele projectie hetzelfde kernpatroon: rij vergrendelen, versienummer vergelijken en actuele JSONB bijwerken. In dezelfde transactie worden de aangeleverde inhoudelijke velden op `conceptId` in `concept_definitions` gezet en wordt, wanneer de browser een render aanlevert, de SVG in `cmap_renders` bij dezelfde documentversie geschreven. Een `conceptId` is een kale, lowercase en globaal unieke UUID; hij bevat bewust geen CMap-slug. De getrimde, hoofdletterongevoelige conceptnaam is wiki-breed uniek; een tweede plaatsing met dezelfde naam krijgt direct de bestaande id. Het opgeslagen CMap-document bevat zelf geen inhoudelijke kopie: `items[]` bewaart alleen structuur en opmaak en `concepts[]` bevat uitsluitend `{id}`-verwijzingen. `concept_definitions` is de enige persistente bron voor naam, samenvatting, aspecten, personen, koppelingen, afbeelding en toelichtingspagina. Bij uitlezen hydrateert de server die verwijzingen voor de editor. Ieder item behalve een verbindingszin is een plaatsing van een concept; `submap`, `page` en `concept` zijn lokale structurele rollen en geen afzonderlijke conceptsoorten. Positie, afmetingen, kleuren, typografie en structurele rol kunnen per plaatsing verschillen. De CMap zelf houdt haar stabiele, leesbare `concept_maps.slug`; die slug identificeert de kaart en staat los van de concept-UUID's. Autosave verhoogt wel het optimistische versienummer, maar maakt geen historieregel. Een expliciete opslag voegt een volledige toestand aan `concept_map_versions` toe en verwijdert oudere handmatige versies boven de grens van vijf. Benoemde snapshots vallen niet onder die grens.
|
||||
|
||||
## Waarom volledige snapshots
|
||||
|
||||
@@ -83,6 +84,7 @@ De volgende regels mogen niet alleen in de browser staan:
|
||||
|
||||
- iedere actuele paginaversie heeft een overeenkomstige onveranderlijke snapshot;
|
||||
- CMap-autosave wijzigt alleen de actuele projectie; CMap-historie bevat alleen snapshots en maximaal vijf handmatige versies;
|
||||
- een SVG-render hoort bij een concrete CMap-documentversie, maar is geen veld van het CMap-JSON-document;
|
||||
- alle actuele plaatsingen met dezelfde `conceptId` lezen hun inhoud uit dezelfde `concept_definitions`-rij;
|
||||
- iedere actuele `conceptId` is een kale lowercase UUID; de CMap-slug blijft afzonderlijk bewaard;
|
||||
- versienummers nemen per object strikt toe;
|
||||
|
||||
@@ -6,7 +6,7 @@ De backend is functioneel opgesplitst. Configuratie, databaseverbinding, migrati
|
||||
|
||||
De belangrijkste grens is die tussen `server.rkt` en de opslagmodules. `server.rkt` hoort HTTP te begrijpen; `storage.rkt`, `cmap-storage.rkt` en `auth.rkt` horen domeinbewerkingen en database-invarianten te begrijpen. Geen opslagprocedure mag een webrequest nodig hebben.
|
||||
|
||||
De frontend heeft een vergelijkbare grens. `cmap-racket-wiki.js` implementeert een editorcomponent met callbacks voor openen, selectie en wijzigingen. `wiki.js` koppelt die callbacks aan routes, API's en dialoogvensters. Zuivere referentie-, route-, Markdown- en outlinebewerkingen staan in eigen modules; `BreadcrumbTrail` beheert uitsluitend de per-tab paginahistorie en kent de DOM niet. `routes.js` herkent hashes, terwijl `wiki.js` eigenaar blijft van permissiecontrole en het openen van views. De concrete controllers onder `static/js/wiki/admin/` beheren hun eigen formulier- of lijstinteractie. Zij ontvangen alleen de bestaande API- en vertaalfuncties en, wanneer de gewone catalogus werkelijk verandert, één gerichte herlaadfunctie.
|
||||
De frontend heeft een vergelijkbare grens. `cmap-racket-wiki.js` is een dunne editorfacade met callbacks voor openen, selectie en wijzigingen; hij composeert gespecialiseerde document-, geometrie-, relatie-, layout-, selectie-, interactie- en submapcontrollers. Onder `static/js/wiki/cmap/` koppelt `CmapWorkspaceController` die editor aan routes, API's, dialogen en DOM-events. `CmapStorageController` beheert dirty state, autosave en de opslagvolgorde; `CmapNavigationController` beheert routes en browsercontext; `CmapTransferController` beheert import en export; `CmapEditorHost` beheert editorlifecycle; `CmapEditorUiController` beheert standaard toolbaracties; `CmapMapController` beheert opgeslagen kaarten en `CmapConceptController` beheert conceptdialogen en geselecteerde conceptbewerkingen. Zuivere referentie-, route-, Markdown- en outlinebewerkingen staan in eigen modules; `BreadcrumbTrail` beheert uitsluitend de per-tab paginahistorie en kent de DOM niet. `routes.js` herkent hashes, terwijl `wiki.js` eigenaar blijft van permissiecontrole en het openen van views.
|
||||
|
||||
## Sterke punten
|
||||
|
||||
@@ -22,7 +22,7 @@ De volgende onderdelen zijn al goed geïsoleerd:
|
||||
|
||||
## Huidige concentraties
|
||||
|
||||
`server.rkt` bevat zowel routing als veel requestparsing en handlerlogica. `static/js/wiki.js` bevat vrijwel de hele single-page applicatie. Dat maakt zoeken eenvoudig, maar vergroot de kans dat een wijziging onverwacht een ander view- of routepad raakt.
|
||||
`server.rkt` bevat zowel routing als veel requestparsing en handlerlogica. `static/js/wiki.js` bevat nog steeds de brede single-page applicatie. De CMap-workspace is daarbinnen echter opgesplitst in eigen modules, waardoor CMap-wijzigingen niet meer in één grote editor- of workspaceklasse samenkomen.
|
||||
|
||||
`private/storage.rkt` combineert pagina's, historie, zoeken, bookmarks, aliases en uploads. Die onderdelen delen pagina-identiteit en transacties, maar hoeven niet onbeperkt samen te groeien.
|
||||
|
||||
@@ -42,7 +42,7 @@ Deze concentraties zijn technische schuld, geen automatische opdracht tot een gr
|
||||
|
||||
Wanneer `server.rkt` verder groeit, ligt opsplitsing per adaptergebied voor de hand: sessie/profiel, pagina's, CMaps en beheer. De centrale router kan dan dun blijven. Handlers ontvangen `config` expliciet en roepen dezelfde bestaande diensten aan.
|
||||
|
||||
Wanneer `wiki.js` verder groeit, zijn route/state, pagina-editor, CMap-host en admin-views natuurlijke grenzen. Splits alleen met native ES-modules wanneer de setup- en cacheversies van alle scripts tegelijk beheerst worden.
|
||||
Wanneer `wiki.js` verder groeit, zijn route/state, pagina-editor en admin-views natuurlijke grenzen. De CMap-host is al als native ES-modulelaag gescheiden. Houd de workspace als coördinator; extra extracties zijn alleen zinvol bij een nieuwe zelfstandige workflow, niet voor losse DOM-hulpen.
|
||||
|
||||
Wanneer paginaopslag wordt aangepast, kunnen bookmarks, aliases en uploads later eigen modules krijgen. De pagina-schrijftransactie en afgeleide indices moeten daarbij als één consistente operatie behouden blijven; opsplitsing van bestanden mag geen opsplitsing van de transactie veroorzaken.
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ De map `private/` bevat de backendonderdelen:
|
||||
| `migrations.rkt` | Opeenvolgende, transactionele schemasprongen |
|
||||
| `auth.rkt` | Gebruikers, wachtwoorden, rollen, sessies, CSRF en herstelcodes |
|
||||
| `storage.rkt` | Pagina's, historie, zoeken, bookmarks, uploads en aliases |
|
||||
| `cmap-storage.rkt` | Conceptmaps en onveranderlijke CMap-versies |
|
||||
| `cmap-storage.rkt` | Conceptmaps, gedeelde conceptdefinities, onveranderlijke CMap-versies en opgeslagen SVG-weergaven |
|
||||
| `attachment-references.rkt` | Huidige en historische verwijzingen naar bijlagen |
|
||||
| `todo.rkt` | Herkennen van wiki-brede `todo(...)`-markeringen |
|
||||
| `mail.rkt` | SMTP-instellingen, STARTTLS, testmail en herstelmail |
|
||||
@@ -38,7 +38,9 @@ De map `private/` bevat de backendonderdelen:
|
||||
|
||||
`translate.rkt` staat bewust aan de publieke rand: zowel backend als frontend gebruiken dezelfde effectieve vertaaltabel.
|
||||
|
||||
De map `static/` bevat de browserapplicatie. `static/index.html` definieert de views en dialogen. `static/js/wiki.js` beheert routedispatch, API-aanroepen, editor- en paginatoestand en speciale views. De modules onder `static/js/wiki/` bevatten afzonderlijk de referentiesyntaxis, routeherkenning, Markdowntransformaties, paginakoppen en breadcrumbhistorie. De controllers onder `static/js/wiki/admin/` beheren ieder één administratief formulier of overzicht; routes, permissiecontrole, breadcrumbs en algemene adminnavigatie blijven in `wiki.js`. `static/js/cmap/cmap.js` levert de grafische basis; `cmap-racket-wiki.js` voegt wiki-items, selectie, relaties, sub-CMaps, historie en documentserialisatie toe. `combobox.js` is een herbruikbaar klein UI-onderdeel. CSS is verdeeld tussen algemene wiki-opmaak en CMap-opmaak.
|
||||
De map `static/` bevat de browserapplicatie. `static/index.html` definieert de views en dialogen. `static/js/wiki.js` beheert routedispatch, API-aanroepen, editor- en paginatoestand en speciale views. De modules onder `static/js/wiki/` bevatten afzonderlijk de referentiesyntaxis, routeherkenning, Markdowntransformaties, paginakoppen en breadcrumbhistorie. De controllers onder `static/js/wiki/admin/` beheren ieder één administratief formulier of overzicht; routes, permissiecontrole, breadcrumbs en algemene adminnavigatie blijven in `wiki.js`.
|
||||
|
||||
De generieke CMap-component staat onder `static/js/cmap/`. `cmap.js` levert de tekenengine. `cmap-racket-wiki.js` is de wiki-editorfacade en composeert document-, geometrie-, relatie-, layout-, selectie-, interactie- en submapcontrollers. De views voor itemdecoratie, grensverwijzingen en SVG-snapshots houden presentatie buiten het model. De wiki-specifieke hostlaag staat onder `static/js/wiki/cmap/`: `CmapWorkspaceController` bouwt afhankelijkheden en registreert DOM-events; `CmapEditorHost`, `CmapEditorUiController`, `CmapStorageController`, `CmapNavigationController`, `CmapTransferController`, `CmapMapController` en `CmapConceptController` bezitten ieder hun eigen workflow. `CmapEmbedView` toont opgeslagen SVG-renders in Markdown en `CmapEditorPresentation` levert editorpresentatie en gebruikstellingen. CSS is verdeeld tussen algemene wiki-opmaak en CMap-opmaak.
|
||||
|
||||
## Afhankelijkheidsrichting
|
||||
|
||||
@@ -56,7 +58,7 @@ Deze richting houdt de belangrijkste domeinregels buiten de UI. Een rolcontrole
|
||||
|
||||
Een pagina heeft een database-id, namespace, slug, actuele Markdown en een versieteller. `page_versions` verwijst naar dezelfde pagina-id. Todo's, bookmarks, aliases en bijlageverwijzingen sluiten via die id aan.
|
||||
|
||||
Een CMap heeft een stabiele slug, titel, JSONB-document en versieteller. `concept_map_versions` bewaart volledige JSONB-snapshots. CMap-items kunnen via `pageSlug` naar een wikipagina verwijzen en via `cmapSlug` naar een andere CMap. De browser gebruikt deze verwijzingen om het gekoppelde doel rechtstreeks te openen.
|
||||
Een CMap heeft een stabiele slug, titel, JSONB-document en versieteller. `concept_map_versions` bewaart volledige JSONB-snapshots; `cmap_renders` bewaart de actuele SVG-weergave per documentversie apart. CMap-items kunnen via `pageSlug` naar een wikipagina verwijzen en via `cmapSlug` naar een andere CMap. De browser gebruikt deze verwijzingen om het gekoppelde doel rechtstreeks te openen.
|
||||
|
||||
Zie [Data, transacties en versiebeheer](racket-wiki:data-en-versies) voor de invarianten en [Modulariteit en afhankelijkheden](racket-wiki:modulariteit) voor de gewenste grenzen bij uitbreiding.
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ De backendfuncties zijn meestal procedureel en krijgen `config` expliciet mee. D
|
||||
|
||||
Versie 0.2.93 introduceert wel tests in `architecture/import.rkt`. Die controleren de manifestset, interne paginalinks, CMap-embeds, unieke node-id's, connector-endpoints en de bronmarkeringen waarmee lokaal gewijzigde importinhoud wordt beschermd. Dit is een begin, geen voldoende dekking van de wiki.
|
||||
|
||||
Versie 0.2.100 voegt pure Node-tests toe voor de Markdown-export: dieptebegrenzing, cycli, optionele wikipagina's, persoonstags, leesbare relaties en afgeleide sub-CMapweergaven. De extractie van persoonsnamen uit CMap-documenten heeft daarnaast een kleine RackUnit-test; database- en browsergedrag blijven integratietestwerk.
|
||||
De Node-suite bevat 83 tests voor het CMap-model, repositorycontracten, import/export, connectorherbedrading, selectie-layout, lagen, historie, submapnavigatie, instellingen en Markdown-transformaties. De tests draaien zonder bundler met `node --test test/*.test.js test/*.test.mjs`. Database- en volledig browsergedrag blijven integratietestwerk.
|
||||
|
||||
Versie 0.2.115 voegt pure roundtrip- en validatietests toe voor het JSON-uitwisselingsformaat. Zij controleren dat coördinaten, afmetingen, kleuren, typografie, groepering en connectoren in de diagramlaag blijven, dat gedeelde conceptinhoud apart wordt opgeslagen en bij import wordt teruggekoppeld, en dat losse concepten, dubbele namen/slugs en ongeldige connector-endpoints worden geweigerd.
|
||||
|
||||
@@ -51,6 +51,8 @@ Introduceer geen groot mockframework. Gewone procedures en expliciete parameters
|
||||
|
||||
Voor frontendcode zijn browsercomponenttests met een echte DOM geschikter dan het namaken van ieder element. De CMap-adapter moet met een klein vast document getest kunnen worden zonder de hele wiki te starten.
|
||||
|
||||
De CMap-controllers zijn bewust via kleine constructorcontracten te testen. Nieuwe gedragstests horen primair bij de eigenaar: documentwijzigingen bij de editorcontrollers, autosave en conflicten bij `CmapStorageController`, routecontext bij `CmapNavigationController`, kaartworkflows bij `CmapMapController` en conceptdialogen, selectie en namespace-migratie bij `CmapConceptController`. Een workspace-test is alleen nodig voor de koppeling van deze grenzen of voor een daadwerkelijk DOM-gebaseerde gebruikersflow.
|
||||
|
||||
De JavaScript-regressietest `test/cmap-connector-rewire.test.js` simuleert het verslepen van een
|
||||
connector naar een andere verbindingszin, klapt de submap in en uit en controleert daarna zowel de
|
||||
tekenlaag als de geserialiseerde `sourceId`.
|
||||
|
||||
Reference in New Issue
Block a user