import type { AuthUser } from './auth' export interface CanvasNode { id: string type: string x: number y: number width: number height: number text?: string file?: string frontmatter?: Record state?: 'pending' | 'in_progress' | 'completed' label?: string assigned_to?: string alarm?: string script_id?: string prompt?: string url?: string method?: string repo?: string branch?: string message?: string style?: Record } export interface CanvasEdge { id: string fromNode: string fromSide: string toNode: string toSide: string } export interface CanvasData { id: string name: string nodes: CanvasNode[] edges: CanvasEdge[] createdAt: string updatedAt: string ownerId: string groupId?: string isPublic?: boolean } export interface UserGroup { userId: string groupId: string role: 'admin' | 'member' | 'viewer' joinedAt: string } export interface Group { id: string name: string description: string isPublic: boolean createdAt: string updatedAt: string ownerId: string } export interface Profile { userId: string displayName: string bio: string avatar: string joinedAt: string canvasCount: number followerCount: number followingCount: number } export interface Activity { id: string userId: string action: string targetId: string targetType: string timestamp: string metadata?: Record } // In-memory stores export const users = new Map() export const nodes = new Map() export const achievements = new Map() export const pushSubscriptions = new Map() export const canvases = new Map() export const userGroups = new Map() export const groups = new Map() export const profiles = new Map() export const activities = new Map() export const follows = new Map() // Seed admins const seedAdmins = [ { id: '1', email: 'admin@xflow.local', username: 'admin' }, { id: '2', email: 'almalexyz@gmail.com', username: 'almalexyz' }, { id: '3', email: 'ormix16@gmail.com', username: 'ormix16' } ] for (const admin of seedAdmins) { users.set(admin.email, { ...admin, password: 'admin123', role: 'admin' }) // Create profiles for admins profiles.set(admin.id, { userId: admin.id, displayName: admin.username, bio: 'XFlow Administrator', avatar: `https://api.dicebear.com/7.x/avataaars/svg?seed=${admin.id}`, joinedAt: new Date().toISOString(), canvasCount: 0, followerCount: 0, followingCount: 0 }) } // Create demo groups const demoGroups: Group[] = [ { id: 'group-1', name: 'XFlow Team', description: 'Core development team', isPublic: true, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), ownerId: '1' }, { id: 'group-2', name: 'Beta Testers', description: 'Early access users', isPublic: true, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), ownerId: '1' }, { id: 'group-3', name: 'AI Research', description: 'AI/LLM integration research', isPublic: false, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), ownerId: '2' } ] demoGroups.forEach(group => { groups.set(group.id, group) // Add admins to groups seedAdmins.forEach(admin => { userGroups.set(`${admin.id}-${group.id}`, { userId: admin.id, groupId: group.id, role: admin.id === '1' ? 'admin' : 'member', joinedAt: new Date().toISOString() }) }) }) // Seed comprehensive XFlow project mind map const xflowProjectCanvas: CanvasData = { id: 'xflow-project', name: 'Обзор Проекта XFlow', nodes: [ // Core Architecture { id: 'arch-1', type: 'text', x: 100, y: 100, width: 320, height: 180, text: '# 🏗️ Основная Архитектура\n\n- **Nuxt 3** - Vue 3 фреймворк\n- **TailwindCSS** - Стилизация\n- **Vue Flow** - Движок канваса\n- **Firebase** - Аутентификация\n- **In-memory DB** - Хранение данных\n- **PWA** - Progressive Web App', style: { background: '#1e293b', border: '#3b82f6' } }, // Frontend Components { id: 'fe-1', type: 'text', x: 500, y: 50, width: 280, height: 160, text: '# 🎨 Фронтенд\n\n- **FlowEditor.vue** - Основной редактор\n- **FlowNodeRenderer.vue** - Отображение узлов\n- **CanvasViewer.vue** - Устаревший просмотр\n- **Админ Панель** - Управление интерфейсом\n- **Система Аутентификации** - Вход через Google', style: { background: '#1e293b', border: '#10b981' } }, // Backend APIs { id: 'be-1', type: 'text', x: 500, y: 250, width: 280, height: 160, text: '# ⚙️ Backend API\n\n- `/api/canvas/*` - CRUD операций с канвасами\n- `/api/nodes/*` - Управление узлами\n- `/api/auth/*` - Аутентификация\n- `/api/admin/*` - Административные операции\n- `/api/push/*` - Уведомления', style: { background: '#1e293b', border: '#f59e0b' } }, // Node Types { id: 'nodes-1', type: 'text', x: 100, y: 320, width: 320, height: 200, text: '# 📦 Типы Узлов\n\n- **Текстовая Заметка** - Markdown контент\n- **Ссылка на Файл** - Ссылки на файлы\n- **Узел Задачи** - Отслеживание состояния\n- **AI/LLM Узел** - AI обработка\n- **Webhook Узел** - HTTP триггеры\n- **Git Sync Узел** - Контроль версий', style: { background: '#1e293b', border: '#8b5cf6' } }, // Features { id: 'feat-1', type: 'text', x: 850, y: 150, width: 300, height: 220, text: '# ✨ Ключевые Функции\n\n- **Редактор в стиле Node-RED**\n - Палитра сбоку\n - Панель свойств\n - Drag & drop\n - Соединения проводами\n\n- **Совместимость с Obsidian**\n - Экспорт в .canvas формат\n - Импорт существующих карт\n - Поддержка Markdown\n\n- **Социальные Функции**\n - Группы пользователей\n - Общие канвасы\n - Лента активности', style: { background: '#1e293b', border: '#ef4444' } }, // Tech Stack { id: 'tech-1', type: 'text', x: 100, y: 560, width: 320, height: 180, text: '# 🛠️ Технологический Стек\n\n```json\n{\n "frontend": "Vue 3 + Nuxt 3",\n "styling": "TailwindCSS",\n "canvas": "Vue Flow",\n "auth": "Firebase Google",\n "storage": "In-memory",\n "pwa": "@vite-pwa/nuxt"\n}\n```', style: { background: '#1e293b', border: '#06b6d4' } }, // Future Plans { id: 'future-1', type: 'text', x: 500, y: 450, width: 280, height: 180, text: '# 🚀 Будущее Развитие\n\n- **Git Интеграция**\n - Commit/push/pull карт\n - История версий\n - Управление ветками\n\n- **AI Интеграция**\n - OpenClaw агенты\n - Автоматизация LLM узлов\n - Умные предложения\n\n- **Социальная Сеть**\n - Профили пользователей\n - Система подписок\n - Ленты активности', style: { background: '#1e293b', border: '#ec4899' } }, // Database Schema { id: 'db-1', type: 'file', x: 850, y: 400, width: 300, height: 160, file: 'app/server/utils/db.ts', text: '## Схема Базы Данных\n\n- `users` - Пользовательские аккаунты\n- `canvases` - Ментальные карты\n- `nodes` - Отдельные узлы\n- `groups` - Группы пользователей\n- `profiles` - Профили пользователей\n- `activities` - Лента активности', style: { background: '#1e293b', border: '#84cc16' } }, // Deployment { id: 'deploy-1', type: 'text', x: 850, y: 590, width: 300, height: 140, text: '# 🚀 Развертывание\n\n- **Docker Compose**\n- **Nginx** - Обратный прокси\n- **Gitea** - Git сервер\n- **PostgreSQL** - База данных\n- **Certbot** - SSL сертификаты', style: { background: '#1e293b', border: '#f97316' } }, // Social Features { id: 'social-1', type: 'text', x: 100, y: 780, width: 320, height: 160, text: '# 👥 Social Network\n\n- **User Profiles**\n - Avatar & bio\n - Canvas statistics\n - Following/followers\n\n- **Groups System**\n - Public/private groups\n - Role-based permissions\n - Shared canvases', style: { background: '#1e293b', border: '#a855f7' } }, // File Structure { id: 'files-1', type: 'file', x: 500, y: 660, width: 280, height: 140, file: 'project-structure.md', text: '## Project Structure\n\n```\napp/\n├── components/\n│ ├── FlowEditor.vue\n│ └── FlowNodeRenderer.vue\n├── pages/\n│ ├── canvas.vue\n│ └── admin.vue\n└── server/api/\n```', style: { background: '#1e293b', border: '#0ea5e9' } } ], edges: [ { id: 'e1', fromNode: 'arch-1', fromSide: 'right', toNode: 'fe-1', toSide: 'left' }, { id: 'e2', fromNode: 'arch-1', fromSide: 'right', toNode: 'be-1', toSide: 'left' }, { id: 'e3', fromNode: 'arch-1', fromSide: 'bottom', toNode: 'nodes-1', toSide: 'top' }, { id: 'e4', fromNode: 'fe-1', fromSide: 'right', toNode: 'feat-1', toSide: 'left' }, { id: 'e5', fromNode: 'be-1', fromSide: 'right', toNode: 'feat-1', toSide: 'left' }, { id: 'e6', fromNode: 'nodes-1', fromSide: 'bottom', toNode: 'tech-1', toSide: 'top' }, { id: 'e7', fromNode: 'be-1', fromSide: 'bottom', toNode: 'future-1', toSide: 'top' }, { id: 'e8', fromNode: 'feat-1', fromSide: 'bottom', toNode: 'db-1', toSide: 'top' }, { id: 'e9', fromNode: 'db-1', fromSide: 'bottom', toNode: 'deploy-1', toSide: 'top' }, { id: 'e10', fromNode: 'tech-1', fromSide: 'right', toNode: 'future-1', toSide: 'left' }, { id: 'e11', fromNode: 'tech-1', fromSide: 'bottom', toNode: 'social-1', toSide: 'top' }, { id: 'e12', fromNode: 'future-1', fromSide: 'bottom', toNode: 'files-1', toSide: 'top' }, { id: 'e13', fromNode: 'social-1', fromSide: 'right', toNode: 'files-1', toSide: 'left' } ], createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), ownerId: '1', isPublic: true } canvases.set('xflow-project', xflowProjectCanvas) // Create shared canvases for groups const sharedCanvases = [ { id: 'team-roadmap', name: 'Team Roadmap 2025', groupId: 'group-1', ownerId: '1' }, { id: 'beta-feedback', name: 'Beta Feedback Map', groupId: 'group-2', ownerId: '1' }, { id: 'ai-research', name: 'AI Integration Ideas', groupId: 'group-3', ownerId: '2' } ] sharedCanvases.forEach(canvas => { const canvasData: CanvasData = { id: canvas.id, name: canvas.name, nodes: [ { id: `${canvas.id}-node-1`, type: 'text', x: 200, y: 200, width: 300, height: 150, text: `# ${canvas.name}\n\nThis is a shared canvas for the group.\n\nStart adding your ideas!`, style: { background: '#1e293b', border: '#3b82f6' } } ], edges: [], createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), ownerId: canvas.ownerId, groupId: canvas.groupId, isPublic: true } canvases.set(canvas.id, canvasData) }) // Add demo activities const demoActivities: Activity[] = [ { id: 'activity-1', userId: '1', action: 'created_canvas', targetId: 'xflow-project', targetType: 'canvas', timestamp: new Date().toISOString() }, { id: 'activity-2', userId: '2', action: 'joined_group', targetId: 'group-1', targetType: 'group', timestamp: new Date().toISOString() }, { id: 'activity-3', userId: '3', action: 'created_canvas', targetId: 'ai-research', targetType: 'canvas', timestamp: new Date().toISOString() }, { id: 'activity-4', userId: '1', action: 'followed_user', targetId: '2', targetType: 'user', timestamp: new Date().toISOString() } ] demoActivities.forEach(activity => { activities.set(activity.id, activity) }) // Add demo follows follows.set('1-2', { followerId: '1', followingId: '2', since: new Date().toISOString() }) follows.set('2-3', { followerId: '2', followingId: '3', since: new Date().toISOString() }) // Keep the old demo canvas for backward compatibility canvases.set('demo', { id: 'demo', name: 'Demo Canvas', nodes: [ { id: 'node-1', type: 'text', x: 0, y: 0, width: 300, height: 200, text: '# Welcome\n\nЭто демо-нода с **Markdown** поддержкой.', state: 'pending', style: { background: '#1e293b', border: '#334155' } }, { id: 'node-2', type: 'file', x: 400, y: 0, width: 300, height: 200, file: 'tasks.md', frontmatter: { alarm: '2025-04-24T09:00:00Z', script_id: 'notify', assigned_to: 'user' }, state: 'pending', style: { background: '#1e293b', border: '#334155' } }, { id: 'node-3', type: 'text', x: 200, y: 300, width: 300, height: 150, text: '### Завершенная задача\n- [x] Настроить PWA', state: 'completed', style: { background: '#064e3b', border: '#059669' } } ], edges: [ { id: 'edge-1', fromNode: 'node-1', fromSide: 'right', toNode: 'node-2', toSide: 'left' }, { id: 'edge-2', fromNode: 'node-2', fromSide: 'bottom', toNode: 'node-3', toSide: 'top' } ], createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), ownerId: '1' }) export function getUserAchievements(userId: string) { return achievements.get(userId) || [] } export function addAchievement(userId: string, achievement: any) { const list = achievements.get(userId) || [] list.push({ ...achievement, unlockedAt: new Date().toISOString() }) achievements.set(userId, list) }