114 lines
3.9 KiB
JavaScript
114 lines
3.9 KiB
JavaScript
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
import path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
export function buildTuiReleaseRequest({
|
|
capabilityManifest,
|
|
packageManifest,
|
|
capabilityManifestPath = "",
|
|
packageManifestPath = "",
|
|
repository = "GameCult/EveTui",
|
|
} = {}) {
|
|
if (!capabilityManifest || typeof capabilityManifest !== "object") {
|
|
throw new Error("capabilityManifest is required");
|
|
}
|
|
if (!packageManifest || typeof packageManifest !== "object") {
|
|
throw new Error("packageManifest is required");
|
|
}
|
|
|
|
const releaseContract = capabilityManifest.lifecycle?.release?.releaseContract;
|
|
if (!releaseContract) {
|
|
throw new Error("capability manifest is missing lifecycle.release.releaseContract");
|
|
}
|
|
|
|
if (packageManifest.name !== releaseContract.packageName) {
|
|
throw new Error(`package name mismatch: expected ${releaseContract.packageName} got ${packageManifest.name || "missing"}`);
|
|
}
|
|
if (!packageManifest.version || !/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(packageManifest.version)) {
|
|
throw new Error(`package version is not a SemVer-compatible release version: ${packageManifest.version || "missing"}`);
|
|
}
|
|
|
|
const tagName = replaceVersion(releaseContract.tagPattern, packageManifest.version);
|
|
const artifactPath = replaceVersion(
|
|
releaseContract.artifactPattern || `artifacts/evetui-release/{version}/${releaseContract.packageName}-{version}.tgz`,
|
|
packageManifest.version,
|
|
);
|
|
|
|
return {
|
|
schema: releaseContract.requestSchema || "gamecult.eve.runtime_release_request.v1",
|
|
ownerRepo: releaseContract.ownerRepo,
|
|
repository,
|
|
packageName: releaseContract.packageName,
|
|
version: packageManifest.version,
|
|
packageRoot: releaseContract.packageRoot,
|
|
versionSource: releaseContract.versionSource,
|
|
tagName,
|
|
artifactKind: releaseContract.artifactKind,
|
|
artifactPath,
|
|
publishProof: releaseContract.publishProof,
|
|
sourceCapabilityManifestPath: capabilityManifestPath,
|
|
sourcePackageManifestPath: packageManifestPath,
|
|
main: packageManifest.main || "",
|
|
scripts: packageManifest.scripts || {},
|
|
dependencies: packageManifest.dependencies || {},
|
|
devDependencies: packageManifest.devDependencies || {},
|
|
};
|
|
}
|
|
|
|
export function loadJsonFile(filePath) {
|
|
return JSON.parse(readFileSync(filePath, "utf8"));
|
|
}
|
|
|
|
export function writeReleaseRequest(request, outputPath) {
|
|
mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
writeFileSync(outputPath, `${JSON.stringify(request, null, 2)}\n`, "utf8");
|
|
}
|
|
|
|
function replaceVersion(pattern, version) {
|
|
if (!pattern || !pattern.includes("{version}")) {
|
|
throw new Error(`release pattern must include {version}: ${pattern || "missing"}`);
|
|
}
|
|
return pattern.replaceAll("{version}", version);
|
|
}
|
|
|
|
function parseArgs(argv) {
|
|
const args = {};
|
|
for (let index = 0; index < argv.length; index += 1) {
|
|
const value = argv[index];
|
|
if (!value.startsWith("--")) continue;
|
|
const key = value.slice(2);
|
|
const next = argv[index + 1];
|
|
if (!next || next.startsWith("--")) {
|
|
args[key] = true;
|
|
} else {
|
|
args[key] = next;
|
|
index += 1;
|
|
}
|
|
}
|
|
return args;
|
|
}
|
|
|
|
function runCli() {
|
|
const args = parseArgs(process.argv.slice(2));
|
|
for (const required of ["capability", "package", "output"]) {
|
|
if (!args[required]) {
|
|
throw new Error(`missing required --${required}`);
|
|
}
|
|
}
|
|
|
|
const request = buildTuiReleaseRequest({
|
|
capabilityManifest: loadJsonFile(args.capability),
|
|
packageManifest: loadJsonFile(args.package),
|
|
capabilityManifestPath: args.capability,
|
|
packageManifestPath: args.package,
|
|
repository: args.repository || "GameCult/EveTui",
|
|
});
|
|
writeReleaseRequest(request, args.output);
|
|
process.stdout.write(`${args.output}\n`);
|
|
}
|
|
|
|
const invokedPath = process.argv[1] ? path.resolve(process.argv[1]) : "";
|
|
const modulePath = fileURLToPath(import.meta.url);
|
|
if (invokedPath === modulePath) {
|
|
runCli();
|
|
}
|