This repository has been archived on 2026-10-29. You can view files and clone it, but you cannot make any changes to its state, such as pushing and creating new issues, pull requests or comments.
EveTui/tools/evetui/evetui-capture-artifact.mjs
2026-07-10 16:40:04 +01:00

118 lines
3.7 KiB
JavaScript

import { mkdirSync, writeFileSync } from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { EveTuiShell } from "../../src/eve-tui-shell.mjs";
import { buildTuiCaptureRequest, loadJsonFile, writeCaptureRequest } from "./evetui-capture-contract.mjs";
export function buildTuiCaptureArtifact({
advertisement,
capabilityManifest,
surfaceDocument,
advertisementPath = "",
capabilityManifestPath = "",
captureSurfaceId = "",
stamp = "latest",
width = 80,
} = {}) {
const request = buildTuiCaptureRequest({
advertisement,
capabilityManifest,
advertisementPath,
capabilityManifestPath,
captureSurfaceId,
stamp,
});
const shell = new EveTuiShell({ width });
const grid = shell.lowerSurface(surfaceDocument, advertisement, request.surfaceId);
validateGridArtifact(grid, request);
return {
request,
grid: {
...grid,
artifactKind: request.artifactKind,
captureKind: request.captureKind,
sourceAdvertisementPath: request.sourceAdvertisementPath,
sourceCapabilityManifestPath: request.sourceCapabilityManifestPath,
issuedAtUtc: request.issuedAtUtc,
},
};
}
export function writeTuiCaptureArtifact({ request, grid }, { outputPath, requestOutputPath = "" } = {}) {
if (!outputPath) throw new Error("outputPath is required");
mkdirSync(path.dirname(outputPath), { recursive: true });
writeFileSync(outputPath, `${JSON.stringify(grid, null, 2)}\n`, "utf8");
if (requestOutputPath) {
writeCaptureRequest(request, requestOutputPath);
}
}
function validateGridArtifact(grid, request) {
if (grid.schema !== "gamecult.eve.tui_grid.v1") {
throw new Error(`Unexpected TUI grid schema: ${grid.schema || ""}`);
}
for (const [field, expected] of [
["runtimeId", request.runtimeId],
["providerId", request.providerId],
["surfaceId", request.surfaceId],
["projectionKind", request.projectionKind],
["commandBoundary", request.commandBoundary],
["receiptSchema", request.receiptSchema],
]) {
if ((grid[field] || "") !== (expected || "")) {
throw new Error(`TUI grid ${field} expected ${expected || ""} got ${grid[field] || ""}`);
}
}
if (!Array.isArray(grid.lines) || !grid.lines.length) {
throw new Error("TUI grid artifact must contain at least one line");
}
}
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 ["advertisement", "capability", "surface", "output"]) {
if (!args[required]) {
throw new Error(`missing required --${required}`);
}
}
const stamp = args.stamp || "latest";
const artifact = buildTuiCaptureArtifact({
advertisement: loadJsonFile(args.advertisement),
capabilityManifest: loadJsonFile(args.capability),
surfaceDocument: loadJsonFile(args.surface),
advertisementPath: args.advertisement,
capabilityManifestPath: args.capability,
captureSurfaceId: args["surface-id"] || "",
stamp,
width: Number(args.width || 80),
});
writeTuiCaptureArtifact(artifact, {
outputPath: args.output,
requestOutputPath: args["request-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();
}