Files
adiuva/src/main/db/index.ts

98 lines
2.7 KiB
TypeScript

import Database from 'better-sqlite3';
import { drizzle } from 'drizzle-orm/better-sqlite3';
import { app } from 'electron';
import path from 'node:path';
import * as schema from './schema';
// SQL to create all tables if they don't exist (non-destructive push strategy)
const MIGRATION_SQL = `
CREATE TABLE IF NOT EXISTS clients (
id TEXT PRIMARY KEY,
parent_id TEXT,
name TEXT NOT NULL,
industry TEXT,
created_at INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS projects (
id TEXT PRIMARY KEY,
client_id TEXT,
name TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'active',
ai_summary TEXT,
created_at INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS tasks (
id TEXT PRIMARY KEY,
project_id TEXT,
title TEXT NOT NULL,
description TEXT,
status TEXT NOT NULL DEFAULT 'todo',
priority TEXT NOT NULL DEFAULT 'medium',
assignee TEXT,
due_date INTEGER,
is_ai_suggested INTEGER NOT NULL DEFAULT 0,
is_approved INTEGER NOT NULL DEFAULT 1,
created_at INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS checkpoints (
id TEXT PRIMARY KEY,
project_id TEXT NOT NULL,
title TEXT NOT NULL,
date INTEGER NOT NULL,
is_ai_suggested INTEGER NOT NULL DEFAULT 0,
is_approved INTEGER NOT NULL DEFAULT 0,
created_at INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS notes (
id TEXT PRIMARY KEY,
project_id TEXT,
title TEXT NOT NULL,
content TEXT NOT NULL DEFAULT '',
created_at INTEGER NOT NULL,
updated_at INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS task_comments (
id TEXT PRIMARY KEY,
task_id TEXT NOT NULL,
author TEXT NOT NULL,
content TEXT NOT NULL,
created_at INTEGER NOT NULL
);
`;
type DbInstance = ReturnType<typeof drizzle<typeof schema>>;
let dbInstance: DbInstance | null = null;
export function initDb(): DbInstance {
const userDataPath = app.getPath('userData');
const dbPath = path.join(userDataPath, 'adiuva.db');
const sqlite = new Database(dbPath);
// Enable WAL mode for better concurrent read performance
sqlite.pragma('journal_mode = WAL');
// Run non-destructive migrations on every start
sqlite.exec(MIGRATION_SQL);
// Additive column migrations (SQLite has no ADD COLUMN IF NOT EXISTS)
try { sqlite.exec('ALTER TABLE tasks ADD COLUMN is_ai_suggested INTEGER NOT NULL DEFAULT 0'); } catch { /* already exists */ }
try { sqlite.exec('ALTER TABLE tasks ADD COLUMN is_approved INTEGER NOT NULL DEFAULT 1'); } catch { /* already exists */ }
dbInstance = drizzle(sqlite, { schema });
return dbInstance;
}
export function getDb(): DbInstance {
if (!dbInstance) {
throw new Error('Database not initialized. Call initDb() first.');
}
return dbInstance;
}