Files
openclaw/scripts/package-manifest.mjs
T
Peter Steinberger 055a2dc6ce feat: continue dashboard sessions from CLI URLs (#120893)
* feat(cli): ingest session targets

* refactor(ui): remove gateway scope shim

* docs(cli): document session targets

* fix(cli): classify session target failures

* fix(cli): keep session target result private

* fix(cli): simplify timeout option warning

* build: declare session URL contract dependency

* fix(cli): parse bare session URL options symmetrically

* fix(cli): preserve command-owned URL arguments

* build: keep session URL contract build-only

* fix: address session URL review findings

* test: preserve session key mock exports

* fix: keep session URL helpers internal

* fix(tui): preserve URL agent for global sessions

* fix(tui): keep URL agent input internal

* fix(gateway): reconcile websocket protocol owner

* fix(attach): preserve global session agent ownership

* fix(attach): enforce global owner at grant boundary
2026-08-09 16:44:25 -07:00

111 lines
3.9 KiB
JavaScript

#!/usr/bin/env node
// Temporarily removes private workspace dependencies from the published manifest.
import { existsSync } from "node:fs";
import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";
const PACKAGE_JSON_PATH = "package.json";
const BACKUP_PATH = path.join(".artifacts", "package-manifest", "package.json.prepack-backup");
function preparedPackageManifest(content) {
const packageJson = JSON.parse(content);
const devDependencies = packageJson.devDependencies;
if (!devDependencies || typeof devDependencies !== "object" || Array.isArray(devDependencies)) {
return content;
}
const devDependencyEntries = Object.entries(devDependencies);
const publishedDevDependencyEntries = devDependencyEntries.filter(
([, spec]) => typeof spec !== "string" || !spec.startsWith("workspace:"),
);
if (publishedDevDependencyEntries.length === devDependencyEntries.length) {
return content;
}
if (publishedDevDependencyEntries.length === 0) {
delete packageJson.devDependencies;
} else {
packageJson.devDependencies = Object.fromEntries(publishedDevDependencyEntries);
}
return `${JSON.stringify(packageJson, null, 2)}\n`;
}
/** Restore package.json after prepack removed private workspace dependencies. */
export async function restorePackageManifest(cwd = process.cwd()) {
const backupPath = path.join(cwd, BACKUP_PATH);
if (!existsSync(backupPath)) {
return false;
}
const packageJsonPath = path.join(cwd, PACKAGE_JSON_PATH);
const [original, current] = await Promise.all([
readFile(backupPath, "utf8"),
readFile(packageJsonPath, "utf8"),
]);
if (current !== original && current !== preparedPackageManifest(original)) {
throw new Error(
`Refusing to restore ${PACKAGE_JSON_PATH} because it changed after prepack sanitized it.`,
);
}
await writeFile(packageJsonPath, original, "utf8");
await rm(backupPath, { force: true });
return true;
}
/** Remove private workspace dependencies while recording restorable source bytes. */
export async function preparePackageManifest(cwd = process.cwd()) {
const packageJsonPath = path.join(cwd, PACKAGE_JSON_PATH);
const backupPath = path.join(cwd, BACKUP_PATH);
const original = await readFile(packageJsonPath, "utf8");
const prepared = preparedPackageManifest(original);
if (prepared === original) {
return false;
}
await mkdir(path.dirname(backupPath), { recursive: true });
try {
await writeFile(backupPath, original, { encoding: "utf8", flag: "wx" });
} catch (error) {
if (error?.code === "EEXIST") {
throw new Error(
`Another package preparation owns ${PACKAGE_JSON_PATH}; wait for it to finish or run \`node scripts/openclaw-postpack.mjs\` after an interrupted pack.`,
{ cause: error },
);
}
throw error;
}
try {
await writeFile(packageJsonPath, prepared, "utf8");
} catch (error) {
try {
await restorePackageManifest(cwd);
} catch (restoreError) {
const failure = new Error(
`Writing ${PACKAGE_JSON_PATH} failed and its source state could not be restored.`,
{ cause: error },
);
Object.assign(failure, { restoreError });
throw failure;
}
throw error;
}
return true;
}
async function main(argv = process.argv.slice(2)) {
if (argv.length !== 1 || (argv[0] !== "prepare" && argv[0] !== "restore")) {
console.error("Usage: node scripts/package-manifest.mjs <prepare|restore>");
process.exitCode = 1;
return;
}
const changed =
argv[0] === "prepare" ? await preparePackageManifest() : await restorePackageManifest();
console.error(
changed
? `package-manifest: ${argv[0] === "prepare" ? "sanitized" : "restored"} package.json.`
: `package-manifest: no ${argv[0] === "prepare" ? "sanitation" : "cleanup"} needed.`,
);
}
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
await main();
}