Files
rea/scripts/verify-package-update.mjs
T
morluto 48ff37f6ea fix(verifiers): consolidate shared helper ownership
Use JSON.parse directly in package verification and retain one parsed Cursor recovery snapshot. Route native command source loading through the shared transform-service owner so completed command cleanup leaves no transform child.

Preserve JSONC validation and caller inputs. Cover the actual public source-loading lifecycle with an authored command and verified process lineage.
2026-10-24 22:28:39 +08:00

208 lines
7.6 KiB
JavaScript

import { createHash } from "node:crypto";
import { createServer } from "node:http";
import { readFile, writeFile, mkdir } from "node:fs/promises";
import { dirname, join } from "node:path";
import { pathToFileURL } from "node:url";
import { withVerifierCleanup } from "./lib/verifier-cleanup.mjs";
/** Exercise the packaged updater with real npm and a local release registry fixture. */
export async function verifyPackageUpdate({
prefix,
packageRoot,
tarball,
workspace,
environment,
commands,
}) {
const metadataPath = join(packageRoot, "package.json");
const metadata = JSON.parse(await readFile(metadataPath, "utf8"));
const archive = await readFile(tarball);
const entry = join(packageRoot, "scripts", "rea.mjs");
const home = join(workspace, "update-home");
const codexPath = join(home, ".codex", "config.toml");
const originalConfig =
'[mcp_servers.rea]\ncommand = "npx"\nargs = ["-y", "rea-agents@0.0.0", "mcp"]\n';
await mkdir(dirname(codexPath), { recursive: true });
await writeFile(codexPath, originalConfig);
let fixtureFailure;
const fixture = new AbortController();
const server = createServer((request, response) => {
void serveRegistry(request, response).catch((error) => {
fixtureFailure ??= { cause: error };
fixture.abort(fixtureFailure.cause);
if (response.headersSent) {
response.destroy();
return;
}
response.writeHead(500);
response.end(String(error));
});
});
let registry;
async function serveRegistry(request, response) {
const pathname = new URL(request.url, registry).pathname;
if (pathname === "/rea-agents") {
response.setHeader("Content-Type", "application/json");
response.end(
JSON.stringify({
name: metadata.name,
"dist-tags": { latest: metadata.version },
versions: {
[metadata.version]: {
...metadata,
dist: {
tarball: `${registry}/release.tgz`,
integrity: `sha512-${createHash("sha512").update(archive).digest("base64")}`,
},
},
},
}),
);
} else if (pathname === "/release.tgz") {
response.end(archive);
} else if (request.method === "POST") {
response.setHeader("Content-Type", "application/json");
response.end("{}");
} else {
const upstream = await fetch(`https://registry.npmjs.org${request.url}`);
const body = Buffer.from(await upstream.arrayBuffer());
response.writeHead(upstream.status, {
"Content-Type":
upstream.headers.get("content-type") ?? "application/octet-stream",
});
response.end(body);
}
}
await new Promise((resolveListen, reject) => {
server.once("error", reject);
server.listen(0, "127.0.0.1", resolveListen);
});
return withVerifierCleanup(async () => {
try {
const address = server.address();
if (typeof address !== "object" || address === null)
throw new Error("Registry fixture did not bind");
registry = `http://127.0.0.1:${address.port}`;
// Model an older installed release's identity while retaining the new updater
// under test. The registry supplies the unmodified packed target artifact.
const generatedPath = join(
packageRoot,
"dist",
"generatedPackageMetadata.js",
);
const generated = await readFile(generatedPath, "utf8");
const previousVersion = "0.0.0";
const previousGenerated = generated.replace(
`version: "${metadata.version}"`,