import { readFile } from "node:fs/promises"; import path from "node:path"; import { pathToFileURL } from "node:url"; import { diagnoseEkklesia, doctorExitCode, formatDoctorReport } from "../diagnostics/index.js"; interface ModuleSdkPackageDocument { readonly version?: unknown; } interface RootPackageDocument extends ModuleSdkPackageDocument { readonly engines?: { readonly node?: unknown; }; } async function readJson(pathname: string): Promise { return JSON.parse(await readFile(pathname, "utf8")) as unknown; } function rootPackageDocument(value: unknown): RootPackageDocument { if (typeof value !== "object" || value === null || Array.isArray(value)) { throw new TypeError("Invalid workspace package metadata."); } return value as RootPackageDocument; } function requiredString(value: unknown): string { if (typeof value !== "string" || value.length === 0) { throw new TypeError("Missing workspace package metadata."); } return value; } export async function runDoctorCommand(repositoryRoot = process.cwd()): Promise { const [rootValue, moduleSdkValue] = await Promise.all([ readJson(path.join(repositoryRoot, "package.json")), readJson(path.join(repositoryRoot, "packages", "module-sdk", "package.json")), ]); const rootPackage = rootPackageDocument(rootValue); const moduleSdkPackage = rootPackageDocument(moduleSdkValue); const report = await diagnoseEkklesia({ databaseUrl: process.env.DATABASE_URL, moduleDiscovery: { moduleSdkVersion: requiredString(moduleSdkPackage.version), modulesDirectory: path.join(repositoryRoot, "modules"), platformVersion: requiredString(rootPackage.version), }, runtimeRange: requiredString(rootPackage.engines?.node), runtimeVersion: process.versions.node, }); console.log(formatDoctorReport(report).join("\n")); return doctorExitCode(report); } function isDirectExecution(): boolean { const entrypoint = process.argv[1]; return ( entrypoint !== undefined && import.meta.url === pathToFileURL(path.resolve(entrypoint)).href ); } if (isDirectExecution()) { runDoctorCommand() .then((exitCode) => { process.exitCode = exitCode; }) .catch(() => { console.error("Ekklesia Doctor failed before diagnostics could be composed."); process.exitCode = 1; }); }