UNPKG

everything-dev

Version:

A consolidated product package for building Module Federation apps with oRPC APIs.

113 lines (111 loc) 4.08 kB
import { extractExpectedTables, getMigrationStorage, pluginMigrationSlug } from "../db.mjs"; import { existsSync, readFileSync } from "node:fs"; import { join, resolve } from "node:path"; import { createHash } from "node:crypto"; //#region src/cli/db-doctor.ts function hashFile(raw) { return createHash("sha256").update(raw).digest("hex"); } function readLocalMigrations(workspaceDir) { const migrationsDir = resolve(workspaceDir, "src/db/migrations"); const journalPath = join(join(migrationsDir, "meta"), "_journal.json"); if (!existsSync(journalPath)) return []; return JSON.parse(readFileSync(journalPath, "utf8")).entries.map((entry) => { const sqlPath = join(migrationsDir, `${entry.tag}.sql`); if (!existsSync(sqlPath)) return { tag: entry.tag, hash: "", sql: [] }; const raw = readFileSync(sqlPath, "utf8"); const sql = raw.split("--> statement-breakpoint").map((s) => s.trim()); return { tag: entry.tag, hash: hashFile(raw), sql }; }); } async function diagnosePlugin(info) { const { Pool } = await import("../node_modules/pg/esm/index.mjs"); const slug = pluginMigrationSlug(info.key); const storage = getMigrationStorage(slug); const journalTable = storage.table; const journalSchema = storage.schema; const journalRef = `"${journalSchema}"."${journalTable}"`; const localMigrations = info.workspaceDir ? readLocalMigrations(info.workspaceDir) : []; const expectedTables = extractExpectedTables(localMigrations); const localHashes = localMigrations.map((m) => m.hash).filter(Boolean); const migrationHashes = localHashes; const pool = new Pool({ connectionString: info.databaseUrl, ssl: info.databaseUrl.includes("localhost") || info.databaseUrl.includes("127.0.0.1") ? false : { rejectUnauthorized: false }, max: 1, connectionTimeoutMillis: 1e4 }); try { const journalExists = await pool.query(` SELECT EXISTS ( SELECT 1 FROM information_schema.tables WHERE table_schema = '${journalSchema}' AND table_name = '${journalTable}' ) AS exists `); let appliedHashCount = 0; if (journalExists.rows[0]?.exists) appliedHashCount = (await pool.query(`SELECT hash FROM ${journalRef}`)).rows.length; let missingTables = []; if (expectedTables.length > 0) { const tableResult = await pool.query(` SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' AND table_name = ANY($1) `, [expectedTables]); const existing = new Set(tableResult.rows.map((r) => r.table_name)); missingTables = expectedTables.filter((t) => !existing.has(t)); } let diagnosis; if (localMigrations.length === 0) diagnosis = "no-local-migrations"; else if (appliedHashCount === 0 && missingTables.length === 0 && localHashes.length > 0) diagnosis = "untracked-existing-schema"; else if (appliedHashCount === 0 && localHashes.length > 0) diagnosis = "unapplied"; else if (missingTables.length === 0) diagnosis = "healthy"; else if (missingTables.length === expectedTables.length) diagnosis = "drift-safe-repair"; else diagnosis = "drift-manual"; const masked = info.databaseUrl.replace(/\/\/[^:]+:[^@]+@/, "//***:***@"); return { plugin: info.key, slug, journalTable, journalSchema, dbSecret: info.databaseSecret, dbUrl: masked, workspaceDir: info.workspaceDir, localMigrationCount: localMigrations.length, appliedHashCount, expectedTables, missingTables, migrationHashes, diagnosis }; } catch (error) { return { plugin: info.key, slug, journalTable, journalSchema, dbSecret: info.databaseSecret, dbUrl: info.databaseUrl.replace(/\/\/[^:]+:[^@]+@/, "//***:***@"), workspaceDir: info.workspaceDir, localMigrationCount: localMigrations.length, appliedHashCount: 0, expectedTables, missingTables: [], migrationHashes: [], diagnosis: "error", error: error instanceof Error ? error.message : String(error) }; } finally { await pool.end().catch(() => {}); } } //#endregion export { diagnosePlugin }; //# sourceMappingURL=db-doctor.mjs.map