mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-27 22:12:13 +00:00
223 lines
5.4 KiB
JavaScript
223 lines
5.4 KiB
JavaScript
#!/usr/bin/env node
|
|
import { spawn, spawnSync } from "node:child_process";
|
|
import fs from "node:fs";
|
|
import { createRequire } from "node:module";
|
|
import path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import { resolvePnpmRunner } from "./pnpm-runner.mjs";
|
|
import { buildCmdExeCommandLine } from "./windows-cmd-helpers.mjs";
|
|
|
|
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
const repoRoot = path.resolve(here, "..");
|
|
const uiDir = path.join(repoRoot, "ui");
|
|
|
|
const WINDOWS_CMD_EXE_EXTENSIONS = new Set([".cmd", ".bat"]);
|
|
|
|
function usage() {
|
|
// keep this tiny; it's invoked from npm scripts too
|
|
process.stderr.write("Usage: node scripts/ui.js <install|dev|build|test> [...args]\n");
|
|
}
|
|
|
|
export function shouldUseCmdExeForCommand(cmd, platform = process.platform) {
|
|
if (platform !== "win32") {
|
|
return false;
|
|
}
|
|
const extension = path.extname(cmd).toLowerCase();
|
|
return WINDOWS_CMD_EXE_EXTENSIONS.has(extension);
|
|
}
|
|
|
|
export function resolveSpawnCall(cmd, args, envOverride, params = {}) {
|
|
const platform = params.platform ?? process.platform;
|
|
const comSpec = params.comSpec ?? process.env.ComSpec ?? "cmd.exe";
|
|
const options = {
|
|
cwd: params.cwd ?? uiDir,
|
|
stdio: "inherit",
|
|
env: envOverride ?? process.env,
|
|
shell: false,
|
|
};
|
|
|
|
if (shouldUseCmdExeForCommand(cmd, platform)) {
|
|
return {
|
|
command: comSpec,
|
|
args: ["/d", "/s", "/c", buildCmdExeCommandLine(cmd, args)],
|
|
options: {
|
|
...options,
|
|
windowsVerbatimArguments: true,
|
|
},
|
|
};
|
|
}
|
|
|
|
return {
|
|
command: cmd,
|
|
args,
|
|
options,
|
|
};
|
|
}
|
|
|
|
export function resolvePnpmSpawnCall(pnpmArgs, envOverride, params = {}) {
|
|
const env = envOverride ?? process.env;
|
|
const platform = params.platform ?? process.platform;
|
|
const runner = resolvePnpmRunner({
|
|
pnpmArgs,
|
|
nodeExecPath: params.nodeExecPath ?? process.execPath,
|
|
npmExecPath: params.npmExecPath ?? env.npm_execpath,
|
|
comSpec: params.comSpec ?? env.ComSpec,
|
|
platform,
|
|
});
|
|
return {
|
|
command: runner.command,
|
|
args: runner.args,
|
|
options: {
|
|
cwd: params.cwd ?? uiDir,
|
|
stdio: "inherit",
|
|
env,
|
|
shell: runner.shell,
|
|
windowsVerbatimArguments: runner.windowsVerbatimArguments,
|
|
},
|
|
};
|
|
}
|
|
|
|
function runSpawnCall(spawnCall, label) {
|
|
const { command, args: spawnArgs, options } = spawnCall;
|
|
let child;
|
|
try {
|
|
child = spawn(command, spawnArgs, options);
|
|
} catch (err) {
|
|
console.error(`Failed to launch ${label}:`, err);
|
|
process.exit(1);
|
|
return;
|
|
}
|
|
|
|
child.on("error", (err) => {
|
|
console.error(`Failed to launch ${label}:`, err);
|
|
process.exit(1);
|
|
});
|
|
child.on("exit", (code) => {
|
|
if (code !== 0) {
|
|
process.exit(code ?? 1);
|
|
}
|
|
});
|
|
}
|
|
|
|
function run(cmd, args) {
|
|
runSpawnCall(resolveSpawnCall(cmd, args), cmd);
|
|
}
|
|
|
|
function runPnpm(args, envOverride) {
|
|
runSpawnCall(resolvePnpmSpawnCall(args, envOverride), "pnpm");
|
|
}
|
|
|
|
function runSpawnCallSync(spawnCall, label) {
|
|
const { command, args: spawnArgs, options } = spawnCall;
|
|
let result;
|
|
try {
|
|
result = spawnSync(command, spawnArgs, options);
|
|
} catch (err) {
|
|
console.error(`Failed to launch ${label}:`, err);
|
|
process.exit(1);
|
|
return;
|
|
}
|
|
if (result.signal) {
|
|
process.exit(1);
|
|
}
|
|
if ((result.status ?? 1) !== 0) {
|
|
process.exit(result.status ?? 1);
|
|
}
|
|
}
|
|
|
|
function runPnpmSync(args, envOverride) {
|
|
runSpawnCallSync(resolvePnpmSpawnCall(args, envOverride), "pnpm");
|
|
}
|
|
|
|
function depsInstalled(kind) {
|
|
try {
|
|
const require = createRequire(path.join(uiDir, "package.json"));
|
|
require.resolve("vite");
|
|
require.resolve("dompurify");
|
|
if (kind === "test") {
|
|
require.resolve("vitest");
|
|
require.resolve("@vitest/browser-playwright");
|
|
require.resolve("playwright");
|
|
}
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function resolveScriptAction(action) {
|
|
if (action === "install") {
|
|
return null;
|
|
}
|
|
if (action === "dev") {
|
|
return "dev";
|
|
}
|
|
if (action === "build") {
|
|
return "build";
|
|
}
|
|
if (action === "test") {
|
|
return "test";
|
|
}
|
|
return null;
|
|
}
|
|
|
|
export function main(argv = process.argv.slice(2)) {
|
|
const [action, ...rest] = argv;
|
|
if (!action) {
|
|
usage();
|
|
process.exit(2);
|
|
}
|
|
|
|
const script = resolveScriptAction(action);
|
|
if (action !== "install" && !script) {
|
|
usage();
|
|
process.exit(2);
|
|
}
|
|
|
|
if (process.env.OPENCLAW_BUILD_ALL_NO_PNPM === "1" && action === "build") {
|
|
run(process.execPath, [path.join(repoRoot, "node_modules/vite/bin/vite.js"), "build", ...rest]);
|
|
return;
|
|
}
|
|
|
|
if (action === "install") {
|
|
runPnpm(["install", ...rest]);
|
|
return;
|
|
}
|
|
|
|
if (!depsInstalled(action === "test" ? "test" : "build")) {
|
|
const installEnv = process.env;
|
|
const installArgs = ["install"];
|
|
runPnpmSync(installArgs, installEnv);
|
|
}
|
|
|
|
runPnpm(["run", script, ...rest]);
|
|
}
|
|
|
|
export function resolveDirectExecutionPath(entry, realpath = fs.realpathSync.native) {
|
|
const resolved = path.resolve(entry);
|
|
try {
|
|
return realpath(resolved);
|
|
} catch {
|
|
return resolved;
|
|
}
|
|
}
|
|
|
|
export function isDirectScriptExecution(
|
|
entry = process.argv[1],
|
|
scriptPath = fileURLToPath(import.meta.url),
|
|
realpath = fs.realpathSync.native,
|
|
) {
|
|
if (!entry) {
|
|
return false;
|
|
}
|
|
return (
|
|
resolveDirectExecutionPath(entry, realpath) === resolveDirectExecutionPath(scriptPath, realpath)
|
|
);
|
|
}
|
|
|
|
const isDirectExecution = isDirectScriptExecution();
|
|
|
|
if (isDirectExecution) {
|
|
main();
|
|
}
|