Initial commit: Clean DSS implementation

Migrated from design-system-swarm with fresh git history.
Old project history preserved in /home/overbits/apps/design-system-swarm

Core components:
- MCP Server (Python FastAPI with mcp 1.23.1)
- Claude Plugin (agents, commands, skills, strategies, hooks, core)
- DSS Backend (dss-mvp1 - token translation, Figma sync)
- Admin UI (Node.js/React)
- Server (Node.js/Express)
- Storybook integration (dss-mvp1/.storybook)

Self-contained configuration:
- All paths relative or use DSS_BASE_PATH=/home/overbits/dss
- PYTHONPATH configured for dss-mvp1 and dss-claude-plugin
- .env file with all configuration
- Claude plugin uses ${CLAUDE_PLUGIN_ROOT} for portability

Migration completed: $(date)
🤖 Clean migration with full functionality preserved
This commit is contained in:
Digital Production Factory
2025-12-09 18:45:48 -03:00
commit 276ed71f31
884 changed files with 373737 additions and 0 deletions

View File

@@ -0,0 +1,324 @@
/**
* DSS Notification Service
*
* Centralized messaging system with structured formats, error taxonomy,
* and correlation IDs for enterprise-grade error tracking and user feedback.
*
* @module messaging
*/
// Event bus for pub/sub notifications
const bus = new EventTarget();
// Event name constant
export const NOTIFICATION_EVENT = 'dss-notification';
/**
* Notification severity types
*/
export const NotificationType = {
SUCCESS: 'success',
ERROR: 'error',
WARNING: 'warning',
INFO: 'info',
};
/**
* Error taxonomy for structured error handling
*/
export const ErrorCode = {
// User errors (E1xxx)
USER_INPUT_INVALID: 'E1001',
USER_ACTION_FORBIDDEN: 'E1002',
USER_NOT_AUTHENTICATED: 'E1003',
// Validation errors (E2xxx)
VALIDATION_FAILED: 'E2001',
VALIDATION_MISSING_FIELD: 'E2002',
VALIDATION_INVALID_FORMAT: 'E2003',
// API errors (E3xxx)
API_REQUEST_FAILED: 'E3001',
API_TIMEOUT: 'E3002',
API_UNAUTHORIZED: 'E3003',
API_NOT_FOUND: 'E3004',
API_SERVER_ERROR: 'E3005',
// System errors (E4xxx)
SYSTEM_UNEXPECTED: 'E4001',
SYSTEM_NETWORK: 'E4002',
SYSTEM_STORAGE: 'E4003',
// Integration errors (E5xxx)
FIGMA_CONNECTION_FAILED: 'E5001',
FIGMA_INVALID_KEY: 'E5002',
FIGMA_API_ERROR: 'E5003',
// Success codes (S1xxx)
SUCCESS_OPERATION: 'S1001',
SUCCESS_CREATED: 'S1002',
SUCCESS_UPDATED: 'S1003',
SUCCESS_DELETED: 'S1004',
};
/**
* Generate correlation ID for request tracking
* @returns {string} UUID v4 correlation ID
*/
function generateCorrelationId() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
/**
* Message queue for persistence
*/
class MessageQueue {
constructor(maxSize = 50) {
this.maxSize = maxSize;
this.storageKey = 'dss_message_queue';
}
/**
* Add message to queue
* @param {Object} message - Notification message
*/
add(message) {
try {
const queue = this.getAll();
queue.unshift(message);
// Keep only last maxSize messages
const trimmed = queue.slice(0, this.maxSize);
localStorage.setItem(this.storageKey, JSON.stringify(trimmed));
} catch (error) {
console.warn('Failed to persist message to queue:', error);
}
}
/**
* Get all messages from queue
* @returns {Array} Array of messages
*/
getAll() {
try {
const data = localStorage.getItem(this.storageKey);
return data ? JSON.parse(data) : [];
} catch (error) {
console.warn('Failed to read message queue:', error);
return [];
}
}
/**
* Clear the message queue
*/
clear() {
try {
localStorage.removeItem(this.storageKey);
} catch (error) {
console.warn('Failed to clear message queue:', error);
}
}
/**
* Get recent errors for debugging
* @param {number} limit - Max number of errors to return
* @returns {Array} Recent error messages
*/
getRecentErrors(limit = 10) {
const queue = this.getAll();
return queue
.filter(msg => msg.type === NotificationType.ERROR)
.slice(0, limit);
}
}
// Singleton message queue
const messageQueue = new MessageQueue();
/**
* Send a notification
*
* @param {Object} detail - Notification details
* @param {string} detail.message - User-facing message
* @param {NotificationType} [detail.type=INFO] - Notification type
* @param {string} [detail.code] - Machine-readable error code
* @param {Object} [detail.metadata] - Additional context for logging
* @param {string} [detail.correlationId] - Optional correlation ID (auto-generated if not provided)
* @param {number} [detail.duration] - Auto-dismiss duration in ms (0 = no auto-dismiss)
*
* @example
* notify({
* message: 'Project created successfully',
* type: NotificationType.SUCCESS,
* code: ErrorCode.SUCCESS_CREATED,
* metadata: { projectId: 'demo-ds' }
* });
*
* @example
* notify({
* message: 'Failed to connect to Figma',
* type: NotificationType.ERROR,
* code: ErrorCode.FIGMA_CONNECTION_FAILED,
* metadata: { fileKey: 'abc123', endpoint: '/figma/file' },
* correlationId: 'custom-id-123'
* });
*/
export function notify(detail) {
const notification = {
id: generateCorrelationId(),
message: detail.message,
type: detail.type || NotificationType.INFO,
code: detail.code || null,
metadata: detail.metadata || {},
correlationId: detail.correlationId || generateCorrelationId(),
timestamp: new Date().toISOString(),
duration: detail.duration !== undefined ? detail.duration : 5000, // Default 5s
};
// Persist to queue
messageQueue.add(notification);
// Dispatch event
bus.dispatchEvent(new CustomEvent(NOTIFICATION_EVENT, {
detail: notification
}));
// Log for debugging
const logMethod = notification.type === NotificationType.ERROR ? 'error' : 'log';
console[logMethod]('[DSS Notification]', {
message: notification.message,
code: notification.code,
correlationId: notification.correlationId,
metadata: notification.metadata,
});
return notification;
}
/**
* Subscribe to notifications
*
* @param {Function} callback - Called when notification is sent
* @returns {Function} Unsubscribe function
*
* @example
* const unsubscribe = subscribe((notification) => {
* console.log('Notification:', notification.message);
* });
*
* // Later: unsubscribe();
*/
export function subscribe(callback) {
const handler = (event) => callback(event.detail);
bus.addEventListener(NOTIFICATION_EVENT, handler);
// Return unsubscribe function
return () => {
bus.removeEventListener(NOTIFICATION_EVENT, handler);
};
}
/**
* Helper: Send success notification
* @param {string} message - Success message
* @param {string} [code] - Success code
* @param {Object} [metadata] - Additional context
*/
export function notifySuccess(message, code = ErrorCode.SUCCESS_OPERATION, metadata = {}) {
return notify({
message,
type: NotificationType.SUCCESS,
code,
metadata,
});
}
/**
* Helper: Send error notification
* @param {string} message - Error message
* @param {string} [code] - Error code
* @param {Object} [metadata] - Additional context
*/
export function notifyError(message, code = ErrorCode.SYSTEM_UNEXPECTED, metadata = {}) {
return notify({
message,
type: NotificationType.ERROR,
code,
metadata,
duration: 0, // Errors don't auto-dismiss
});
}
/**
* Helper: Send warning notification
* @param {string} message - Warning message
* @param {Object} [metadata] - Additional context
*/
export function notifyWarning(message, metadata = {}) {
return notify({
message,
type: NotificationType.WARNING,
metadata,
duration: 7000, // Warnings stay a bit longer
});
}
/**
* Helper: Send info notification
* @param {string} message - Info message
* @param {Object} [metadata] - Additional context
*/
export function notifyInfo(message, metadata = {}) {
return notify({
message,
type: NotificationType.INFO,
metadata,
});
}
/**
* Get message history
* @returns {Array} All persisted messages
*/
export function getMessageHistory() {
return messageQueue.getAll();
}
/**
* Get recent errors for debugging
* @param {number} limit - Max number of errors
* @returns {Array} Recent errors
*/
export function getRecentErrors(limit = 10) {
return messageQueue.getRecentErrors(limit);
}
/**
* Clear message history
*/
export function clearMessageHistory() {
messageQueue.clear();
}
// Export singleton queue for advanced use cases
export { messageQueue };
export default {
notify,
subscribe,
notifySuccess,
notifyError,
notifyWarning,
notifyInfo,
getMessageHistory,
getRecentErrors,
clearMessageHistory,
NotificationType,
ErrorCode,
};