Spaces:
Paused
Paused
| /** | |
| * Widget Registry | |
| * | |
| * Central registry der håndterer widget discovery, queries og relationship management. | |
| * Gør det muligt for widgets at finde hinanden og etablere dataflow. | |
| */ | |
| import { | |
| WidgetMetadata, | |
| WidgetQuery, | |
| WidgetRegistry, | |
| DataType, | |
| securityWidgetSchemas, | |
| calendarScheduleWidgetSchemas | |
| } from '@/types/WidgetSchema'; | |
| class WidgetRegistryImpl implements WidgetRegistry { | |
| widgets: Map<string, WidgetMetadata> = new Map(); | |
| constructor() { | |
| // Initialize with security widget schemas | |
| Object.values(securityWidgetSchemas).forEach(widget => { | |
| this.register(widget); | |
| }); | |
| // Initialize with calendar/schedule widget schemas | |
| Object.values(calendarScheduleWidgetSchemas).forEach(widget => { | |
| this.register(widget); | |
| }); | |
| } | |
| register(widget: WidgetMetadata): void { | |
| this.widgets.set(widget.id, widget); | |
| } | |
| unregister(widgetId: string): void { | |
| this.widgets.delete(widgetId); | |
| } | |
| get(widgetId: string): WidgetMetadata | undefined { | |
| return this.widgets.get(widgetId); | |
| } | |
| // Find widgets that provide a specific data type | |
| findByCapability(type: DataType): WidgetMetadata[] { | |
| return Array.from(this.widgets.values()).filter(widget => | |
| widget.provides.some(cap => cap.outputType === type) | |
| ); | |
| } | |
| // Find widgets that require a specific data type | |
| findByRequirement(type: DataType): WidgetMetadata[] { | |
| return Array.from(this.widgets.values()).filter(widget => | |
| widget.requires.some(req => req.type === type) | |
| ); | |
| } | |
| // Find widgets that can connect to a given widget | |
| findCompatible(widgetId: string): WidgetMetadata[] { | |
| const widget = this.widgets.get(widgetId); | |
| if (!widget) return []; | |
| const compatible: Set<WidgetMetadata> = new Set(); | |
| // Find widgets that can provide what this widget requires | |
| widget.requires.forEach(req => { | |
| this.findByCapability(req.type).forEach(provider => { | |
| if (provider.id !== widgetId) { | |
| compatible.add(provider); | |
| } | |
| }); | |
| }); | |
| // Find widgets that require what this widget provides | |
| widget.provides.forEach(cap => { | |
| this.findByRequirement(cap.outputType).forEach(consumer => { | |
| if (consumer.id !== widgetId) { | |
| compatible.add(consumer); | |
| } | |
| }); | |
| }); | |
| return Array.from(compatible); | |
| } | |
| // Advanced query for widget discovery | |
| query(query: WidgetQuery): WidgetMetadata[] { | |
| return Array.from(this.widgets.values()).filter(widget => { | |
| // Filter by provided type | |
| if (query.providesType && | |
| !widget.provides.some(cap => cap.outputType === query.providesType)) { | |
| return false; | |
| } | |
| // Filter by specific capability | |
| if (query.providesCapability && | |
| !widget.provides.some(cap => cap.id === query.providesCapability)) { | |
| return false; | |
| } | |
| // Filter by required type | |
| if (query.requiresType && | |
| !widget.requires.some(req => req.type === query.requiresType)) { | |
| return false; | |
| } | |
| // Filter by required source | |
| if (query.requiresSource && | |
| !widget.requires.some(req => req.source === query.requiresSource)) { | |
| return false; | |
| } | |
| // Filter by category | |
| if (query.category && widget.category !== query.category) { | |
| return false; | |
| } | |
| // Filter by tags | |
| if (query.tags && !query.tags.some(tag => widget.tags.includes(tag))) { | |
| return false; | |
| } | |
| // Filter by priority | |
| if (query.priority && widget.priority !== query.priority) { | |
| return false; | |
| } | |
| return true; | |
| }); | |
| } | |
| // Get widgets that provide data to the given widget | |
| getProviders(widgetId: string): WidgetMetadata[] { | |
| const widget = this.widgets.get(widgetId); | |
| if (!widget) return []; | |
| return widget.relations | |
| .filter(rel => rel.type === 'depends_on') | |
| .map(rel => this.widgets.get(rel.targetWidgetId)) | |
| .filter((w): w is WidgetMetadata => w !== undefined); | |
| } | |
| // Get widgets that consume data from the given widget | |
| getConsumers(widgetId: string): WidgetMetadata[] { | |
| const widget = this.widgets.get(widgetId); | |
| if (!widget) return []; | |
| return widget.relations | |
| .filter(rel => rel.type === 'provides_to') | |
| .map(rel => this.widgets.get(rel.targetWidgetId)) | |
| .filter((w): w is WidgetMetadata => w !== undefined); | |
| } | |
| // Build complete dependency graph | |
| getDependencyGraph(): Map<string, string[]> { | |
| const graph = new Map<string, string[]>(); | |
| this.widgets.forEach((widget, id) => { | |
| const dependencies = widget.relations | |
| .filter(rel => rel.type === 'depends_on') | |
| .map(rel => rel.targetWidgetId); | |
| graph.set(id, dependencies); | |
| }); | |
| return graph; | |
| } | |
| // Get widget's introduction/description for ecosystem | |
| describeWidget(widgetId: string): string { | |
| const widget = this.widgets.get(widgetId); | |
| if (!widget) return 'Widget ikke fundet'; | |
| const requires = widget.requires.map(r => ` - ${r.name} (${r.type}): ${r.description}`).join('\n'); | |
| const provides = widget.provides.map(p => ` - ${p.name} (${p.outputType}): ${p.description}`).join('\n'); | |
| const configs = widget.config.map(c => ` - ${c.name}: ${c.description}`).join('\n'); | |
| return ` | |
| ## ${widget.name} (v${widget.version}) | |
| ${widget.description} | |
| **Kategori:** ${widget.category} | |
| **Tags:** ${widget.tags.join(', ')} | |
| **Prioritet:** ${widget.priority || 'medium'} | |
| ### Kræver Data: | |
| ${requires || ' Ingen data-afhængigheder'} | |
| ### Leverer Data: | |
| ${provides || ' Ingen outputs'} | |
| ### Konfiguration: | |
| ${configs || ' Ingen konfigurerbare indstillinger'} | |
| ${widget.documentation ? `### Dokumentation:\n${widget.documentation}` : ''} | |
| `.trim(); | |
| } | |
| // Export registry state for persistence or debugging | |
| export(): Record<string, WidgetMetadata> { | |
| const result: Record<string, WidgetMetadata> = {}; | |
| this.widgets.forEach((widget, id) => { | |
| result[id] = widget; | |
| }); | |
| return result; | |
| } | |
| } | |
| // Singleton instance | |
| export const widgetRegistry = new WidgetRegistryImpl(); | |
| // React hook for widget discovery | |
| export function useWidgetRegistry() { | |
| return widgetRegistry; | |
| } | |