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:
@@ -76,3 +76,46 @@ export interface DesktopLatestResponse {
|
||||
buildTime: string;
|
||||
files: Partial<Record<DesktopPlatform, DesktopLatestFile>>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dashboard-Kacheln: EINE Typliste fuer Web und API (quick-260922-m1h).
|
||||
*
|
||||
* Vorher stand dieselbe Liste an sieben Stellen (Union-Typ, Constraints,
|
||||
* Registry, Katalog-Liste, `@IsIn`-Whitelist ...). Vergass man eine, fehlte
|
||||
* die Kachel im Katalog oder die API lehnte sie mit 400 ab. Seit m1h leiten
|
||||
* beide Seiten von hier ab: `apps/web/src/components/dashboard/
|
||||
* widget-registry.tsx` (Registry + Katalog) und
|
||||
* `apps/api/src/dashboard/dto/create-widget.dto.ts` (`@IsIn`).
|
||||
*
|
||||
* ACHTUNG: Dies ist der erste LAUFZEIT-Import aus `@tessera/shared` (alle
|
||||
* uebrigen sind `import type`). `packages/shared` liefert rohes TypeScript
|
||||
* (`main: src/index.ts`, kein Bauschritt); die API laedt es im Betrieb ueber
|
||||
* das native Type-Stripping von Node 24. Deshalb darf diese Datei nur
|
||||
* loeschbare Syntax enthalten — keine `enum`, kein `namespace`, keine
|
||||
* Parameter-Eigenschaften.
|
||||
*/
|
||||
export const WIDGET_TYPES = [
|
||||
'clock',
|
||||
'search',
|
||||
'calendar',
|
||||
'note',
|
||||
'calculator',
|
||||
'favorites',
|
||||
'stopwatch',
|
||||
'picture-frame',
|
||||
'xframe',
|
||||
] as const;
|
||||
|
||||
export type WidgetType = (typeof WIDGET_TYPES)[number];
|
||||
|
||||
/**
|
||||
* Kachel → Modul-Slug. Eine Kachel ohne Eintrag ist immer sichtbar; eine
|
||||
* Kachel MIT Eintrag erscheint nur fuer Benutzer, die das Modul nutzen
|
||||
* duerfen — im Katalog (Komfort, `visibleWidgetTypes`) und verbindlich
|
||||
* serverseitig in `DashboardService.getWidgets` (fail-closed).
|
||||
*
|
||||
* Heute bewusst leer: alle neun Kacheln sind Plattform-Kacheln ohne
|
||||
* Modulbezug. Die erste modulgebundene Kachel (Proxmox) traegt hier ihren
|
||||
* Slug ein.
|
||||
*/
|
||||
export const WIDGET_MODULE_SLUGS: Partial<Record<WidgetType, string>> = {};
|
||||
|
||||
Reference in New Issue
Block a user