79 lines
2.4 KiB
TypeScript
79 lines
2.4 KiB
TypeScript
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 };
|
|
});
|
|
}
|