feat: first cut on M0 - base structure of project
This commit is contained in:
49
crates/bds-core/src/db/connection.rs
Normal file
49
crates/bds-core/src/db/connection.rs
Normal file
@@ -0,0 +1,49 @@
|
||||
use rusqlite::Connection;
|
||||
use std::path::Path;
|
||||
use crate::db::migrations;
|
||||
|
||||
/// Database wrapper managing a SQLite connection.
|
||||
pub struct Database {
|
||||
conn: Connection,
|
||||
}
|
||||
|
||||
impl Database {
|
||||
/// Open an existing bDS project database.
|
||||
pub fn open(path: &Path) -> Result<Self, rusqlite::Error> {
|
||||
let conn = Connection::open(path)?;
|
||||
conn.execute_batch("PRAGMA journal_mode=WAL; PRAGMA foreign_keys=ON;")?;
|
||||
Ok(Self { conn })
|
||||
}
|
||||
|
||||
/// Open an in-memory database (for tests).
|
||||
pub fn open_in_memory() -> Result<Self, rusqlite::Error> {
|
||||
let conn = Connection::open_in_memory()?;
|
||||
conn.execute_batch("PRAGMA foreign_keys=ON;")?;
|
||||
Ok(Self { conn })
|
||||
}
|
||||
|
||||
/// Get a reference to the underlying connection.
|
||||
pub fn conn(&self) -> &Connection {
|
||||
&self.conn
|
||||
}
|
||||
|
||||
/// Run all pending migrations.
|
||||
pub fn migrate(&self) -> Result<(), Box<dyn std::error::Error>> {
|
||||
migrations::run_migrations(&self.conn)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn open_in_memory() {
|
||||
let db = Database::open_in_memory().expect("should open in-memory db");
|
||||
let result: i64 = db
|
||||
.conn()
|
||||
.query_row("SELECT 1", [], |row| row.get(0))
|
||||
.unwrap();
|
||||
assert_eq!(result, 1);
|
||||
}
|
||||
}
|
||||
22
crates/bds-core/src/db/migrations.rs
Normal file
22
crates/bds-core/src/db/migrations.rs
Normal file
@@ -0,0 +1,22 @@
|
||||
use rusqlite::Connection;
|
||||
|
||||
/// Run all embedded migrations against the given connection.
|
||||
///
|
||||
/// For M0, this is a stub. Once we have the full schema from the TypeScript
|
||||
/// app's migrations, we will embed them via refinery.
|
||||
pub fn run_migrations(conn: &Connection) -> Result<(), Box<dyn std::error::Error>> {
|
||||
// TODO(M0): Embed real migrations from the TypeScript app's schema.
|
||||
// For now, create the minimal tables needed for read-access verification.
|
||||
conn.execute_batch(
|
||||
"
|
||||
CREATE TABLE IF NOT EXISTS projects (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
path TEXT NOT NULL,
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
",
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
5
crates/bds-core/src/db/mod.rs
Normal file
5
crates/bds-core/src/db/mod.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
mod connection;
|
||||
mod migrations;
|
||||
|
||||
pub use connection::Database;
|
||||
pub use migrations::run_migrations;
|
||||
Reference in New Issue
Block a user