import type { WrnexusPackageManifest } from "./types.ts"; export interface PluginCompatibilityTarget { runtime: "bun" | "node" | "edge" | "worker" | "service-worker" | "browser"; version?: string; os?: "win32" | "linux" | "darwin" | string; capabilities?: readonly string[]; } export interface PluginCompatibilityResult { target: PluginCompatibilityTarget; ok: boolean; issues: Array<{ code: | "WRN-PLUGIN-MATRIX-RUNTIME" | "WRN-PLUGIN-MATRIX-VERSION" | "WRN-PLUGIN-MATRIX-OS" | "WRN-PLUGIN-MATRIX-CAPABILITY"; message: string; }>; } function parts(version: string): number[] { return version .replace(/^[^\d]*/, "") .split(/[.-]/) .slice(0, 3) .map((value) => Number(value) || 0); } function atLeast(version: string, minimum: string): boolean { const left = parts(version); const right = parts(minimum); for (let index = 0; index < 3; index += 1) { if (left[index] !== right[index]) return (left[index] ?? 0) > (right[index] ?? 0); } return true; } export function testPluginCompatibility( manifest: WrnexusPackageManifest, targets: readonly PluginCompatibilityTarget[], ): PluginCompatibilityResult[] { return targets.map((target) => { const issues: PluginCompatibilityResult["issues"] = []; if (manifest.runtimes?.length && !manifest.runtimes.includes(target.runtime)) { issues.push({ code: "WRN-PLUGIN-MATRIX-RUNTIME", message: `${target.runtime} is not declared.`, }); } const compatibility = manifest.compatibility; if ( target.runtime === "bun" && target.version && compatibility?.bunMin && !atLeast(target.version, compatibility.bunMin) ) { issues.push({ code: "WRN-PLUGIN-MATRIX-VERSION", message: `Bun ${target.version} is below ${compatibility.bunMin}.`, }); } if (target.os && compatibility?.os?.length && !compatibility.os.includes(target.os)) { issues.push({ code: "WRN-PLUGIN-MATRIX-OS", message: `${target.os} is not declared.` }); } const missing = (manifest.requires ?? []).filter( (capability) => !target.capabilities?.includes(capability), ); if (missing.length) { issues.push({ code: "WRN-PLUGIN-MATRIX-CAPABILITY", message: `Missing: ${missing.join(", ")}.`, }); } return { target: { ...target }, ok: issues.length === 0, issues }; }); }