mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 23:01:09 +02:00
Move inactive projects out of active workspace: - bauntown (community website) - maerchenzauber (AI story generation) - memoro (voice memo app) - news (news aggregation) - nutriphi (nutrition tracking) - reader (reading app) - uload (URL shortener) - wisekeep (AI wisdom extraction) Update CLAUDE.md documentation: - Add presi to active projects - Document archived projects section - Update workspace configuration Archived apps can be re-activated by moving back to apps/ 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
8.7 KiB
8.7 KiB
Database Refactoring Plan - Card System
Aktuelle Problematik
Derzeit existieren 3 separate Collections für Cards:
cards- Allgemeine Cardsuser_cards- User-spezifische Cardscard_templates- Vordefinierte Templates
Dies führt zu:
- Redundanz in der Datenhaltung
- Komplexität bei Queries
- Inkonsistenzen zwischen Collections
- Wartungsprobleme bei Schema-Änderungen
Vorschlag 1: Unified Cards Collection (Empfohlen) ✅
Schema Design
{
collection: "cards",
type: "base",
schema: {
// Core Fields
id: "auto",
user_id: "relation:users", // null für System-Templates
// Card Type & Origin
type: "select", // "user" | "template" | "system"
source: "select", // "created" | "duplicated" | "imported"
template_id: "relation:cards", // Verweis auf Original-Template
// Card Configuration (Vereinheitlicht!)
config: "json", // Discriminated Union: {mode, ...config}
metadata: "json", // Name, description, tags, etc.
constraints: "json", // aspectRatio, limits, etc.
// Organization
page: "text", // Für User-Cards: welche Seite
position: "number", // Sortierung
folder_id: "relation:folders", // Optional: Ordner-Zuordnung
// Visibility & Sharing
visibility: "select", // "private" | "public" | "unlisted"
is_featured: "bool", // Für Template-Store
allow_duplication: "bool", // Kann als Template verwendet werden
// Statistics
usage_count: "number", // Wie oft als Template verwendet
likes_count: "number", // Für Template-Store
// Timestamps
created: "autodate",
updated: "autodate"
},
indexes: [
"user_id",
"type",
"page",
"visibility",
"template_id"
],
rules: {
list: "@request.auth.id = user_id || visibility = 'public'",
view: "@request.auth.id = user_id || visibility != 'private'",
create: "@request.auth.id != ''",
update: "@request.auth.id = user_id",
delete: "@request.auth.id = user_id && type != 'system'"
}
}
Vorteile
- Eine Quelle der Wahrheit - Alle Cards in einer Collection
- Flexibilität - User-Cards können zu Templates werden
- Einfache Queries - Keine JOINs zwischen Collections
- Konsistenz - Gleiches Schema für alle Card-Typen
- Performance - Bessere Indizierung möglich
Migration Strategy
// 1. Neue Collection erstellen
await createUnifiedCardsCollection();
// 2. Daten migrieren
await migrateUserCards(); // user_cards → cards (type: "user")
await migrateTemplates(); // card_templates → cards (type: "template")
await migrateSystemCards(); // cards → cards (vereinheitlichen)
// 3. Alte Collections archivieren
await archiveOldCollections();
Vorschlag 2: Optimierte Separate Collections
Falls eine Trennung gewünscht ist, dann mit klarer Hierarchie:
// 1. card_definitions - Alle Card-Definitionen
{
collection: "card_definitions",
fields: [
{ name: "config", type: "json" }, // Card-Konfiguration
{ name: "metadata", type: "json" }, // Meta-Informationen
{ name: "constraints", type: "json" }, // Beschränkungen
{ name: "checksum", type: "text" } // Für Deduplizierung
]
}
// 2. card_instances - Konkrete Verwendungen
{
collection: "card_instances",
fields: [
{ name: "definition_id", type: "relation:card_definitions" },
{ name: "user_id", type: "relation:users" },
{ name: "type", type: "select" }, // "personal" | "template"
{ name: "overrides", type: "json" }, // Lokale Anpassungen
{ name: "page", type: "text" },
{ name: "position", type: "number" }
]
}
Vorschlag 3: Hybrid-Ansatz mit Smart References
// Haupttabelle für aktive Cards
{
collection: "cards",
fields: [
{ name: "user_id", type: "relation" },
{ name: "data", type: "json" }, // Komplette Card-Daten
{ name: "template_ref", type: "text" }, // Optional: Template-ID
{ name: "is_template", type: "bool" }, // Kann als Template genutzt werden
{ name: "cache_key", type: "text" } // Für Caching
]
}
// Separate Template-Registry
{
collection: "template_registry",
fields: [
{ name: "card_id", type: "relation:cards" },
{ name: "category", type: "select" },
{ name: "tags", type: "json" },
{ name: "featured", type: "bool" },
{ name: "stats", type: "json" }
]
}
Empfohlene Implementierung
Phase 1: Schema-Vereinfachung (1-2 Tage)
// Neue unified cards collection
const unifiedCardSchema = {
// User & System Fields kombiniert
user_id: { type: 'relation', required: false }, // null = System-Template
type: { type: 'select', options: ['user', 'template', 'system'] },
// Vereinheitlichte Datenstruktur
data: {
type: 'json',
schema: {
config: CardConfig, // Discriminated Union
metadata: CardMetadata,
constraints: CardConstraints
}
},
// Gemeinsame Features
visibility: { type: 'select', default: 'private' },
tags: { type: 'json', default: [] },
stats: { type: 'json', default: {} }
};
Phase 2: Service-Layer Anpassung (1 Tag)
class UnifiedCardService {
// Vereinfachte API
async getCard(id: string): Promise<Card> {
const record = await pb.collection('cards').getOne(id);
return this.parseCard(record);
}
async getUserCards(userId: string): Promise<Card[]> {
return pb.collection('cards').getList({
filter: `user_id = "${userId}" && type = "user"`
});
}
async getTemplates(category?: string): Promise<Card[]> {
return pb.collection('cards').getList({
filter: `type = "template" && visibility = "public"`
});
}
async createFromTemplate(templateId: string): Promise<Card> {
const template = await this.getCard(templateId);
return this.createCard({
...template,
type: 'user',
template_id: templateId,
user_id: pb.authStore.model?.id
});
}
}
Phase 3: Migration (1-2 Tage)
// Migrations-Script
async function migrateToUnifiedCards() {
// 1. Backup erstellen
await backupDatabase();
// 2. User Cards migrieren
const userCards = await pb.collection('user_cards').getFullList();
for (const card of userCards) {
await pb.collection('cards').create({
user_id: card.user_id,
type: 'user',
data: {
config: card.config || card.modules,
metadata: card.metadata,
constraints: card.constraints
},
page: card.page,
position: card.position
});
}
// 3. Templates migrieren
const templates = await pb.collection('card_templates').getFullList();
for (const template of templates) {
await pb.collection('cards').create({
user_id: null,
type: 'template',
data: {
config: template.config,
metadata: {
name: template.name,
description: template.description,
category: template.category
}
},
visibility: 'public',
is_featured: template.featured
});
}
// 4. Alte Collections deaktivieren
await archiveCollection('user_cards');
await archiveCollection('card_templates');
}
Vorteile der Vereinheitlichung
1. Weniger Komplexität
- Eine Collection statt drei
- Einheitliches Schema
- Einfachere Queries
2. Bessere Performance
- Weniger JOINs
- Effizientere Indizes
- Besseres Caching
3. Flexibilität
- User-Cards können Templates werden
- Templates können personalisiert werden
- Einfaches Sharing
4. Wartbarkeit
- Ein Schema zu pflegen
- Konsistente Validierung
- Einfachere Backups
Risiken & Mitigation
| Risiko | Mitigation |
|---|---|
| Datenverlust bei Migration | Vollständiges Backup, Staging-Test |
| Performance bei großen Datenmengen | Indizes optimieren, Pagination |
| Breaking Changes in API | Compatibility Layer während Übergang |
| Komplexere Permissions | Rule-based Access Control |
Zeitplan
- Woche 1: Schema-Design finalisieren, Tests schreiben
- Woche 2: Migration implementieren, Staging-Test
- Woche 3: Production-Migration, Monitoring
- Woche 4: Alte Collections entfernen, Cleanup
Metriken für Erfolg
- ✅ Reduzierung der Datenbankgröße um ~20%
- ✅ Query-Performance Verbesserung um ~30%
- ✅ Weniger Code (-40% in Services)
- ✅ Einfachere API für Frontend
- ✅ Bessere Testbarkeit
Fazit
Empfehlung: Vorschlag 1 - Unified Cards Collection
Dies bietet die beste Balance aus:
- Einfachheit
- Performance
- Flexibilität
- Zukunftssicherheit
Die Migration ist überschaubar und die Vorteile überwiegen deutlich die einmaligen Migrationskosten.