fix(cli): apply biome lint fixes and remove old MJS files
Apply biome auto-fixes: - Sort imports: move type imports first in urec.ts and uconn.ts - Remove inferrable type annotations (stdoutBuf, stderrBuf, backoff) Complete migration: - Delete old urec.mjs and uconn.mjs files All biome checks now pass with no errors. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,117 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
import { mkdir, readFile, readdir, stat, unlink, writeFile } from "node:fs/promises";
|
||||
import { homedir, hostname } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { MSG } from "@uncaged/dashboard-server/protocol";
|
||||
import { watch } from "chokidar";
|
||||
import { program } from "commander";
|
||||
import { WebSocket } from "ws";
|
||||
|
||||
program.option("--url <url>", "WebSocket URL", "wss://dashboard.shazhou.work/ws/worker").parse();
|
||||
|
||||
const opts = program.opts();
|
||||
const WS_URL = opts.url;
|
||||
const DEVICE = hostname();
|
||||
const RECORDS_DIR = join(homedir(), ".uwf-dashboard/records");
|
||||
const SYNCED_FILE = join(homedir(), ".uwf-dashboard/.synced");
|
||||
const THREE_DAYS = 3 * 24 * 60 * 60 * 1000;
|
||||
|
||||
await mkdir(RECORDS_DIR, { recursive: true });
|
||||
|
||||
let synced = new Set();
|
||||
let ws = null;
|
||||
let pendingRecords = [];
|
||||
let backoff = 1000;
|
||||
const MAX_BACKOFF = 30000;
|
||||
|
||||
async function loadSynced() {
|
||||
try {
|
||||
const data = await readFile(SYNCED_FILE, "utf8");
|
||||
synced = new Set(data.split("\n").filter(Boolean));
|
||||
} catch {
|
||||
synced = new Set();
|
||||
}
|
||||
}
|
||||
|
||||
async function saveSynced() {
|
||||
await writeFile(SYNCED_FILE, [...synced].join("\n"));
|
||||
}
|
||||
|
||||
async function cleanOldRecords() {
|
||||
try {
|
||||
const files = await readdir(RECORDS_DIR);
|
||||
const now = Date.now();
|
||||
for (const f of files) {
|
||||
if (!f.endsWith(".json")) continue;
|
||||
const fp = join(RECORDS_DIR, f);
|
||||
const s = await stat(fp);
|
||||
if (now - s.mtimeMs > THREE_DAYS) {
|
||||
await unlink(fp).catch(() => {});
|
||||
synced.delete(f.replace(".json", ""));
|
||||
}
|
||||
}
|
||||
await saveSynced();
|
||||
} catch {}
|
||||
}
|
||||
|
||||
async function sendRecord(filePath) {
|
||||
try {
|
||||
const data = await readFile(filePath, "utf8");
|
||||
const record = JSON.parse(data);
|
||||
if (synced.has(record.id)) return;
|
||||
if (ws?.readyState === WebSocket.OPEN) {
|
||||
ws.send(JSON.stringify({ type: MSG.RECORD, record }));
|
||||
synced.add(record.id);
|
||||
await saveSynced();
|
||||
} else {
|
||||
pendingRecords.push(filePath);
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
|
||||
async function syncAll() {
|
||||
try {
|
||||
const files = await readdir(RECORDS_DIR);
|
||||
for (const f of files) {
|
||||
if (!f.endsWith(".json")) continue;
|
||||
await sendRecord(join(RECORDS_DIR, f));
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
|
||||
function connect() {
|
||||
console.log(`Connecting to ${WS_URL}...`);
|
||||
ws = new WebSocket(WS_URL);
|
||||
ws.on("open", () => {
|
||||
console.log("Connected to dashboard server");
|
||||
backoff = 1000;
|
||||
ws.send(JSON.stringify({ type: MSG.REGISTER, device: DEVICE }));
|
||||
syncAll();
|
||||
const pending = [...pendingRecords];
|
||||
pendingRecords = [];
|
||||
for (const f of pending) sendRecord(f);
|
||||
});
|
||||
ws.on("close", () => {
|
||||
console.log(`Disconnected. Reconnecting in ${backoff / 1000}s...`);
|
||||
setTimeout(connect, backoff);
|
||||
backoff = Math.min(backoff * 2, MAX_BACKOFF);
|
||||
});
|
||||
ws.on("error", (err) => {
|
||||
console.error("WebSocket error:", err.message);
|
||||
ws.close();
|
||||
});
|
||||
}
|
||||
|
||||
await loadSynced();
|
||||
await cleanOldRecords();
|
||||
setInterval(cleanOldRecords, 60 * 60 * 1000);
|
||||
|
||||
connect();
|
||||
|
||||
const watcher = watch(RECORDS_DIR, {
|
||||
ignoreInitial: true,
|
||||
awaitWriteFinish: { stabilityThreshold: 300 },
|
||||
});
|
||||
watcher.on("add", (fp) => {
|
||||
if (fp.endsWith(".json")) sendRecord(fp);
|
||||
});
|
||||
@@ -3,7 +3,7 @@ import { mkdir, readFile, readdir, stat, unlink, writeFile } from "node:fs/promi
|
||||
import { homedir, hostname } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { MSG } from "@uncaged/dashboard-server/protocol";
|
||||
import { watch, type FSWatcher } from "chokidar";
|
||||
import { type FSWatcher, watch } from "chokidar";
|
||||
import { program } from "commander";
|
||||
import { WebSocket } from "ws";
|
||||
|
||||
@@ -34,7 +34,7 @@ await mkdir(RECORDS_DIR, { recursive: true });
|
||||
let synced: Set<string> = new Set();
|
||||
let ws: WebSocket | null = null;
|
||||
let pendingRecords: string[] = [];
|
||||
let backoff: number = 1000;
|
||||
let backoff = 1000;
|
||||
const MAX_BACKOFF: number = 30000;
|
||||
|
||||
async function loadSynced(): Promise<void> {
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
import { spawn } from "node:child_process";
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { mkdir, writeFile } from "node:fs/promises";
|
||||
import { homedir, hostname } from "node:os";
|
||||
import { join } from "node:path";
|
||||
|
||||
const RECORDS_DIR = join(homedir(), ".uwf-dashboard/records");
|
||||
await mkdir(RECORDS_DIR, { recursive: true });
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
if (args.length === 0) {
|
||||
console.error("Usage: urec <command> [args...]");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const command = args.join(" ");
|
||||
const id = randomUUID();
|
||||
const device = hostname();
|
||||
const startedAt = new Date().toISOString();
|
||||
let stdoutBuf = "";
|
||||
let stderrBuf = "";
|
||||
|
||||
const child = spawn(args[0], args.slice(1), { stdio: ["inherit", "pipe", "pipe"] });
|
||||
|
||||
child.stdout.on("data", (d) => {
|
||||
const s = d.toString();
|
||||
process.stdout.write(s);
|
||||
stdoutBuf += s;
|
||||
});
|
||||
child.stderr.on("data", (d) => {
|
||||
const s = d.toString();
|
||||
process.stderr.write(s);
|
||||
stderrBuf += s;
|
||||
});
|
||||
|
||||
const signals = ["SIGINT", "SIGTERM"];
|
||||
for (const sig of signals) process.on(sig, () => child.kill(sig));
|
||||
|
||||
child.on("close", async (exitCode) => {
|
||||
const finishedAt = new Date().toISOString();
|
||||
const durationMs = new Date(finishedAt) - new Date(startedAt);
|
||||
const record = {
|
||||
id,
|
||||
device,
|
||||
command,
|
||||
args: args.slice(1),
|
||||
stdout: stdoutBuf,
|
||||
stderr: stderrBuf,
|
||||
exitCode: exitCode ?? 1,
|
||||
startedAt,
|
||||
finishedAt,
|
||||
durationMs,
|
||||
};
|
||||
await writeFile(join(RECORDS_DIR, `${id}.json`), JSON.stringify(record, null, 2));
|
||||
process.exit(exitCode ?? 1);
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env node
|
||||
import { spawn, type ChildProcess } from "node:child_process";
|
||||
import { type ChildProcess, spawn } from "node:child_process";
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { mkdir, writeFile } from "node:fs/promises";
|
||||
import { homedir, hostname } from "node:os";
|
||||
@@ -31,8 +31,8 @@ const command: string = args.join(" ");
|
||||
const id: string = randomUUID();
|
||||
const device: string = hostname();
|
||||
const startedAt: string = new Date().toISOString();
|
||||
let stdoutBuf: string = "";
|
||||
let stderrBuf: string = "";
|
||||
let stdoutBuf = "";
|
||||
let stderrBuf = "";
|
||||
|
||||
const child: ChildProcess = spawn(args[0], args.slice(1), { stdio: ["inherit", "pipe", "pipe"] });
|
||||
|
||||
|
||||
Reference in New Issue
Block a user