feat(02-01): create database connection factory
- src/db/config.ts: getDbPath() returns ~/.cw/data/cw.db with CW_DB_PATH override - src/db/index.ts: createDatabase() factory with WAL mode and foreign keys - drizzle.config.ts: Drizzle Kit configuration for migrations Pattern: Factory function (not singleton) allows isolated test instances
This commit is contained in:
12
drizzle.config.ts
Normal file
12
drizzle.config.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { defineConfig } from 'drizzle-kit';
|
||||
import { join } from 'node:path';
|
||||
import { homedir } from 'node:os';
|
||||
|
||||
export default defineConfig({
|
||||
schema: './src/db/schema.ts',
|
||||
out: './drizzle',
|
||||
dialect: 'sqlite',
|
||||
dbCredentials: {
|
||||
url: process.env.CW_DB_PATH ?? join(homedir(), '.cw', 'data', 'cw.db'),
|
||||
},
|
||||
});
|
||||
33
src/db/config.ts
Normal file
33
src/db/config.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import { mkdirSync } from 'node:fs';
|
||||
import { dirname, join } from 'node:path';
|
||||
import { homedir } from 'node:os';
|
||||
|
||||
/**
|
||||
* Get the database path.
|
||||
*
|
||||
* - Default: ~/.cw/data/cw.db
|
||||
* - Override via CW_DB_PATH environment variable
|
||||
* - For testing, pass ':memory:' as CW_DB_PATH
|
||||
*/
|
||||
export function getDbPath(): string {
|
||||
const envPath = process.env.CW_DB_PATH;
|
||||
if (envPath) {
|
||||
return envPath;
|
||||
}
|
||||
|
||||
return join(homedir(), '.cw', 'data', 'cw.db');
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the parent directory for the database file exists.
|
||||
* No-op for in-memory databases.
|
||||
*/
|
||||
export function ensureDbDirectory(dbPath: string): void {
|
||||
// Skip for in-memory database
|
||||
if (dbPath === ':memory:') {
|
||||
return;
|
||||
}
|
||||
|
||||
const dir = dirname(dbPath);
|
||||
mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
43
src/db/index.ts
Normal file
43
src/db/index.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import Database from 'better-sqlite3';
|
||||
import { drizzle } from 'drizzle-orm/better-sqlite3';
|
||||
import type { BetterSQLite3Database } from 'drizzle-orm/better-sqlite3';
|
||||
|
||||
import { getDbPath, ensureDbDirectory } from './config.js';
|
||||
import * as schema from './schema.js';
|
||||
|
||||
export type DrizzleDatabase = BetterSQLite3Database<typeof schema>;
|
||||
|
||||
/**
|
||||
* Create a new database connection.
|
||||
*
|
||||
* This is a factory function (not a singleton) to allow multiple instances
|
||||
* for testing with isolated databases.
|
||||
*
|
||||
* @param path - Optional path override. Defaults to getDbPath().
|
||||
* Use ':memory:' for in-memory testing database.
|
||||
* @returns Drizzle database instance with schema
|
||||
*/
|
||||
export function createDatabase(path?: string): DrizzleDatabase {
|
||||
const dbPath = path ?? getDbPath();
|
||||
|
||||
// Ensure directory exists for file-based databases
|
||||
ensureDbDirectory(dbPath);
|
||||
|
||||
// Create SQLite connection
|
||||
const sqlite = new Database(dbPath);
|
||||
|
||||
// Enable WAL mode for better concurrent read performance
|
||||
sqlite.pragma('journal_mode = WAL');
|
||||
|
||||
// Enable foreign keys (SQLite has them disabled by default)
|
||||
sqlite.pragma('foreign_keys = ON');
|
||||
|
||||
// Create Drizzle instance with schema
|
||||
return drizzle(sqlite, { schema });
|
||||
}
|
||||
|
||||
// Re-export config utilities
|
||||
export { getDbPath, ensureDbDirectory } from './config.js';
|
||||
|
||||
// Re-export schema and types
|
||||
export * from './schema.js';
|
||||
15
src/db/schema.ts
Normal file
15
src/db/schema.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Database schema for Codewalk District.
|
||||
*
|
||||
* Defines the four-level task hierarchy:
|
||||
* - Initiative: Top-level project
|
||||
* - Phase: Major milestone within initiative
|
||||
* - Plan: Group of related tasks within phase
|
||||
* - Task: Individual work item
|
||||
*
|
||||
* Schema will be defined in Task 3.
|
||||
*/
|
||||
|
||||
// Placeholder export to allow index.ts to compile
|
||||
// Full schema defined in Task 3
|
||||
export {};
|
||||
Reference in New Issue
Block a user