130 lines
3.9 KiB
TypeScript
130 lines
3.9 KiB
TypeScript
import Database from 'better-sqlite3';
|
|
import { drizzle } from 'drizzle-orm/better-sqlite3';
|
|
import * as schema from '../lib/db/schema';
|
|
import { eq } from 'drizzle-orm';
|
|
import { existsSync } from 'fs';
|
|
|
|
interface InitResult {
|
|
needsMigration: boolean;
|
|
needsSeeding: boolean;
|
|
hasData: boolean;
|
|
adminExists: boolean;
|
|
summary: string;
|
|
}
|
|
|
|
async function checkDatabaseState(): Promise<InitResult> {
|
|
const dbPath = process.env.DATABASE_URL || './data/sqlite.db';
|
|
const result: InitResult = {
|
|
needsMigration: false,
|
|
needsSeeding: false,
|
|
hasData: false,
|
|
adminExists: false,
|
|
summary: ''
|
|
};
|
|
|
|
// Check if database file exists
|
|
if (!existsSync(dbPath)) {
|
|
result.needsMigration = true;
|
|
result.needsSeeding = true;
|
|
result.summary = 'Database file does not exist - full initialization needed';
|
|
return result;
|
|
}
|
|
|
|
let sqlite: Database.Database | null = null;
|
|
|
|
try {
|
|
sqlite = new Database(dbPath);
|
|
const db = drizzle(sqlite, { schema });
|
|
|
|
// Check if core tables exist by trying to query them
|
|
try {
|
|
const userCount = db.select().from(schema.users).limit(1).all();
|
|
const courtCount = db.select().from(schema.courts).limit(1).all();
|
|
const settingsCount = db.select().from(schema.settings).limit(1).all();
|
|
|
|
// Database has tables and some basic structure
|
|
result.hasData = userCount.length > 0 || courtCount.length > 0 || settingsCount.length > 0;
|
|
|
|
// Check for admin users specifically
|
|
const adminUsers = db
|
|
.select()
|
|
.from(schema.users)
|
|
.where(eq(schema.users.role, 'admin'))
|
|
.limit(1)
|
|
.all();
|
|
|
|
result.adminExists = adminUsers.length > 0;
|
|
|
|
// Determine what's needed
|
|
if (!result.hasData) {
|
|
result.needsSeeding = true;
|
|
result.summary = 'Database exists with empty tables - seeding needed';
|
|
} else if (!result.adminExists) {
|
|
result.needsSeeding = true;
|
|
result.summary = 'Database has data but no admin users found - admin creation needed';
|
|
} else {
|
|
result.summary = `Database ready - found ${userCount.length ? 'users' : 'no users'}, ${courtCount.length ? 'courts' : 'no courts'}, admin users present`;
|
|
}
|
|
} catch (tableError) {
|
|
// Tables don't exist or schema is outdated
|
|
result.needsMigration = true;
|
|
result.needsSeeding = true;
|
|
result.summary = 'Database exists but tables missing/outdated - migration and seeding needed';
|
|
}
|
|
} catch (dbError) {
|
|
// Database file exists but is corrupted or inaccessible
|
|
result.needsMigration = true;
|
|
result.needsSeeding = true;
|
|
result.summary = `Database file exists but inaccessible: ${(dbError as Error).message}`;
|
|
} finally {
|
|
if (sqlite) {
|
|
try {
|
|
sqlite.close();
|
|
} catch (e) {
|
|
// Ignore close errors
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
async function main() {
|
|
try {
|
|
console.log('🔍 Checking database state...');
|
|
const state = await checkDatabaseState();
|
|
|
|
console.log(`📊 ${state.summary}`);
|
|
console.log(` Migration needed: ${state.needsMigration ? '✅' : '❌'}`);
|
|
console.log(` Seeding needed: ${state.needsSeeding ? '✅' : '❌'}`);
|
|
console.log(` Has existing data: ${state.hasData ? '✅' : '❌'}`);
|
|
console.log(` Admin user exists: ${state.adminExists ? '✅' : '❌'}`);
|
|
|
|
// Output structured result for shell consumption
|
|
process.env.DB_NEEDS_MIGRATION = state.needsMigration.toString();
|
|
process.env.DB_NEEDS_SEEDING = state.needsSeeding.toString();
|
|
process.env.DB_HAS_DATA = state.hasData.toString();
|
|
process.env.DB_ADMIN_EXISTS = state.adminExists.toString();
|
|
|
|
// Exit codes for shell scripting
|
|
// 0 = ready, 1 = needs migration, 2 = needs seeding, 3 = needs both
|
|
if (state.needsMigration && state.needsSeeding) {
|
|
process.exit(3);
|
|
} else if (state.needsMigration) {
|
|
process.exit(1);
|
|
} else if (state.needsSeeding) {
|
|
process.exit(2);
|
|
} else {
|
|
process.exit(0);
|
|
}
|
|
} catch (error) {
|
|
console.error('❌ Database state check failed:', error);
|
|
process.exit(4); // Error state
|
|
}
|
|
}
|
|
|
|
if (require.main === module) {
|
|
main();
|
|
}
|
|
|
|
export { checkDatabaseState, type InitResult }; |