1use anyhow::Result;
4use rusqlite::{Connection, OpenFlags};
5use std::path::{Path, PathBuf};
6use std::sync::Mutex;
7
8pub mod events;
9pub mod schema;
10pub mod sessions;
11pub mod transcripts;
12
13pub struct Database {
15 path: PathBuf,
16 conn: Mutex<Option<Connection>>,
17}
18
19impl Database {
20 pub fn new(project_root: &Path) -> Self {
21 let path = project_root.join(".scud").join("scud.db");
22 Self {
23 path,
24 conn: Mutex::new(None),
25 }
26 }
27
28 pub fn connection(&self) -> Result<std::sync::MutexGuard<'_, Option<Connection>>> {
30 let mut guard = self.conn.lock().unwrap();
31 if guard.is_none() {
32 let conn = Connection::open_with_flags(
33 &self.path,
34 OpenFlags::SQLITE_OPEN_READ_WRITE
35 | OpenFlags::SQLITE_OPEN_CREATE
36 | OpenFlags::SQLITE_OPEN_FULL_MUTEX,
37 )?;
38 conn.execute_batch("PRAGMA journal_mode=WAL;")?;
41 *guard = Some(conn);
42 }
43 Ok(guard)
44 }
45
46 pub fn initialize(&self) -> Result<()> {
48 let guard = self.connection()?;
49 let conn = guard.as_ref().unwrap();
50 schema::create_tables(conn)?;
51 Ok(())
52 }
53
54 pub fn path(&self) -> &Path {
55 &self.path
56 }
57}