import semver from "semver"; import { isNonSemverSpecifier, passthroughResolver, readDeclaredVersion, type SpecifierResolver, type VersionFinding, type WorkspacePackage, } from "./shared"; export interface CompatEntry { range: string; rationale: string; } export const compat: Record = { "@tailor-platform/sdk": { range: "^2.2.0", rationale: "erp-kit resolver/executor code relies on the v2 API surface (TailorPrincipal-based caller/invoker, Attributes module augmentation, db.table) released in 2.0.0, the scaffold closes its resolver namespace to anonymous callers with the namespace-level `defaultPermission` added in 2.1.0, and every module's create/read generics are typed with TailorDBInsertable / TailorDBSelectable from @tailor-platform/sdk/kysely, added in 2.2.0.", }, "@tailor-platform/app-shell": { range: "^1.3.0", rationale: "The frontend skill reads the app-shell-patterns skill bundled in this package (shipped since 1.3.0).", }, }; export function checkCompatRange( packages: WorkspacePackage[], resolve: SpecifierResolver = passthroughResolver, ): VersionFinding[] { const findings: VersionFinding[] = []; for (const [pkgName, entry] of Object.entries(compat)) { for (const pkg of packages) { const raw = readDeclaredVersion(pkg.manifest, pkgName); if (raw === undefined) continue; const { spec, display, unresolvedCatalog } = resolve(raw, pkgName); if (unresolvedCatalog) { findings.push({ severity: "warning", check: "compat-range", subject: pkg.relativePath, message: `${pkgName}@${raw} references a pnpm catalog entry that couldn't be resolved; cannot verify against compat range ${entry.range}. Ensure dependencies are installed and the catalog defines it.`, }); continue; } if (isNonSemverSpecifier(spec)) { findings.push({ severity: "warning", check: "compat-range", subject: pkg.relativePath, message: `${pkgName}@${display} uses a non-semver specifier; cannot verify against compat range ${entry.range}. Pin an exact version.`, }); continue; } if (semver.valid(spec)) { if (!semver.satisfies(spec, entry.range)) { findings.push({ severity: "error", check: "compat-range", subject: pkg.relativePath, message: `${pkgName}@${display} does not satisfy erp-kit compat range ${entry.range}. ${entry.rationale}`, }); } continue; } if (!semver.validRange(spec)) { findings.push({ severity: "error", check: "compat-range", subject: pkg.relativePath, message: `${pkgName}@${display} is not a valid version or range. Pin to an exact version inside ${entry.range}.`, }); continue; } // valid range that is not a single version if (semver.subset(spec, entry.range)) { findings.push({ severity: "warning", check: "compat-range", subject: pkg.relativePath, message: `${pkgName}@${display} should be pinned to an exact version so an unintended one can't be installed.`, }); } else { findings.push({ severity: "error", check: "compat-range", subject: pkg.relativePath, message: `${pkgName}@${display} admits versions outside erp-kit compat range ${entry.range}; pin an exact version. ${entry.rationale}`, }); } } } return findings; }