const Database = require("better-sqlite3"); const path = require("node:path"); const dbPath = path.resolve("data", "leistungsbilanz.db"); const db = new Database(dbPath, { readonly: true }); const requiredTables = [ "circuit_sections", "circuits", "circuit_device_rows", "legacy_consumer_circuit_migrations", "legacy_consumer_migration_reports", ]; const rows = db .prepare("SELECT name FROM sqlite_master WHERE type='table' AND name IN (?, ?, ?, ?, ?)") .all(...requiredTables); const existing = new Set(rows.map((row) => row.name)); const missing = requiredTables.filter((name) => !existing.has(name)); const requiredProjectDeviceColumns = [ "phase_type", "connection_kind", "cost_group", "power_per_unit", "simultaneity_factor", "cos_phi", "remark", ]; const projectDeviceColumns = new Set( db.prepare("PRAGMA table_info(project_devices)").all().map((column) => column.name) ); const missingProjectDeviceColumns = requiredProjectDeviceColumns.filter( (name) => !projectDeviceColumns.has(name) ); const removedProjectDeviceColumns = [ "installed_power_per_unit_kw", "demand_factor", "phase_count", "power_factor", "note", ]; const remainingRemovedProjectDeviceColumns = removedProjectDeviceColumns.filter( (name) => projectDeviceColumns.has(name) ); const requiredCircuitColumns = ["control_requirement"]; const circuitColumns = new Set( db.prepare("PRAGMA table_info(circuits)").all().map((column) => column.name) ); const missingCircuitColumns = requiredCircuitColumns.filter((name) => !circuitColumns.has(name)); const requiredProjectColumns = [ "internal_project_number", "external_project_number", "building_owner", "description", "enabled_distribution_board_supply_types", ]; const projectColumns = new Set( db.prepare("PRAGMA table_info(projects)").all().map((column) => column.name) ); const missingProjectColumns = requiredProjectColumns.filter( (name) => !projectColumns.has(name) ); const requiredDistributionBoardColumns = ["floor_id", "supply_type"]; const distributionBoardColumns = new Set( db .prepare("PRAGMA table_info(distribution_boards)") .all() .map((column) => column.name) ); const missingDistributionBoardColumns = requiredDistributionBoardColumns.filter( (name) => !distributionBoardColumns.has(name) ); const integrityCheck = db.pragma("integrity_check", { simple: true }); const foreignKeyViolations = db.pragma("foreign_key_check"); console.log("Database:", dbPath); console.log("Required tables:", requiredTables.join(", ")); console.log("Existing tables:", [...existing].join(", ") || "(none)"); console.log("Required project-device columns:", requiredProjectDeviceColumns.join(", ")); console.log("Required circuit columns:", requiredCircuitColumns.join(", ")); console.log("Required project columns:", requiredProjectColumns.join(", ")); console.log( "Required distribution-board columns:", requiredDistributionBoardColumns.join(", ") ); console.log("Integrity:", integrityCheck); console.log("Foreign-key violations:", foreignKeyViolations.length); if (missing.length > 0) { console.error("Missing tables:", missing.join(", ")); process.exit(1); } if (missingProjectDeviceColumns.length > 0) { console.error("Missing project-device columns:", missingProjectDeviceColumns.join(", ")); process.exit(1); } if (remainingRemovedProjectDeviceColumns.length > 0) { console.error( "Transitional project-device columns still present:", remainingRemovedProjectDeviceColumns.join(", ") ); process.exit(1); } if (missingCircuitColumns.length > 0) { console.error("Missing circuit columns:", missingCircuitColumns.join(", ")); process.exit(1); } if (missingProjectColumns.length > 0) { console.error("Missing project columns:", missingProjectColumns.join(", ")); process.exit(1); } if (missingDistributionBoardColumns.length > 0) { console.error( "Missing distribution-board columns:", missingDistributionBoardColumns.join(", ") ); process.exit(1); } if (integrityCheck !== "ok" || foreignKeyViolations.length > 0) { console.error("Database integrity or foreign-key verification failed."); process.exit(1); } console.log("Circuit-first schema verification passed.");