122 lines
5.7 KiB
JavaScript
122 lines
5.7 KiB
JavaScript
const { Pool } = require('pg')
|
|
|
|
// Connection string from .env
|
|
const DB_URL = 'postgresql://xflow:xflow_pass@localhost:5433/xflow'
|
|
const pool = new Pool({ connectionString: DB_URL })
|
|
|
|
const CANVAS_ID = 'xflow-project-brief'
|
|
const OWNER_ID = 'GqbpMyUW0NaxjIy5nvCiXCiQu9t2'
|
|
|
|
const nodes = [
|
|
{
|
|
id: 'main',
|
|
type: 'text',
|
|
x: 0, y: 0,
|
|
width: 450, height: 220,
|
|
label: '🤖 XFlow — Project Brief',
|
|
text: `# 🤖 XFlow\n\n**Visual CRM/ERP system based on Obsidian Canvas.**\n\n- **Owner:** Alex Ives (almalexyz@gmail.com)\n- **Firebase UID:** \`GqbpMyUW0NaxjIy5nvCiXCiQu9t2\`\n- **Repo:** [git.a-crm.controlsystem.kz](http://git.a-crm.controlsystem.kz/AVTEX/XFlow)\n- **Prod:** [a-crm.controlsystem.kz](https://a-crm.controlsystem.kz)\n- **Local:** [localhost:3000](http://localhost:3000)`
|
|
},
|
|
{
|
|
id: 'tech-stack',
|
|
type: 'text',
|
|
x: 600, y: -250,
|
|
width: 400, height: 350,
|
|
label: '🏗️ Tech Stack',
|
|
text: `# 🏗️ Стек технологий\n\n- **Frontend:** Nuxt 3 (SSR + API routes)\n- **Canvas Engine:** Vue Flow\n- **Styling:** TailwindCSS\n- **ORM:** Prisma 7 + @prisma/adapter-pg\n- **Database:** PostgreSQL 16 (Docker)\n- **Auth:** Firebase Auth + JWT\n- **PWA:** @vite-pwa/nuxt\n- **CI/CD:** Gitea Actions`
|
|
},
|
|
{
|
|
id: 'infrastructure',
|
|
type: 'text',
|
|
x: 600, y: 250,
|
|
width: 400, height: 350,
|
|
label: '🖥️ Infrastructure',
|
|
text: `# 🖥️ Инфраструктура\n\n- **VM (Debian):** 10.0.0.120\n- **Docker Network:** \`infra\`\n- **Services:**\n - \`postgres:5432\` (Shared DB)\n - \`gitea:3001\` (Git server)\n - \`xflow:3002\` (Production app)\n - \`npb-app:3000\` (Other project)\n- **Reverse Proxy:** Nginx (FastPanel)\n\n[🔗 Перейти к карте инфраструктуры](canvas/infrastructure)`
|
|
},
|
|
{
|
|
id: 'database',
|
|
type: 'text',
|
|
x: 1100, y: 0,
|
|
width: 400, height: 300,
|
|
label: '🗄️ Database Schema',
|
|
text: `# 🗄️ Prisma Schema\n\n- **User:** Firebase ID, Email, Role (admin/user)\n- **Canvas:** ID, Name, Owner, Public, Nodes (Json), Edges (Json)\n\n⚠️ **Важно:** Узлы хранятся как JSON-массив. При обновлении нужно перезаписывать весь массив.`
|
|
},
|
|
{
|
|
id: 'auth-flow',
|
|
type: 'text',
|
|
x: -600, y: -250,
|
|
width: 400, height: 300,
|
|
label: '🔐 Auth Flow',
|
|
text: `# 🔐 Аутентификация\n\n1. Client logins via Firebase Google Auth.\n2. Token sent to \`/api/auth/google\`.\n3. Server upserts user (ID = Firebase UID).\n4. Returns JWT in \`xflow_token\` cookie.\n5. \`requireAuth\` middleware protects routes.\n\n⚠️ User.id MUST match Firebase UID.`
|
|
},
|
|
{
|
|
id: 'features',
|
|
type: 'text',
|
|
x: -600, y: 250,
|
|
width: 400, height: 420,
|
|
label: '✅ Features',
|
|
text: `# ✅ Реализовано\n\n- **Canvas:** Interactive Vue Flow editor\n- **Nodes:** text, task, ai, webhook, file, git\n- **Kanban:** Board (/tasks) with DnD\n- **AI:** Execution with context from neighbors\n- **Webhooks:** GET/POST execution\n- **Git:** Sync maps with Gitea\n- **Auth:** RBAC (user/admin) & Firebase\n- **PWA:** Service Worker & Manifest`
|
|
},
|
|
{
|
|
id: 'todo',
|
|
type: 'text',
|
|
x: 0, y: 450,
|
|
width: 400, height: 320,
|
|
label: '🔴 To-Do',
|
|
text: `# 🔴 Что нужно доделать\n\n- **AI Key:** Get a working Groq key (llama-3.3-70b).\n- **Dashboard:** Main page with stats.\n- **Webhooks:** Telegram notifications.\n- **Users:** Invitation system.\n- **Stability:** Fix PWA service worker caching issue.`
|
|
},
|
|
{
|
|
id: 'dev-tips',
|
|
type: 'text',
|
|
x: 0, y: -450,
|
|
width: 450, height: 320,
|
|
label: '💡 Dev Tips',
|
|
text: `# 💡 Советы по разработке\n\n- **Local run:** \`npm run dev\`\n- **DB Tunnel:** \`ssh -J alex@178.238.78.98 -L 5433:localhost:5432 root@10.0.0.120\`\n- **Check DB:** \`node scripts/list_users.cjs\`\n- **Test AI:** \`node scripts/test_qwen.cjs\`\n- **Note:** Don't use \`git push && ...\` in PowerShell.`
|
|
},
|
|
{
|
|
id: 'issues',
|
|
type: 'text',
|
|
x: -1100, y: 0,
|
|
width: 400, height: 280,
|
|
label: '🐛 Known Issues',
|
|
text: `# 🐛 Известные проблемы\n\n- **PWA:** Clear site data if non-precached-url error occurs.\n- **Gitea:** 403 error on push if token expired.\n- **Logs:** Remove debug logs from \`execute.post.ts\` before prod.`
|
|
}
|
|
]
|
|
|
|
const edges = [
|
|
{ id: 'e1', source: 'main', target: 'tech-stack' },
|
|
{ id: 'e2', source: 'main', target: 'infrastructure' },
|
|
{ id: 'e3', source: 'main', target: 'features' },
|
|
{ id: 'e4', source: 'main', target: 'auth-flow' },
|
|
{ id: 'e5', source: 'main', target: 'todo' },
|
|
{ id: 'e6', source: 'main', target: 'dev-tips' },
|
|
{ id: 'e7', source: 'tech-stack', target: 'database' },
|
|
{ id: 'e8', source: 'infrastructure', target: 'database' },
|
|
{ id: 'e9', source: 'features', target: 'issues' }
|
|
]
|
|
|
|
async function run() {
|
|
try {
|
|
const check = await pool.query('SELECT id FROM "Canvas" WHERE id = $1', [CANVAS_ID])
|
|
|
|
if (check.rows.length > 0) {
|
|
await pool.query(
|
|
'UPDATE "Canvas" SET nodes = $1, edges = $2, name = $3, "updatedAt" = NOW() WHERE id = $4',
|
|
[JSON.stringify(nodes), JSON.stringify(edges), '🤖 XFlow — Project Brief', CANVAS_ID]
|
|
)
|
|
console.log('✅ XFlow Brief canvas updated!')
|
|
} else {
|
|
await pool.query(
|
|
'INSERT INTO "Canvas" (id, name, "ownerId", "isPublic", nodes, edges, "createdAt", "updatedAt") VALUES ($1, $2, $3, true, $4, $5, NOW(), NOW())',
|
|
[CANVAS_ID, '🤖 XFlow — Project Brief', OWNER_ID, JSON.stringify(nodes), JSON.stringify(edges)]
|
|
)
|
|
console.log('✅ XFlow Brief canvas created!')
|
|
}
|
|
} catch (e) {
|
|
console.error('❌ Error:', e.message)
|
|
} finally {
|
|
await pool.end()
|
|
}
|
|
}
|
|
|
|
run()
|