// Test-helper voor M8 acceptatie. Muteert een task of story rechtstreeks // in de DB om realtime-events te triggeren — alsof MCP of een andere // schrijver het zou doen. Niet voor productiegebruik. // // Gebruik: // tsx scripts/realtime-mutate.ts move // tsx scripts/realtime-mutate.ts touch task // tsx scripts/realtime-mutate.ts touch story // tsx scripts/realtime-mutate.ts rename story // tsx scripts/realtime-mutate.ts list-tasks # toont id + status van assigned tasks import * as dotenv from 'dotenv' import * as path from 'path' import { Pool } from 'pg' const root = path.resolve(__dirname, '..') dotenv.config({ path: path.join(root, '.env.local'), override: true }) dotenv.config({ path: path.join(root, '.env') }) async function main() { const url = process.env.DATABASE_URL if (!url) throw new Error('DATABASE_URL is not set') const pool = new Pool({ connectionString: url }) const [, , cmd, ...rest] = process.argv try { if (cmd === 'move') { const [taskId, status] = rest if (!taskId || !status) throw new Error('move requires ') const r = await pool.query( 'UPDATE tasks SET status = $1::"TaskStatus", updated_at = NOW() WHERE id = $2 RETURNING id, status', [status, taskId], ) console.log('moved:', r.rows[0]) } else if (cmd === 'touch') { const [entity, id] = rest if (entity !== 'task' && entity !== 'story') throw new Error('touch entity must be task or story') const table = entity === 'task' ? 'tasks' : 'stories' const r = await pool.query( `UPDATE ${table} SET updated_at = NOW() WHERE id = $1 RETURNING id`, [id], ) console.log('touched:', r.rows[0]) } else if (cmd === 'rename') { const [entity, id, ...titleParts] = rest const title = titleParts.join(' ') if (entity !== 'story') throw new Error('rename only supported for story for now') if (!id || !title) throw new Error('rename requires ') const r = await pool.query( 'UPDATE stories SET title = $1, updated_at = NOW() WHERE id = $2 RETURNING id, title', [title, id], ) console.log('renamed:', r.rows[0]) } else if (cmd === 'list-tasks') { const r = await pool.query(` SELECT t.id, t.title, t.status, s.code AS story_code, s.title AS story_title FROM tasks t JOIN stories s ON t.story_id = s.id WHERE s.assignee_id IS NOT NULL ORDER BY s.sort_order, t.sort_order LIMIT 20 `) console.table(r.rows) } else { console.error('Usage:') console.error(' tsx scripts/realtime-mutate.ts move ') console.error(' tsx scripts/realtime-mutate.ts touch task|story ') console.error(' tsx scripts/realtime-mutate.ts rename story ') console.error(' tsx scripts/realtime-mutate.ts list-tasks') process.exit(1) } } finally { await pool.end() } } main().catch((err) => { console.error(err.message) process.exit(1) })