refactor(quick-260922-m1h): Widget-Typen an einer Stelle, Katalog aus der Registry, Kachel kennt ihr Modul
Ein neuer Widget-Typ war an sieben Stellen einzutragen; vergass man eine, fehlte die Kachel im Katalog oder die API lehnte sie mit 400 ab. - WIDGET_TYPES/WidgetType/WIDGET_MODULE_SLUGS stehen jetzt einmal in packages/shared; Registry, Katalog und die @IsIn-Whitelist der API leiten davon ab - neun wireXWidget()-Funktionen durch ein generisches registerWidget() ersetzt (idempotent, unbekannter Typ wirft in der Entwicklung) - der Katalog fuehrt keine zweite Typliste mehr, sondern leitet sie aus der Registry ab und filtert nach Modulzugriff (fail-closed, wenn die Modulliste unbekannt ist); der Abruf von /modules/active liegt auf der Dashboard-Seite, nicht im Dialog - widget-module-map.ts liest die geteilte Tabelle statt einer Kopie, die oeffentliche Funktion bleibt unveraendert Der Katalogfilter ist Komfort (T-M1H-01) — verbindlich bleibt der serverseitige Filter in DashboardService.getWidgets. Abweichung vom Plan: apps/web hing entgegen der Planannahme noch nicht von @tessera/shared ab; die Abhaengigkeit wurde ergaenzt (Lockfile). Die Dockerfiles kopieren packages/shared bereits, der Produktionsbau von Next.js und der nest build laufen unveraendert. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import { WIDGET_MODULE_SLUGS } from '@tessera/shared';
|
||||
|
||||
/**
|
||||
* Zuordnung Widget-Typ → Modul (D-22, PERM-07).
|
||||
*
|
||||
@@ -8,24 +10,29 @@
|
||||
* Schlüssel sind Werte von `WidgetInstance.widgetType`, Werte sind
|
||||
* Modul-Slugs aus `Module.slug`.
|
||||
*
|
||||
* quick-260922-m1h: Die Tabelle selbst steht seit diesem Umbau in
|
||||
* `packages/shared/src/index.ts` als `WIDGET_MODULE_SLUGS` — EINE Tabelle
|
||||
* für beide Seiten, damit der Katalogfilter im Web
|
||||
* (`visibleWidgetTypes`, Komfort) und dieser Server-Filter (verbindlich)
|
||||
* nicht auseinanderlaufen. Hier steht nur noch der Lesezugriff; die
|
||||
* öffentliche Schnittstelle dieser Datei bleibt unverändert, weil
|
||||
* dashboard.service.spec.ts sie gezielt mockt.
|
||||
*
|
||||
* Bewusst eine TypeScript-Konstante statt einer Spalte auf
|
||||
* `WidgetInstance`: eine Migration auf einer bereits befüllten Tabelle
|
||||
* für ein Feld, das derzeit für jede Zeile leer wäre, wiegt schwerer als
|
||||
* diese Konstante mit identischer Aussagekraft (15-RESEARCH.md Pitfall 5).
|
||||
*
|
||||
* Die Tabelle ist am Ende dieser Phase bewusst leer: alle sieben heute
|
||||
* registrierten Widget-Typen (clock/search/calendar/note/calculator/
|
||||
* favorites/stopwatch, siehe apps/web/src/components/dashboard/
|
||||
* widget-registry.tsx) sind Plattform-Widgets ohne Modulbezug. Das
|
||||
* einzige bislang geplante modulgebundene Widget steht in
|
||||
* .planning/REQUIREMENTS.md unter "Future Requirements (deferred)" und
|
||||
* wird in dieser Phase bewusst nicht registriert.
|
||||
* Die Tabelle ist bewusst leer: alle neun registrierten Widget-Typen
|
||||
* (clock/search/calendar/note/calculator/favorites/stopwatch/
|
||||
* picture-frame/xframe) sind Plattform-Widgets ohne Modulbezug. Die erste
|
||||
* modulgebundene Kachel trägt ihren Slug in `WIDGET_MODULE_SLUGS` ein.
|
||||
*/
|
||||
export const WIDGET_MODULE_MAP: Readonly<Record<string, string>> = {};
|
||||
export const WIDGET_MODULE_MAP: Readonly<Record<string, string>> = WIDGET_MODULE_SLUGS;
|
||||
|
||||
/**
|
||||
* Liefert den Modul-Slug für einen Widget-Typ, oder `undefined`, wenn
|
||||
* der Typ kein Modul-Widget ist (der heutige Zustand für alle sieben
|
||||
* der Typ kein Modul-Widget ist (der heutige Zustand für alle neun
|
||||
* bestehenden Typen). Einziger Lesezugriff auf die Zuordnungstabelle,
|
||||
* damit Tests sie gezielt mocken können.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user