import fs from 'fs'; import path from 'path'; import { randomUUID } from 'crypto'; const DATA_DIR = path.join(__dirname, '..', '..', 'build', 'data', 'db'); if (!fs.existsSync(DATA_DIR)) fs.mkdirSync(DATA_DIR, { recursive: true }); export interface User { id: string; username: string; password: string; created_at: string; } export interface Group { id: string; name: string; created_at: string; } export interface GroupMember { id: string; group_id: string; member_type: 'user' | 'group'; member_id: string; } export interface Project { id: string; name: string; owner_id: string; created_at: string; } export interface ProjectMember { id: string; project_id: string; member_type: 'user' | 'group'; member_id: string; role: string; } function read(table: string): T[] { const file = path.join(DATA_DIR, `${table}.json`); if (!fs.existsSync(file)) return []; return JSON.parse(fs.readFileSync(file, 'utf8')) as T[]; } function write(table: string, rows: T[]): void { fs.writeFileSync(path.join(DATA_DIR, `${table}.json`), JSON.stringify(rows, null, 2)); } export const users = { all: (): User[] => read('users'), findById: (id: string): User | undefined => read('users').find(u => u.id === id), findByUsername: (name: string): User | undefined => read('users').find(u => u.username === name), create(data: Omit): User { const rows = read('users'); if (rows.find(u => u.username === data.username)) throw new Error('Taken'); const user: User = { id: randomUUID(), ...data, created_at: new Date().toISOString() }; write('users', [...rows, user]); return user; }, delete(id: string): void { write('users', read('users').filter(u => u.id !== id)); } }; export const groups = { all: (): Group[] => read('groups'), findById: (id: string): Group | undefined => read('groups').find(g => g.id === id), create(data: Omit): Group { const rows = read('groups'); if (rows.find(g => g.name === data.name)) throw new Error('Taken'); const group: Group = { id: randomUUID(), ...data, created_at: new Date().toISOString() }; write('groups', [...rows, group]); return group; }, delete(id: string): void { write('groups', read('groups').filter(g => g.id !== id)); write('group_members', read('group_members').filter(m => m.group_id !== id)); } }; export const groupMembers = { forGroup: (groupId: string): GroupMember[] => read('group_members').filter(m => m.group_id === groupId), add(data: Omit): GroupMember { const rows = read('group_members'); const member: GroupMember = { id: randomUUID(), ...data }; write('group_members', [...rows, member]); return member; }, remove(id: string): void { write('group_members', read('group_members').filter(m => m.id !== id)); } }; export const projects = { all: (): Project[] => read('projects'), findById: (id: string): Project | undefined => read('projects').find(p => p.id === id), create(data: Omit): Project { const rows = read('projects'); const project: Project = { id: randomUUID(), ...data, created_at: new Date().toISOString() }; write('projects', [...rows, project]); return project; }, delete(id: string): void { write('projects', read('projects').filter(p => p.id !== id)); write('project_members', read('project_members').filter(m => m.project_id !== id)); } }; export const projectMembers = { forProject: (projectId: string): ProjectMember[] => read('project_members').filter(m => m.project_id === projectId), add(data: Omit): ProjectMember { const rows = read('project_members'); const member: ProjectMember = { id: randomUUID(), ...data }; write('project_members', [...rows, member]); return member; }, remove(id: string): void { write('project_members', read('project_members').filter(m => m.id !== id)); } };