Files
Ekklesia/core/src/cli/validate-modules.ts
T
ekklesia 80b56b72b1
CI / verify (pull_request) Successful in 24s
CI / infrastructure-smoke (pull_request) Successful in 20s
feat: add module schema discovery and validation
2026-07-13 21:35:21 -05:00

65 lines
2.1 KiB
TypeScript

import { readFile } from "node:fs/promises";
import path from "node:path";
import {
discoverModuleSchemas,
ModuleDiscoveryError,
ModuleSchemaDiscoveryError,
} from "../modules/index.js";
interface PackageVersion {
version?: unknown;
}
async function readPackageVersion(packagePath: string): Promise<string> {
const packageData = JSON.parse(await readFile(packagePath, "utf8")) as PackageVersion;
if (typeof packageData.version !== "string") {
throw new Error(`${packagePath} does not declare a version.`);
}
return packageData.version;
}
async function main(): Promise<void> {
const repositoryRoot = process.cwd();
const [platformVersion, moduleSdkVersion] = await Promise.all([
readPackageVersion(path.join(repositoryRoot, "package.json")),
readPackageVersion(path.join(repositoryRoot, "packages/module-sdk/package.json")),
]);
const schemaAggregate = await discoverModuleSchemas({
moduleSdkVersion,
modulesDirectory: path.join(repositoryRoot, "modules"),
platformVersion,
});
const modules = schemaAggregate.discoveredModules;
if (modules.length === 0) {
console.log("Module validation passed (0 modules installed).");
return;
}
console.log(
`Module validation passed (${modules.length} modules, ${schemaAggregate.tables.length} tables):`,
);
for (const discoveredModule of modules) {
console.log(`- ${discoveredModule.manifest.id}@${discoveredModule.manifest.version}`);
}
}
main().catch((error: unknown) => {
if (error instanceof ModuleDiscoveryError) {
console.error(error.message);
for (const issue of error.issues) {
const issuePath = issue.path ? ` (${issue.path})` : "";
console.error(`[${issue.code}] ${issue.moduleDirectory}${issuePath}: ${issue.message}`);
}
} else if (error instanceof ModuleSchemaDiscoveryError) {
console.error(error.message);
for (const issue of error.issues) {
const issuePath = issue.path ? ` (${issue.path})` : "";
console.error(`[${issue.code}] ${issue.moduleId}${issuePath}: ${issue.message}`);
}
} else {
console.error(error instanceof Error ? error.message : String(error));
}
process.exitCode = 1;
});