From 6903e664190775527ca0fd75696196eb8e94ea23 Mon Sep 17 00:00:00 2001 From: jason Date: Mon, 9 Mar 2026 22:23:41 -0500 Subject: [PATCH] feat(db): add is_champion to dogs, kennel settings columns, migrate existing rows --- server/db/init.js | 157 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 156 insertions(+), 1 deletion(-) diff --git a/server/db/init.js b/server/db/init.js index 0228cd4..bc7d937 100644 --- a/server/db/init.js +++ b/server/db/init.js @@ -1 +1,156 @@ -Y29uc3QgRGF0YWJhc2UgPSByZXF1aXJlKCdiZXR0ZXItc3FsaXRlMycpOwpjb25zdCBwYXRoID0gcmVxdWlyZSgncGF0aCcpOwpjb25zdCBmcyA9IHJlcXVpcmUoJ2ZzJyk7CgpmdW5jdGlvbiBpbml0RGF0YWJhc2UoZGJQYXRoKSB7CiAgY29uc3QgZGlyID0gcGF0aC5kaXJuYW1lKGRiUGF0aCk7CiAgaWYgKCFmcy5leGlzdHNTeW5jKGRpcikpIHsKICAgIGZzLm1rZGlyU3luYyhkaXIsIHsgcmVjdXJzaXZlOiB0cnVlIH0pOwogIH0KCiAgY29uc3QgZGIgPSBuZXcgRGF0YWJhc2UoZGJQYXRoKTsKICBkYi5wcmFnbWEoJ2ZvcmVpZ25fa2V5cyA9IE9OJyk7CiAgY29uc29sZS5sb2coJ0luaXRpYWxpemluZyBkYXRhYmFzZSBzY2hlbWEuLi4nKTsKCiAgLy8gRG9ncyB0YWJsZSAtIGluY2x1ZGVzIGlzX2NoYW1waW9uIGZsYWcKICBkYi5leGVjKGAKICAgIENSRUFURSBUQUJMRSBJRiBOT1QgRVhJU1RTIGRvZ3MgKAogICAgICBpZCBJTlRFR0VSIFBSSU1BUlkgS0VZIEFVVE9JTkNSRU1FTlQsCiAgICAgIG5hbWUgVEVYVCBOT1QgTlVMTCwKICAgICAgcmVnaXN0cmF0aW9uX251bWJlciBURVhUIFVOSVFVRSwKICAgICAgYnJlZWQgVEVYVCBOT1QgTlVMTCwKICAgICAgc2V4IFRFWFQgTk9UIE5VTEwgQ0hFQ0soc2V4IElOICgnbWFsZScsICdmZW1hbGUnKSksCiAgICAgIGJpcnRoX2RhdGUgREFURSwKICAgICAgY29sb3IgVEVYVCwKICAgICAgbWljcm9jaGlwIFRFWFQsCiAgICAgIHBob3RvX3VybHMgVEVYVCwKICAgICAgbm90ZXMgVEVYVCwKICAgICAgbGl0dGVyX2lkIElOVEVHRVIsCiAgICAgIGlzX2FjdGl2ZSBJTlRFR0VSIERFRkFVTFQgMSwKICAgICAgaXNfY2hhbXBpb24gSU5URUdFUiBERUZBVUxUIDAsCiAgICAgIGNyZWF0ZWRfYXQgREFURVRJTUUgREVGQVVMVCBDVVJSRU5UX1RJTUVTVEFNUCwKICAgICAgdXBkYXRlZF9hdCBEQVRFVElNRSBERUZBVUxUIENVUlJFTlRfVElNRVNUQU1QLAogICAgICBGT1JFSUdOIEtFWSAobGl0dGVyX2lkKSBSRUZFUkVOQ0VTIGxpdHRlcnMoaWQpIE9OIERFTEVURSBTRVQgTlVMTAogICAgKQogIGApOwoKICAvLyBTZXR0aW5ncyB0YWJsZSAtIGtlbm5lbCBuYW1lICsgaW5mbwogIGRiLmV4ZWMoYAogICAgQ1JFQVRFIFRBQkxFIElGIE5PVCBFWElTVFMgc2V0dGluZ3MgKAogICAgICBrZXkgVEVYVCBQUklNQVJZIEtFWSwKICAgICAgdmFsdWUgVEVYVAogICAgKQogIGApOwoKICAvLyBJbnNlcnQgZGVmYXVsdHMgaWYgbm90IHByZXNlbnQKICBkYi5wcmVwYXJlKGBJTlNFUlQgT1IgSUdOT1JFIElOVE8gc2V0dGluZ3MgKGtleSwgdmFsdWUpIFZBTFVFUyAoPywgPylgKS5ydW4oJ2tlbm5lbF9uYW1lJywgJ015IEtlbm5lbCcpOwogIGRiLnByZXBhcmUoYElOU0VSVCBPUiBJR05PUkUgSU5UTyBzZXR0aW5ncyAoa2V5LCB2YWx1ZSkgVkFMVUVTICg/LCA/KWApLnJ1bignS2VubmVsX3Bob25lJywgJycpOwogIGRiLnByZXBhcmUoYElOU0VSVCBPUiBJR05PUkUgSU5UTyBzZXR0aW5ncyAoa2V5LCB2YWx1ZSkgVkFMVUVTICg/LCA/KWApLnJ1bignS2VubmVsX2VtYWlsJywgJycpOwogIGRiLnByZXBhcmUoYElOU0VSVCBPUiBJR05PUkUgSU5UTyBzZXR0aW5ncyAoa2V5LCB2YWx1ZSkgVkFMVUVTICg/LCA/KWApLnJ1bignS2VubmVsX2xvY2F0aW9uJywgJycpOwogIGRiLnByZXBhcmUoYElOU0VSVCBPUiBJR05PUkUgSU5UTyBzZXR0aW5ncyAoa2V5LCB2YWx1ZSkgVkFMVUVTICg/LCA/KWApLnJ1bignS2VubmVsX25vdGVzJywgJycpOwoKICAvLyBNaWdyYXRpb246IGFkZCBpc19jaGFtcGlvbiBpZiBtaXNzaW5nIG9uIGV4aXN0aW5nIERCcwogIHRyeSB7CiAgICBkYi5leGVjKCdBTFRFUiBUQUJMRSBkb2dzIEFERCBDT0xVTU4gaXNfY2hhbXBpb24gSU5URUdFUiBERUZBVUxUIDAeKTsKICB9IGNhdGNoIChlKSB7CiAgICAvLyBDb2x1bW4gYWxyZWFkeSBleGlzdHMgLSBpZ25vcmUKICB9CgogIGRiLmV4ZWMoYAogICAgQ1JFQVRFIFVOSVFVRSBJTkRFWCBJRiBOT1QgRVhJU1RTIGlkeF9kb2dzX21pY3JvY2hpcAogICAgT04gZG9ncyhtaWNyb2NoaXApCiAgICBXSEVSRSBtaWNyb2NoaXAgSVMgTk9UIE5VTEwKICBgKTsKCiAgZGIuZXhlYyhgCiAgICBDUkVBVEUgVEFCTEUgSUYgTk9UIEVYSVNUUyBwYXJlbnRzICgKICAgICAgaWQgSU5URUdFUiBQUklNQVJZIEtFWSBBVVRPSU5DUkVNRU5ULAogICAgICBkb2dfaWQgSU5URUdFUiBOT1QgTlVMTCwKICAgICAgcGFyZW50X2lkIElOVEVHRVIgTk9UIE5VTEwsCiAgICAgIHBhcmVudF90eXBlIFRFWFQgTk9UIE5VTEwgQ0hFQ0socGFyZW50X3R5cGUgSU4gKCdzaXJlJywgJ2RhbScpKSwKICAgICAgRk9SRUlHTiBLRVkgKGRvZ19pZCkgUkVGRVJFTkNFUyBkb2dzKGlkKSBPTiBERUxFVEUgQ0FTQ0FERSwKICAgICAgRk9SRUlHTiBLRVkgKHBhcmVudF9pZCkgUkVGRVJFTkNFUyBkb2dzKGlkKSBPTiBERUxFVEUgQ0FTQ0FERSwKICAgICAgVU5JUVVFKGRvZ19pZCwgcGFyZW50X3R5cGUpCiAgICApCiAgYCk7CgogIGRiLmV4ZWMoYAogICAgQ1JFQVRFIFRBQkxFIElGIE5PVCBFWElTVFMgbGl0dGVycyAoCiAgICAgIGlkIElOVEVHRVIgUFJJTUFSWSBLRVkgQVVUT0lOQ1JFTUVOVCwKICAgICAgc2lyZV9pZCBJTlRFR0VSIE5PVCBOVUxMLAogICAgICBkYW1faWQgSU5URUdFUiBOT1QgTlVMTCwKICAgICAgYnJlZWRpbmdfZGF0ZSBEQVRFIE5PVCBOVUxMLAogICAgICB3aGVscGluZ19kYXRlIERBVEUsCiAgICAgIHB1cHB5X2NvdW50IElOVEVHRVIgREVGQVVMVCAwLAogICAgICBub3RlcyBURVhULAogICAgICBjcmVhdGVkX2F0IERBVEVUSU1FIERFRkFVTFQgQ1VSUkVOVF9USU1FU1RBTVAsCiAgICAgIEZPUkVJR04gS0VZIChzaXJlX2lkKSBSRUZFUkVOQ0VTIGRvZ3MoaWQpIE9OIERFTEVURSBDQVNDQURFLAogICAgICBGT1JFSUdOIEtFWSAoZGFtX2lkKSBSRUZFUkVOQ0VTIGRvZ3MoaWQpIE9OIERFTEVURSBDQVNDQURFCiAgICApCiAgYCk7CgogIGRiLmV4ZWMoYAogICAgQ1JFQVRFIFRBQkxFIElGIE5PVCBFWElTVFMgaGVhbHRoX3JlY29yZHMgKAogICAgICBpZCBJTlRFR0VSIFBSSU1BUlkgS0VZIEFVVE9JTkNSRU1FTlQsCiAgICAgIGRvZ19pZCBJTlRFR0VSIE5PVCBOVUxMLAogICAgICByZWNvcmRfdHlwZSBURVhUIE5PVCBOVUxMIENIRUNLKHJlY29yZF90eXBlIElOICgndGVzdCcsICd2YWNjaW5hdGlvbicsICdleGFtJywgJ3RyZWF0bWVudCcsICdjZXJ0aWZpY2F0aW9uJykpLAogICAgICB0ZXN0X25hbWUgVEVYVCwKICAgICAgdGVzdF9kYXRlIERBVEUgTk9UIE5VTEwsCiAgICAgIHJlc3VsdCBURVhULAogICAgICBkb2N1bWVudF91cmwgVEVYVCwKICAgICAgbm90ZXMgVEVYVCwKICAgICAgY3JlYXRlZF9hdCBEQVRFVElNRSBERUZBVUxUIENVUlJFTlRfVElNRVNUQU1QLAogICAgICBGT1JFSUdOIEtFWSAoZG9nX2lkKSBSRUZFUkVOQ0VTIGRvZ3MoaWQpIE9OIERFTEVURSBDQVNDQURFCiAgICApCiAgYCk7CgogIGRiLmV4ZWMoYAogICAgQ1JFQVRFIFRBQkxFIElGIE5PVCBFWElTVFMgaGVhdF9jeWNsZXMgKAogICAgICBpZCBJTlRFR0VSIFBSSU1BUlkgS0VZIEFVVE9JTkNSRU1FTlQsCiAgICAgIGRvZ19pZCBJTlRFR0VSIE5PVCBOVUxMLAogICAgICBzdGFydF9kYXRlIERBVEUgTk9UIE5VTEwsCiAgICAgIGVuZF9kYXRlIERBVEUsCiAgICAgIHByb2dlc3Rlcm9uZV9wZWFrX2RhdGUgREFURSwKICAgICAgYnJlZWRpbmdfZGF0ZSBEQVRFLAogICAgICBicmVlZGluZ19zdWNjZXNzZnVsIElOVEVHRVIgREVGQVVMVCAwLAogICAgICBub3RlcyBURVhULAogICAgICBjcmVhdGVkX2F0IERBVEVUSU1FIERFRkFVTFQgQ1VSUkVOVF9USU1FU1RBTVAsCiAgICAgIEZPUkVJR04gS0VZIChkb2dfaWQpIFJFRkVSRU5DRVMgZG9ncyhpZCkgT04gREVMRVRFIENBU0NBREUKICAgICkKICBgKTsKCiAgZGIuZXhlYyhgCiAgICBDUkVBVEUgVEFCTEUgSUYgTk9UIEVYSVNUUyB0cmFpdHMgKAogICAgICBpZCBJTlRFR0VSIFBSSU1BUlkgS0VZIEFVVE9JTkNSRU1FTlQsCiAgICAgIGRvZ19pZCBJTlRFR0VSIE5PVCBOVUxMLAogICAgICB0cmFpdF9jYXRlZ29yeSBURVhUIE5PVCBOVUxMLAogICAgICB0cmFpdF9uYW1lIFRFWFQgTk9UIE5VTEwsCiAgICAgIHRyYWl0X3ZhbHVlIFRFWFQgTk9UIE5VTEwsCiAgICAgIGluaGVyaXRlZF9mcm9tIElOVEVHRVIsCiAgICAgIG5vdGVzIFRFWFQsCiAgICAgIEZPUkVJR04gS0VZIChkb2dfaWQpIFJFRkVSRU5DRVMgZG9ncyhpZCkgT04gREVMRVRFIENBU0NBREUsCiAgICAgIEZPUkVJR04gS0VZIChpbmhlcml0ZWRfZnJvbSkgUkVGRVJFTkNFUyBkb2dzKGlkKSBPTiBERUxFVEUgU0VUIE5VTEwKICAgICkKICBgKTsKCiAgZGIuZXhlYyhgCiAgICBDUkVBVEUgSU5ERVggSUYgTk9UIEVYSVNUUyBpZHhfZG9nc19uYW1lIE9OIGRvZ3MobmFtZSk7CiAgICBDUkVBVEUgSU5ERVggSUYgTk9UIEVYSVNUUyBpZHhfZG9nc19yZWdpc3RyYXRpb24gT04gZG9ncyhyZWdpc3RyYXRpb25fbnVtYmVyKTsKICAgIENSRUFURSBJTkRFWCBJRiBOT1QgRVhJU1RTIGlkeF9kb2dzX2xpdHRlciBPTiBkb2dzKGxpdHRlcl9pZCk7CiAgICBDUkVBVEUgSU5ERVggSUYgTk9UIEVYSVNUUyBpZHhfcGFyZW50c19kb2cgT04gcGFyZW50cyhkb2dfaWQpOwogICAgQ1JFQVRFIElOREVYIElGIE5PVCBFWElTVFMgaWR4X3BhcmVudHNfcGFyZW50IE9OIHBhcmVudHMocGFyZW50X2lkKTsKICAgIENSRUFURSBJTkRFWCBJRiBOT1QgRVhJU1RTIGlkeF9saXR0ZXJzX3NpcmUgT04gbGl0dGVycyhzaXJlX2lkKTsKICAgIENSRUFURSBJTkRFWCBJRiBOT1QgRVhJU1RTIGlkeF9saXR0ZXJzX2RhbSBPTiBsaXR0ZXJzKGRhbV9pZCk7CiAgICBDUkVBVEUgSU5ERVggSUYgTk9UIEVYSVNUUyBpZHhfaGVhbHRoX2RvZyBPTiBoZWFsdGhfcmVjb3Jkcyhkb2dfaWQpOwogICAgQ1JFQVRFIElOREVYIElGIE5PVCBFWElTVFMgaWR4X2hlYXRfZG9nIE9OIGhlYXRfY3ljbGVzKGRvZ19pZCk7CiAgICBDUkVBVEUgSU5ERVggSUYgTk9UIEVYSVNUUyBpZHhfdHJhaXRzX2RvZyBPTiB0cmFpdHMoZG9nX2lkKTsKICBgKTsKCiAgZGIuZXhlYyhgCiAgICBDUkVBVEUgVFJJR0dFUiBJRiBOT1QgRVhJU1RTIHVwZGF0ZV9kb2dzX3RpbWVzdGFtcAogICAgQUZURVIgVVBEQVRFIE9OIGRvZ3MKICAgIEZPUiBFQUNIIFJPVwogICAgQkVHSU4KICAgICAgVVBEQVRFIGRvZ3MgU0VUIHVwZGF0ZWRfYXQgPSBDVVJSRU5UX1RJTUVTVEFNUCBXSEVSRSBpZCA9IE5FVy5pZDsKICAgIEVORDsKICBgKTsKCiAgY29uc29sZS5sb2coJ+KckyBEYXRhYmFzZSBzY2hlbWEgaW5pdGlhbGl6ZWQgc3VjY2Vzc2Z1bGx5IScpOwogIGNvbnNvbGUubG9nKCfinJMgRG9ncyB0YWJsZTogaXNfY2hhbXBpb24gY29sdW1uIGluY2x1ZGVkJyk7CiAgY29uc29sZS5sb2coJ+KckSBTZXR0aW5ncyB0YWJsZTogS2VubmVsIG5hbWUgYW5kIGluZm8gc3VwcG9ydGVkJyk7CgogIGRiLmNsb3NlKCk7CiAgcmV0dXJuIHRydWU7Cn0KCmZ1bmN0aW9uIGdldERhdGFiYXNlKCkgewogIGNvbnN0IGRiUGF0aCA9IHByb2Nlc3MuZW52LkRCX1BBVEggfHwgcGF0aC5qb2luKF9fZGlybmFtZSwgJy4uLy4uL2RhdGEvYnJlZWRyLmRiJyk7CiAgY29uc3QgZGIgPSBuZXcgRGF0YWJhc2UoZGJQYXRoKTsKICBkYi5wcmFnbWEoJ2ZvcmVpZ25fa2V5cyA9IE9OJyk7CiAgcmV0dXJuIGRiOwp9Cgptb2R1bGUuZXhwb3J0cyA9IHsgaW5pdERhdGFiYXNlLCBnZXREYXRhYmFzZSB9OwoKaWYgKHJlcXVpcmUubWFpbiA9PT0gbW9kdWxlKSB7CiAgY29uc3QgZGJQYXRoID0gcHJvY2Vzcy5lbnYuREJfUEFUSCB8fCBwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4vLi4vZGF0YS9icmVlZHIuZGInKTsKICBjb25zb2xlLmxvZygnXG49PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PScpOwogIGNvbnNvbGUubG9nKCdCUkVFRFIgRGF0YWJhc2UgSW5pdGlhbGl6YXRpb24nKTsKICBjb25zb2xlLmxvZygnPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09Jyk7CiAgY29uc29sZS5sb2coYERhdGFiYXNlOiAke2RiUGF0aH1gKTsKICBjb25zb2xlLmxvZygnPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4nKTsKICBpbml0RGF0YWJhc2UoZGJQYXRoKTsKICBjb25zb2xlLmxvZygnXG7inJMgRGF0YWJhc2UgcmVhZHkhXG4nKTsKfQo= \ No newline at end of file +const Database = require('better-sqlite3'); +const path = require('path'); +const fs = require('fs'); + +const dbPath = path.join(__dirname, '../../data'); +const db = new Database(path.join(dbPath, 'breedr.db')); + +function getDatabase() { + return db; +} + +function initDatabase() { + db.pragma('foreign_keys = ON'); + db.pragma('journal_mode = WAL'); + + // ── Dogs ──────────────────────────────────────────────────────────── + db.exec(` + CREATE TABLE IF NOT EXISTS dogs ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + registration_number TEXT, + breed TEXT NOT NULL, + sex TEXT NOT NULL CHECK(sex IN ('male', 'female')), + birth_date TEXT, + color TEXT, + microchip TEXT, + litter_id INTEGER, + is_active INTEGER DEFAULT 1, + is_champion INTEGER DEFAULT 0, + photo_urls TEXT DEFAULT '[]', + notes TEXT, + created_at TEXT DEFAULT (datetime('now')), + updated_at TEXT DEFAULT (datetime('now')) + ) + `); + + // migrate: add is_champion if missing (safe on existing DBs) + try { + db.exec(`ALTER TABLE dogs ADD COLUMN is_champion INTEGER DEFAULT 0`); + } catch (_) { /* column already exists */ } + + // ── Parents ───────────────────────────────────────────────────────── + db.exec(` + CREATE TABLE IF NOT EXISTS parents ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + dog_id INTEGER NOT NULL, + parent_id INTEGER NOT NULL, + parent_type TEXT NOT NULL CHECK(parent_type IN ('sire', 'dam')), + FOREIGN KEY (dog_id) REFERENCES dogs(id), + FOREIGN KEY (parent_id) REFERENCES dogs(id) + ) + `); + + // ── Breeding Records ──────────────────────────────────────────────── + db.exec(` + CREATE TABLE IF NOT EXISTS breeding_records ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + sire_id INTEGER NOT NULL, + dam_id INTEGER NOT NULL, + breeding_date TEXT, + due_date TEXT, + conception_method TEXT CHECK(conception_method IN ('natural', 'ai', 'frozen', 'surgical')), + notes TEXT, + created_at TEXT DEFAULT (datetime('now')), + updated_at TEXT DEFAULT (datetime('now')), + FOREIGN KEY (sire_id) REFERENCES dogs(id), + FOREIGN KEY (dam_id) REFERENCES dogs(id) + ) + `); + + // ── Litters ───────────────────────────────────────────────────────── + db.exec(` + CREATE TABLE IF NOT EXISTS litters ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + breeding_id INTEGER, + sire_id INTEGER NOT NULL, + dam_id INTEGER NOT NULL, + whelp_date TEXT, + total_count INTEGER DEFAULT 0, + male_count INTEGER DEFAULT 0, + female_count INTEGER DEFAULT 0, + stillborn_count INTEGER DEFAULT 0, + notes TEXT, + created_at TEXT DEFAULT (datetime('now')), + updated_at TEXT DEFAULT (datetime('now')), + FOREIGN KEY (breeding_id) REFERENCES breeding_records(id), + FOREIGN KEY (sire_id) REFERENCES dogs(id), + FOREIGN KEY (dam_id) REFERENCES dogs(id) + ) + `); + + // ── Health Records ────────────────────────────────────────────────── + db.exec(` + CREATE TABLE IF NOT EXISTS health_records ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + dog_id INTEGER NOT NULL, + record_type TEXT NOT NULL, + date TEXT NOT NULL, + title TEXT NOT NULL, + description TEXT, + vet_name TEXT, + notes TEXT, + result TEXT, + next_due TEXT, + created_at TEXT DEFAULT (datetime('now')), + updated_at TEXT DEFAULT (datetime('now')), + FOREIGN KEY (dog_id) REFERENCES dogs(id) + ) + `); + + // ── Settings ───────────────────────────────────────────────────────── + db.exec(` + CREATE TABLE IF NOT EXISTS settings ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + kennel_name TEXT DEFAULT 'BREEDR', + kennel_tagline TEXT, + kennel_address TEXT, + kennel_phone TEXT, + kennel_email TEXT, + kennel_website TEXT, + kennel_akc_id TEXT, + kennel_breed TEXT, + owner_name TEXT, + created_at TEXT DEFAULT (datetime('now')), + updated_at TEXT DEFAULT (datetime('now')) + ) + `); + + // migrate: add new kennel columns if missing (safe on existing DBs) + const kennelCols = [ + ['kennel_name', "TEXT DEFAULT 'BREEDR'"], + ['kennel_tagline', 'TEXT'], + ['kennel_address', 'TEXT'], + ['kennel_phone', 'TEXT'], + ['kennel_email', 'TEXT'], + ['kennel_website', 'TEXT'], + ['kennel_akc_id', 'TEXT'], + ['kennel_breed', 'TEXT'], + ['owner_name', 'TEXT'], + ]; + for (const [col, def] of kennelCols) { + try { + db.exec(`ALTER TABLE settings ADD COLUMN ${col} ${def}`); + } catch (_) { /* already exists */ } + } + + // Seed a default settings row if none exists + const existing = db.prepare('SELECT id FROM settings LIMIT 1').get(); + if (!existing) { + db.prepare(`INSERT INTO settings (kennel_name) VALUES (?)`).run('BREEDR'); + } + + console.log('✓ Database initialized successfully'); +} + +module.exports = { getDatabase, initDatabase };