/** * Configuration diff viewer. * * Shows what changed in configuration before saving. */ const ConfigDiffViewer = { /** * Original configuration state (before changes). */ originalConfigs: new Map(), /** * Store original configuration for a plugin. * * @param {string} pluginId - Plugin identifier * @param {Object} config - Original configuration */ storeOriginal(pluginId, config) { this.originalConfigs.set(pluginId, JSON.parse(JSON.stringify(config))); }, /** * Get original configuration for a plugin. * * @param {string} pluginId - Plugin identifier * @returns {Object|null} Original configuration */ getOriginal(pluginId) { return this.originalConfigs.get(pluginId) || null; }, /** * Clear stored original configuration. * * @param {string} pluginId - Plugin identifier */ clearOriginal(pluginId) { this.originalConfigs.delete(pluginId); }, /** * Compare two configuration objects and return differences. * * @param {Object} oldConfig - Old configuration * @param {Object} newConfig - New configuration * @returns {Object} Differences object with added, removed, and changed keys */ compare(oldConfig, newConfig) { const differences = { added: {}, removed: {}, changed: {}, unchanged: {} }; // Get all keys from both configs const allKeys = new Set([ ...Object.keys(oldConfig || {}), ...Object.keys(newConfig || {}) ]); for (const key of allKeys) { const oldValue = oldConfig?.[key]; const newValue = newConfig?.[key]; if (!(key in (oldConfig || {}))) { // Key was added differences.added[key] = newValue; } else if (!(key in (newConfig || {}))) { // Key was removed differences.removed[key] = oldValue; } else if (JSON.stringify(oldValue) !== JSON.stringify(newValue)) { // Key was changed differences.changed[key] = { old: oldValue, new: newValue }; } else { // Key unchanged differences.unchanged[key] = oldValue; } } return differences; }, /** * Check if there are any differences. * * @param {Object} differences - Differences object from compare() * @returns {boolean} True if there are changes */ hasChanges(differences) { return Object.keys(differences.added).length > 0 || Object.keys(differences.removed).length > 0 || Object.keys(differences.changed).length > 0; }, /** * Format differences for display. * * @param {Object} differences - Differences object * @returns {string} HTML formatted diff */ formatDiff(differences) { const parts = []; // Added keys if (Object.keys(differences.added).length > 0) { parts.push(`
${this.escapeHtml(key)}
=
${this.escapeHtml(JSON.stringify(value, null, 2))}
${this.escapeHtml(key)}
=
${this.escapeHtml(JSON.stringify(value, null, 2))}
${this.escapeHtml(key)}
${this.escapeHtml(JSON.stringify(change.old, null, 2))}
${this.escapeHtml(JSON.stringify(change.new, null, 2))}