diff --git a/src/cli/nodes-cli/pairing-render.ts b/src/cli/nodes-cli/pairing-render.ts new file mode 100644 index 00000000000..a24561912ee --- /dev/null +++ b/src/cli/nodes-cli/pairing-render.ts @@ -0,0 +1,38 @@ +import type { PendingRequest } from "./types.js"; +import { formatTimeAgo } from "../../infra/format-time/format-relative.ts"; +import { renderTable } from "../../terminal/table.js"; + +export function renderPendingPairingRequestsTable(params: { + pending: PendingRequest[]; + now: number; + tableWidth: number; + theme: { + heading: (text: string) => string; + warn: (text: string) => string; + muted: (text: string) => string; + }; +}) { + const { pending, now, tableWidth, theme } = params; + const rows = pending.map((r) => ({ + Request: r.requestId, + Node: r.displayName?.trim() ? r.displayName.trim() : r.nodeId, + IP: r.remoteIp ?? "", + Requested: + typeof r.ts === "number" ? formatTimeAgo(Math.max(0, now - r.ts)) : theme.muted("unknown"), + Repair: r.isRepair ? theme.warn("yes") : "", + })); + return { + heading: theme.heading("Pending"), + table: renderTable({ + width: tableWidth, + columns: [ + { key: "Request", header: "Request", minWidth: 8 }, + { key: "Node", header: "Node", minWidth: 14, flex: true }, + { key: "IP", header: "IP", minWidth: 10 }, + { key: "Requested", header: "Requested", minWidth: 12 }, + { key: "Repair", header: "Repair", minWidth: 6 }, + ], + rows, + }).trimEnd(), + }; +} diff --git a/src/cli/nodes-cli/register.pairing.ts b/src/cli/nodes-cli/register.pairing.ts index 9241aeff782..daab00bdf32 100644 --- a/src/cli/nodes-cli/register.pairing.ts +++ b/src/cli/nodes-cli/register.pairing.ts @@ -1,10 +1,9 @@ import type { Command } from "commander"; import type { NodesRpcOpts } from "./types.js"; -import { formatTimeAgo } from "../../infra/format-time/format-relative.ts"; import { defaultRuntime } from "../../runtime.js"; -import { renderTable } from "../../terminal/table.js"; import { getNodesTheme, runNodesCommand } from "./cli-utils.js"; import { parsePairingList } from "./format.js"; +import { renderPendingPairingRequestsTable } from "./pairing-render.js"; import { callGatewayCli, nodesCallOpts, resolveNodeId } from "./rpc.js"; export function registerNodesPairingCommands(nodes: Command) { @@ -28,28 +27,14 @@ export function registerNodesPairingCommands(nodes: Command) { const { heading, warn, muted } = getNodesTheme(); const tableWidth = Math.max(60, (process.stdout.columns ?? 120) - 1); const now = Date.now(); - const rows = pending.map((r) => ({ - Request: r.requestId, - Node: r.displayName?.trim() ? r.displayName.trim() : r.nodeId, - IP: r.remoteIp ?? "", - Requested: - typeof r.ts === "number" ? formatTimeAgo(Math.max(0, now - r.ts)) : muted("unknown"), - Repair: r.isRepair ? warn("yes") : "", - })); - defaultRuntime.log(heading("Pending")); - defaultRuntime.log( - renderTable({ - width: tableWidth, - columns: [ - { key: "Request", header: "Request", minWidth: 8 }, - { key: "Node", header: "Node", minWidth: 14, flex: true }, - { key: "IP", header: "IP", minWidth: 10 }, - { key: "Requested", header: "Requested", minWidth: 12 }, - { key: "Repair", header: "Repair", minWidth: 6 }, - ], - rows, - }).trimEnd(), - ); + const rendered = renderPendingPairingRequestsTable({ + pending, + now, + tableWidth, + theme: { heading, warn, muted }, + }); + defaultRuntime.log(rendered.heading); + defaultRuntime.log(rendered.table); }); }), ); diff --git a/src/cli/nodes-cli/register.status.ts b/src/cli/nodes-cli/register.status.ts index e29b79d0699..414106f130b 100644 --- a/src/cli/nodes-cli/register.status.ts +++ b/src/cli/nodes-cli/register.status.ts @@ -7,6 +7,7 @@ import { shortenHomeInString } from "../../utils.js"; import { parseDurationMs } from "../parse-duration.js"; import { getNodesTheme, runNodesCommand } from "./cli-utils.js"; import { formatPermissions, parseNodeList, parsePairingList } from "./format.js"; +import { renderPendingPairingRequestsTable } from "./pairing-render.js"; import { callGatewayCli, nodesCallOpts, resolveNodeId } from "./rpc.js"; function formatVersionLabel(raw: string) { @@ -356,31 +357,15 @@ export function registerNodesStatusCommands(nodes: Command) { } if (pendingRows.length > 0) { - const pendingRowsRendered = pendingRows.map((r) => ({ - Request: r.requestId, - Node: r.displayName?.trim() ? r.displayName.trim() : r.nodeId, - IP: r.remoteIp ?? "", - Requested: - typeof r.ts === "number" - ? formatTimeAgo(Math.max(0, now - r.ts)) - : muted("unknown"), - Repair: r.isRepair ? warn("yes") : "", - })); + const rendered = renderPendingPairingRequestsTable({ + pending: pendingRows, + now, + tableWidth, + theme: { heading, warn, muted }, + }); defaultRuntime.log(""); - defaultRuntime.log(heading("Pending")); - defaultRuntime.log( - renderTable({ - width: tableWidth, - columns: [ - { key: "Request", header: "Request", minWidth: 8 }, - { key: "Node", header: "Node", minWidth: 14, flex: true }, - { key: "IP", header: "IP", minWidth: 10 }, - { key: "Requested", header: "Requested", minWidth: 12 }, - { key: "Repair", header: "Repair", minWidth: 6 }, - ], - rows: pendingRowsRendered, - }).trimEnd(), - ); + defaultRuntime.log(rendered.heading); + defaultRuntime.log(rendered.table); } if (filteredPaired.length > 0) {