diff --git a/src/backend/database/routes/open-tabs.ts b/src/backend/database/routes/open-tabs.ts index a101c160..6ea7c22e 100644 --- a/src/backend/database/routes/open-tabs.ts +++ b/src/backend/database/routes/open-tabs.ts @@ -3,7 +3,7 @@ import express from "express"; import type { Request, Response } from "express"; import { databaseLogger } from "../../utils/logger.js"; import { AuthManager } from "../../utils/auth-manager.js"; -import { sessionManager } from "../../hosts/terminal-session-manager.js"; +import { sessionManager } from "../../hosts/terminal/session-manager.js"; import { getCurrentSettingValue, createCurrentOpenTabRepository, diff --git a/src/backend/hosts/docker/console.ts b/src/backend/hosts/docker/console.ts index 8ef06556..46a3c9bf 100644 --- a/src/backend/hosts/docker/console.ts +++ b/src/backend/hosts/docker/console.ts @@ -10,7 +10,7 @@ import { containerCommand, getContainerRuntimeConfig, type ContainerRuntime, -} from "../container-runtime.js"; +} from "./container-runtime.js"; import { resolveSshConnectConfigHost } from "../ssh-dns.js"; const sshLogger = systemLogger; diff --git a/src/backend/hosts/docker/container-routes.ts b/src/backend/hosts/docker/container-routes.ts index cc82de66..75d5f924 100644 --- a/src/backend/hosts/docker/container-routes.ts +++ b/src/backend/hosts/docker/container-routes.ts @@ -3,7 +3,7 @@ import { logger } from "../../utils/logger.js"; import { containerCommand, type ContainerRuntime, -} from "../container-runtime.js"; +} from "./container-runtime.js"; const sshLogger = logger; diff --git a/src/backend/hosts/container-runtime.ts b/src/backend/hosts/docker/container-runtime.ts similarity index 100% rename from src/backend/hosts/container-runtime.ts rename to src/backend/hosts/docker/container-runtime.ts diff --git a/src/backend/hosts/docker/routes.ts b/src/backend/hosts/docker/routes.ts index 1786e069..4bd2781f 100644 --- a/src/backend/hosts/docker/routes.ts +++ b/src/backend/hosts/docker/routes.ts @@ -28,7 +28,7 @@ import { containerCommand, getContainerRuntimeConfig, getRuntimeLabel, -} from "../container-runtime.js"; +} from "./container-runtime.js"; import { resolveSshConnectConfigHost } from "../ssh-dns.js"; import { type SSHSession, diff --git a/src/backend/hosts/docker/session-manager.ts b/src/backend/hosts/docker/session-manager.ts index 0157f669..6a620db1 100644 --- a/src/backend/hosts/docker/session-manager.ts +++ b/src/backend/hosts/docker/session-manager.ts @@ -1,6 +1,6 @@ import { Client as SSHClient } from "ssh2"; import { logger } from "../../utils/logger.js"; -import type { ContainerRuntime } from "../container-runtime.js"; +import type { ContainerRuntime } from "./container-runtime.js"; const sshLogger = logger; diff --git a/src/backend/hosts/file-manager-action-routes.ts b/src/backend/hosts/file-manager/action-routes.ts similarity index 98% rename from src/backend/hosts/file-manager-action-routes.ts rename to src/backend/hosts/file-manager/action-routes.ts index 18a610cb..930aa31c 100644 --- a/src/backend/hosts/file-manager-action-routes.ts +++ b/src/backend/hosts/file-manager/action-routes.ts @@ -1,7 +1,7 @@ import type { Express } from "express"; -import type { AuthenticatedRequest } from "../../types/index.js"; -import { fileLogger } from "../utils/logger.js"; -import { execChannel, type SSHSession } from "./file-manager-session.js"; +import type { AuthenticatedRequest } from "../../../types/index.js"; +import { fileLogger } from "../../utils/logger.js"; +import { execChannel, type SSHSession } from "./session.js"; type FileActionRoutesDeps = { sshSessions: Record; diff --git a/src/backend/hosts/file-manager-content-routes.ts b/src/backend/hosts/file-manager/content-routes.ts similarity index 99% rename from src/backend/hosts/file-manager-content-routes.ts rename to src/backend/hosts/file-manager/content-routes.ts index 768b277e..bda93e68 100644 --- a/src/backend/hosts/file-manager-content-routes.ts +++ b/src/backend/hosts/file-manager/content-routes.ts @@ -1,15 +1,15 @@ import type { Express, Request, Response } from "express"; import Busboy from "busboy"; -import type { AuthenticatedRequest } from "../../types/index.js"; -import { fileLogger } from "../utils/logger.js"; +import type { AuthenticatedRequest } from "../../../types/index.js"; +import { fileLogger } from "../../utils/logger.js"; import { execChannel, execWithSudo, execWithSudoBuffer, getSessionSftp, type SSHSession, -} from "./file-manager-session.js"; -import { detectBinary } from "./file-manager-utils.js"; +} from "./session.js"; +import { detectBinary } from "./utils.js"; type FileContentRoutesDeps = { sshSessions: Record; diff --git a/src/backend/hosts/file-manager-download-routes.ts b/src/backend/hosts/file-manager/download-routes.ts similarity index 97% rename from src/backend/hosts/file-manager-download-routes.ts rename to src/backend/hosts/file-manager/download-routes.ts index e7e58d60..99ac4361 100644 --- a/src/backend/hosts/file-manager-download-routes.ts +++ b/src/backend/hosts/file-manager/download-routes.ts @@ -1,12 +1,8 @@ import type { Express } from "express"; -import type { AuthenticatedRequest } from "../../types/index.js"; -import { fileLogger } from "../utils/logger.js"; -import { getMimeType } from "./file-manager-utils.js"; -import { - execChannel, - getSessionSftp, - type SSHSession, -} from "./file-manager-session.js"; +import type { AuthenticatedRequest } from "../../../types/index.js"; +import { fileLogger } from "../../utils/logger.js"; +import { getMimeType } from "./utils.js"; +import { execChannel, getSessionSftp, type SSHSession } from "./session.js"; type FileDownloadRoutesDeps = { sshSessions: Record; diff --git a/src/backend/hosts/file-manager.ts b/src/backend/hosts/file-manager/index.ts similarity index 97% rename from src/backend/hosts/file-manager.ts rename to src/backend/hosts/file-manager/index.ts index f8dfef24..5f378a64 100644 --- a/src/backend/hosts/file-manager.ts +++ b/src/backend/hosts/file-manager/index.ts @@ -1,21 +1,24 @@ import express from "express"; -import { createCorsMiddleware } from "../utils/cors-config.js"; +import { createCorsMiddleware } from "../../utils/cors-config.js"; import cookieParser from "cookie-parser"; import axios from "axios"; import { Client as SSHClient } from "ssh2"; -import { SSH_ALGORITHMS } from "../utils/ssh-algorithms.js"; -import { createCurrentHostResolutionRepository } from "../database/repositories/factory.js"; -import { fileLogger } from "../utils/logger.js"; -import { AuthManager } from "../utils/auth-manager.js"; -import type { AuthenticatedRequest, ProxyNode } from "../../types/index.js"; +import { SSH_ALGORITHMS } from "../../utils/ssh-algorithms.js"; +import { createCurrentHostResolutionRepository } from "../../database/repositories/factory.js"; +import { fileLogger } from "../../utils/logger.js"; +import { AuthManager } from "../../utils/auth-manager.js"; +import type { AuthenticatedRequest, ProxyNode } from "../../../types/index.js"; import { createSocks5Connection, type SOCKS5Config, -} from "../utils/socks5-helper.js"; -import type { LogEntry, ConnectionStage } from "../../types/connection-log.js"; -import { SSHHostKeyVerifier } from "./host-key-verifier.js"; -import { resolveHostById } from "./host-resolver.js"; -import type { SSHHost } from "../../types/index.js"; +} from "../../utils/socks5-helper.js"; +import type { + LogEntry, + ConnectionStage, +} from "../../../types/connection-log.js"; +import { SSHHostKeyVerifier } from "../host-key-verifier.js"; +import { resolveHostById } from "../host-resolver.js"; +import type { SSHHost } from "../../../types/index.js"; import { startHostTransfer, getTransferStatus, @@ -26,24 +29,24 @@ import { retryHostTransfer, previewArchiveTransferMethod, type HostTransferDeps, -} from "./host-transfer.js"; -import { registerFileContentRoutes } from "./file-manager-content-routes.js"; -import { createConnectionLog } from "./connection-log.js"; -import { createJumpHostChain } from "./jump-host-chain.js"; -import { preparePrivateKeyForSSH2 } from "../utils/ssh-key-utils.js"; +} from "./transfer-engine.js"; +import { registerFileContentRoutes } from "./content-routes.js"; +import { createConnectionLog } from "../connection-log.js"; +import { createJumpHostChain } from "../jump-host-chain.js"; +import { preparePrivateKeyForSSH2 } from "../../utils/ssh-key-utils.js"; import { ChannelOpenSerializer, execChannel, getSessionSftp, type PendingTOTPSession, type SSHSession, -} from "./file-manager-session.js"; -import { registerFileListingRoutes } from "./file-manager-list-routes.js"; -import { registerFileOperationRoutes } from "./file-manager-operation-routes.js"; -import { resolveSshConnectConfigHost } from "./ssh-dns.js"; -import { registerFileDownloadRoutes } from "./file-manager-download-routes.js"; -import { registerFileActionRoutes } from "./file-manager-action-routes.js"; -import { applyAgentAuth } from "./terminal-auth-helpers.js"; +} from "./session.js"; +import { registerFileListingRoutes } from "./list-routes.js"; +import { registerFileOperationRoutes } from "./operation-routes.js"; +import { resolveSshConnectConfigHost } from "../ssh-dns.js"; +import { registerFileDownloadRoutes } from "./download-routes.js"; +import { registerFileActionRoutes } from "./action-routes.js"; +import { applyAgentAuth } from "../terminal-auth-helpers.js"; const app = express(); @@ -209,14 +212,14 @@ async function buildDedicatedTransferConnectConfig( } config.password = host.password; } else if (authType === "opkssh") { - const { getOPKSSHToken } = await import("./opkssh-auth.js"); + const { getOPKSSHToken } = await import("../opkssh-auth.js"); const token = await getOPKSSHToken(userId, host.id); if (!token) { throw new Error( "OPKSSH authentication required. Open a Terminal connection to this host first.", ); } - const { setupOPKSSHCertAuth } = await import("./opkssh-cert-auth.js"); + const { setupOPKSSHCertAuth } = await import("../opkssh-cert-auth.js"); await setupOPKSSHCertAuth( config as import("ssh2").ConnectConfig, client, @@ -747,7 +750,7 @@ app.post("/ssh/file_manager/ssh/connect", async (req, res) => { let resolvedSocks5ProxyChain = socks5ProxyChain; if (hostId && userId && !password && !sshKey) { try { - const { resolveHostById } = await import("./host-resolver.js"); + const { resolveHostById } = await import("../host-resolver.js"); const resolvedHost = await resolveHostById(hostId, userId); if (resolvedHost) { resolvedIp = resolvedHost.ip; @@ -806,7 +809,7 @@ app.post("/ssh/file_manager/ssh/connect", async (req, res) => { } else if (credentialId && hostId && userId) { // Legacy: credential resolution from credentialId try { - const { resolveHostById } = await import("./host-resolver.js"); + const { resolveHostById } = await import("../host-resolver.js"); const resolvedHost = await resolveHostById(hostId, userId); if (resolvedHost) { resolvedIp = resolvedHost.ip; @@ -998,7 +1001,7 @@ app.post("/ssh/file_manager/ssh/connect", async (req, res) => { ); } else if (resolvedCredentials.authType === "opkssh") { try { - const { getOPKSSHToken } = await import("./opkssh-auth.js"); + const { getOPKSSHToken } = await import("../opkssh-auth.js"); const token = await getOPKSSHToken(userId, hostId); if (!token) { @@ -1017,7 +1020,7 @@ app.post("/ssh/file_manager/ssh/connect", async (req, res) => { }); } - const { setupOPKSSHCertAuth } = await import("./opkssh-cert-auth.js"); + const { setupOPKSSHCertAuth } = await import("../opkssh-cert-auth.js"); await setupOPKSSHCertAuth( config as import("ssh2").ConnectConfig, client, diff --git a/src/backend/hosts/file-manager-list-routes.ts b/src/backend/hosts/file-manager/list-routes.ts similarity index 98% rename from src/backend/hosts/file-manager-list-routes.ts rename to src/backend/hosts/file-manager/list-routes.ts index a279a63c..a4b1a343 100644 --- a/src/backend/hosts/file-manager-list-routes.ts +++ b/src/backend/hosts/file-manager/list-routes.ts @@ -1,17 +1,13 @@ import type { Express } from "express"; -import type { AuthenticatedRequest } from "../../types/index.js"; -import { fileLogger } from "../utils/logger.js"; -import { - execChannel, - getSessionSftp, - type SSHSession, -} from "./file-manager-session.js"; +import type { AuthenticatedRequest } from "../../../types/index.js"; +import { fileLogger } from "../../utils/logger.js"; +import { execChannel, getSessionSftp, type SSHSession } from "./session.js"; import { formatMtime, isExecutableFile, modeToPermissions, parseLsDateToTimestamp, -} from "./file-manager-utils.js"; +} from "./utils.js"; type FileListingRoutesDeps = { sshSessions: Record; diff --git a/src/backend/hosts/file-manager-operation-commands.ts b/src/backend/hosts/file-manager/operation-commands.ts similarity index 92% rename from src/backend/hosts/file-manager-operation-commands.ts rename to src/backend/hosts/file-manager/operation-commands.ts index 0eea91c9..2aad2c30 100644 --- a/src/backend/hosts/file-manager-operation-commands.ts +++ b/src/backend/hosts/file-manager/operation-commands.ts @@ -1,4 +1,4 @@ -import { isWindowsSftpPath, sftpPathToLocalPath } from "./transfer-paths.js"; +import { isWindowsSftpPath, sftpPathToLocalPath } from "../transfer-paths.js"; export interface DeleteCommand { command: string; diff --git a/src/backend/hosts/file-manager-operation-routes.ts b/src/backend/hosts/file-manager/operation-routes.ts similarity index 98% rename from src/backend/hosts/file-manager-operation-routes.ts rename to src/backend/hosts/file-manager/operation-routes.ts index 317ceef2..4a2e4977 100644 --- a/src/backend/hosts/file-manager-operation-routes.ts +++ b/src/backend/hosts/file-manager/operation-routes.ts @@ -1,12 +1,8 @@ import type { Express } from "express"; -import type { AuthenticatedRequest } from "../../types/index.js"; -import { fileLogger } from "../utils/logger.js"; -import { - execChannel, - execWithSudo, - type SSHSession, -} from "./file-manager-session.js"; -import { buildDeleteCommand } from "./file-manager-operation-commands.js"; +import type { AuthenticatedRequest } from "../../../types/index.js"; +import { fileLogger } from "../../utils/logger.js"; +import { execChannel, execWithSudo, type SSHSession } from "./session.js"; +import { buildDeleteCommand } from "./operation-commands.js"; type FileOperationRoutesDeps = { sshSessions: Record; diff --git a/src/backend/hosts/file-manager-session.ts b/src/backend/hosts/file-manager/session.ts similarity index 100% rename from src/backend/hosts/file-manager-session.ts rename to src/backend/hosts/file-manager/session.ts diff --git a/src/backend/hosts/host-transfer.ts b/src/backend/hosts/file-manager/transfer-engine.ts similarity index 99% rename from src/backend/hosts/host-transfer.ts rename to src/backend/hosts/file-manager/transfer-engine.ts index 7d12eeff..4a83a280 100644 --- a/src/backend/hosts/host-transfer.ts +++ b/src/backend/hosts/file-manager/transfer-engine.ts @@ -2,7 +2,7 @@ import { randomUUID } from "crypto"; import { networkInterfaces } from "os"; import { performance } from "node:perf_hooks"; import type { ClientChannel } from "ssh2"; -import { fileLogger } from "../utils/logger.js"; +import { fileLogger } from "../../utils/logger.js"; import { basename, buildPathFromSegments, @@ -15,7 +15,7 @@ import { sftpPathToLocalPath, splitPathSegments, type TransferPlatform, -} from "./transfer-paths.js"; +} from "../transfer-paths.js"; import { buildTransferScanSummary, getArchiveTransferReasonKey, diff --git a/src/backend/hosts/transfer-routing.ts b/src/backend/hosts/file-manager/transfer-routing.ts similarity index 98% rename from src/backend/hosts/transfer-routing.ts rename to src/backend/hosts/file-manager/transfer-routing.ts index eab1456c..c351742f 100644 --- a/src/backend/hosts/transfer-routing.ts +++ b/src/backend/hosts/file-manager/transfer-routing.ts @@ -1,4 +1,4 @@ -import type { TransferPlatform } from "./transfer-paths.js"; +import type { TransferPlatform } from "../transfer-paths.js"; export type TransferMethodPreference = "auto" | "tar" | "item_sftp"; diff --git a/src/backend/hosts/file-manager-utils.ts b/src/backend/hosts/file-manager/utils.ts similarity index 100% rename from src/backend/hosts/file-manager-utils.ts rename to src/backend/hosts/file-manager/utils.ts diff --git a/src/backend/hosts/alert-engine.ts b/src/backend/hosts/metrics/alert-engine.ts similarity index 98% rename from src/backend/hosts/alert-engine.ts rename to src/backend/hosts/metrics/alert-engine.ts index e5514598..deface56 100644 --- a/src/backend/hosts/alert-engine.ts +++ b/src/backend/hosts/metrics/alert-engine.ts @@ -1,10 +1,10 @@ -import { createCurrentAlertRepository } from "../database/repositories/factory.js"; -import { statsLogger } from "../utils/logger.js"; +import { createCurrentAlertRepository } from "../../database/repositories/factory.js"; +import { statsLogger } from "../../utils/logger.js"; import { sendNotification, type AlertPayload, type NotificationChannel, -} from "../utils/notification-sender.js"; +} from "../../utils/notification-sender.js"; type AlertTriggerType = | "host_offline" diff --git a/src/backend/hosts/host-metrics-helpers.ts b/src/backend/hosts/metrics/helpers.ts similarity index 100% rename from src/backend/hosts/host-metrics-helpers.ts rename to src/backend/hosts/metrics/helpers.ts diff --git a/src/backend/hosts/host-metrics-history-routes.ts b/src/backend/hosts/metrics/history-routes.ts similarity index 94% rename from src/backend/hosts/host-metrics-history-routes.ts rename to src/backend/hosts/metrics/history-routes.ts index 8e8c1dcd..672c35b4 100644 --- a/src/backend/hosts/host-metrics-history-routes.ts +++ b/src/backend/hosts/metrics/history-routes.ts @@ -1,7 +1,7 @@ import type { Express, RequestHandler } from "express"; -import type { AuthenticatedRequest } from "../../types/index.js"; -import { createCurrentHostMetricsHistoryRepository } from "../database/repositories/factory.js"; -import { statsLogger } from "../utils/logger.js"; +import type { AuthenticatedRequest } from "../../../types/index.js"; +import { createCurrentHostMetricsHistoryRepository } from "../../database/repositories/factory.js"; +import { statsLogger } from "../../utils/logger.js"; type HistoryRoutesDeps = { validateHostId: RequestHandler; diff --git a/src/backend/hosts/host-metrics.ts b/src/backend/hosts/metrics/index.ts similarity index 97% rename from src/backend/hosts/host-metrics.ts rename to src/backend/hosts/metrics/index.ts index cf260359..fd610a32 100644 --- a/src/backend/hosts/host-metrics.ts +++ b/src/backend/hosts/metrics/index.ts @@ -1,24 +1,27 @@ import express from "express"; import net from "net"; -import { createCorsMiddleware } from "../utils/cors-config.js"; +import { createCorsMiddleware } from "../../utils/cors-config.js"; import cookieParser from "cookie-parser"; import { Client, type ConnectConfig } from "ssh2"; -import { SSH_ALGORITHMS } from "../utils/ssh-algorithms.js"; +import { SSH_ALGORITHMS } from "../../utils/ssh-algorithms.js"; import { pickResolvedPassword, pickResolvedUsername, -} from "./credential-username.js"; +} from "../credential-username.js"; import { getCurrentSettingValue, createCurrentHostMetricsHistoryRepository, createCurrentHostResolutionRepository, -} from "../database/repositories/factory.js"; -import { statsLogger } from "../utils/logger.js"; -import { DataCrypto } from "../utils/data-crypto.js"; -import { AuthManager } from "../utils/auth-manager.js"; -import { PermissionManager } from "../utils/permission-manager.js"; -import type { AuthenticatedRequest, ProxyNode } from "../../types/index.js"; -import type { LogEntry, ConnectionStage } from "../../types/connection-log.js"; +} from "../../database/repositories/factory.js"; +import { statsLogger } from "../../utils/logger.js"; +import { DataCrypto } from "../../utils/data-crypto.js"; +import { AuthManager } from "../../utils/auth-manager.js"; +import { PermissionManager } from "../../utils/permission-manager.js"; +import type { AuthenticatedRequest, ProxyNode } from "../../../types/index.js"; +import type { + LogEntry, + ConnectionStage, +} from "../../../types/connection-log.js"; import { collectCpuMetrics } from "./widgets/cpu-collector.js"; import { collectMemoryMetrics } from "./widgets/memory-collector.js"; import { collectDiskMetrics } from "./widgets/disk-collector.js"; @@ -32,26 +35,26 @@ import { collectFirewallMetrics } from "./widgets/firewall-collector.js"; import { createSocks5Connection, type SOCKS5Config, -} from "../utils/socks5-helper.js"; -import { preparePrivateKeyForSSH2 } from "../utils/ssh-key-utils.js"; -import { SSHHostKeyVerifier } from "./host-key-verifier.js"; -import { connectionPool, withConnection } from "./ssh-connection-pool.js"; -import { registerHostMetricsSettingsRoutes } from "./host-metrics-settings-routes.js"; -import { registerHostMetricsViewerRoutes } from "./host-metrics-viewer-routes.js"; -import { registerHostMetricsPreferencesRoutes } from "./host-metrics-preferences-routes.js"; -import { registerHostMetricsHistoryRoutes } from "./host-metrics-history-routes.js"; +} from "../../utils/socks5-helper.js"; +import { preparePrivateKeyForSSH2 } from "../../utils/ssh-key-utils.js"; +import { SSHHostKeyVerifier } from "../host-key-verifier.js"; +import { connectionPool, withConnection } from "../ssh-connection-pool.js"; +import { registerHostMetricsSettingsRoutes } from "./settings-routes.js"; +import { registerHostMetricsViewerRoutes } from "./viewer-routes.js"; +import { registerHostMetricsPreferencesRoutes } from "./preferences-routes.js"; +import { registerHostMetricsHistoryRoutes } from "./history-routes.js"; import { AlertEngine } from "./alert-engine.js"; import { registerManagerRoutes } from "./managers/index.js"; -import { resolveSshConnectConfigHost } from "./ssh-dns.js"; +import { resolveSshConnectConfigHost } from "../ssh-dns.js"; import { AccessDeniedError } from "./managers/route-helpers.js"; import type { ManagerHost } from "./managers/types.js"; -import { createJumpHostChain } from "./jump-host-chain.js"; +import { createJumpHostChain } from "../jump-host-chain.js"; import { isTcpPingEnabled, supportsMetrics, tcpPingThroughJumpHost, -} from "./host-metrics-helpers.js"; -import { createConnectionLog } from "./connection-log.js"; +} from "./helpers.js"; +import { createConnectionLog } from "../connection-log.js"; import { cleanupMetricsSession, getSessionKey, @@ -59,7 +62,7 @@ import { pendingTOTPSessions, scheduleMetricsSessionCleanup, type MetricsViewer, -} from "./host-metrics-sessions.js"; +} from "./sessions.js"; import { authFailureTracker, hostPollCache, @@ -68,7 +71,7 @@ import { pollingBackoff, requestQueue, statusPollLimiter, -} from "./host-metrics-state.js"; +} from "./state.js"; const authManager = AuthManager.getInstance(); const permissionManager = PermissionManager.getInstance(); @@ -989,7 +992,7 @@ async function resolveHostCredentials( if (isSharedHost) { const { SharedCredentialManager } = - await import("../utils/shared-credential-manager.js"); + await import("../../utils/shared-credential-manager.js"); const sharedCredManager = SharedCredentialManager.getInstance(); const sharedCred = await sharedCredManager.getSharedCredentialForUser( host.id as number, @@ -1255,18 +1258,18 @@ function createSshFactory(host: SSHHostWithCredentials): () => Promise { // Set up OPKSSH cert auth if needed (requires client instance) if (host.authType === "opkssh" && host.userId) { - const { getOPKSSHToken } = await import("./opkssh-auth.js"); + const { getOPKSSHToken } = await import("../opkssh-auth.js"); const token = await getOPKSSHToken(host.userId, host.id); if (!token) { throw new Error( "OPKSSH authentication required. Please open a Terminal connection first.", ); } - const { setupOPKSSHCertAuth } = await import("./opkssh-cert-auth.js"); + const { setupOPKSSHCertAuth } = await import("../opkssh-cert-auth.js"); await setupOPKSSHCertAuth(config, client, token, host.username); } else if (host.authType === "vault") { const { setupVaultSshSignerAuth } = - await import("./vault-ssh-connect.js"); + await import("../vault-ssh-connect.js"); await setupVaultSshSignerAuth(config, client, host); } @@ -2123,7 +2126,7 @@ app.post("/metrics/start/:id", validateHostId, async (req, res) => { const client = new Client(); if (host.authType === "opkssh" && host.userId) { - const { getOPKSSHToken } = await import("./opkssh-auth.js"); + const { getOPKSSHToken } = await import("../opkssh-auth.js"); const token = await getOPKSSHToken(host.userId, host.id); if (!token) { connectionLogs.push( @@ -2139,11 +2142,11 @@ app.post("/metrics/start/:id", validateHostId, async (req, res) => { connectionLogs, }); } - const { setupOPKSSHCertAuth } = await import("./opkssh-cert-auth.js"); + const { setupOPKSSHCertAuth } = await import("../opkssh-cert-auth.js"); await setupOPKSSHCertAuth(config, client, token, host.username); } else if (host.authType === "vault") { const { setupVaultSshSignerAuth } = - await import("./vault-ssh-connect.js"); + await import("../vault-ssh-connect.js"); await setupVaultSshSignerAuth(config, client, host); } @@ -2792,7 +2795,8 @@ app.post("/internal/login-alert", async (req, res) => { ) { return res.status(403).json({ error: "Forbidden" }); } - const systemCrypto = (await import("../utils/system-crypto.js")).SystemCrypto; + const systemCrypto = (await import("../../utils/system-crypto.js")) + .SystemCrypto; const expectedToken = await systemCrypto.getInstance().getInternalAuthToken(); const token = req.headers["x-internal-auth"]; if (!token || token !== expectedToken) { diff --git a/src/backend/hosts/managers/cron.ts b/src/backend/hosts/metrics/managers/cron.ts similarity index 100% rename from src/backend/hosts/managers/cron.ts rename to src/backend/hosts/metrics/managers/cron.ts diff --git a/src/backend/hosts/managers/exec-elevated.ts b/src/backend/hosts/metrics/managers/exec-elevated.ts similarity index 100% rename from src/backend/hosts/managers/exec-elevated.ts rename to src/backend/hosts/metrics/managers/exec-elevated.ts diff --git a/src/backend/hosts/managers/firewall.ts b/src/backend/hosts/metrics/managers/firewall.ts similarity index 100% rename from src/backend/hosts/managers/firewall.ts rename to src/backend/hosts/metrics/managers/firewall.ts diff --git a/src/backend/hosts/managers/health.ts b/src/backend/hosts/metrics/managers/health.ts similarity index 97% rename from src/backend/hosts/managers/health.ts rename to src/backend/hosts/metrics/managers/health.ts index eb2a53b5..bd631066 100644 --- a/src/backend/hosts/managers/health.ts +++ b/src/backend/hosts/metrics/managers/health.ts @@ -1,8 +1,8 @@ import type { Express } from "express"; import type { Client } from "ssh2"; -import type { AuthenticatedRequest } from "../../../types/index.js"; +import type { AuthenticatedRequest } from "../../../../types/index.js"; import { execCommand } from "../widgets/common-utils.js"; -import { createCurrentHostHealthRepository } from "../../database/repositories/factory.js"; +import { createCurrentHostHealthRepository } from "../../../database/repositories/factory.js"; import { managerHandler, ManagerInputError } from "./route-helpers.js"; import { shellSingleQuote } from "./exec-elevated.js"; import { isValidPort } from "./validation.js"; diff --git a/src/backend/hosts/managers/index.ts b/src/backend/hosts/metrics/managers/index.ts similarity index 100% rename from src/backend/hosts/managers/index.ts rename to src/backend/hosts/metrics/managers/index.ts diff --git a/src/backend/hosts/managers/logs.ts b/src/backend/hosts/metrics/managers/logs.ts similarity index 100% rename from src/backend/hosts/managers/logs.ts rename to src/backend/hosts/metrics/managers/logs.ts diff --git a/src/backend/hosts/managers/packages.ts b/src/backend/hosts/metrics/managers/packages.ts similarity index 100% rename from src/backend/hosts/managers/packages.ts rename to src/backend/hosts/metrics/managers/packages.ts diff --git a/src/backend/hosts/managers/platform.ts b/src/backend/hosts/metrics/managers/platform.ts similarity index 100% rename from src/backend/hosts/managers/platform.ts rename to src/backend/hosts/metrics/managers/platform.ts diff --git a/src/backend/hosts/managers/processes.ts b/src/backend/hosts/metrics/managers/processes.ts similarity index 100% rename from src/backend/hosts/managers/processes.ts rename to src/backend/hosts/metrics/managers/processes.ts diff --git a/src/backend/hosts/managers/route-helpers.ts b/src/backend/hosts/metrics/managers/route-helpers.ts similarity index 93% rename from src/backend/hosts/managers/route-helpers.ts rename to src/backend/hosts/metrics/managers/route-helpers.ts index 5dfb6301..52199b6d 100644 --- a/src/backend/hosts/managers/route-helpers.ts +++ b/src/backend/hosts/metrics/managers/route-helpers.ts @@ -1,7 +1,7 @@ import type { Request, Response } from "express"; import type { Client } from "ssh2"; -import type { AuthenticatedRequest } from "../../../types/index.js"; -import { statsLogger } from "../../utils/logger.js"; +import type { AuthenticatedRequest } from "../../../../types/index.js"; +import { statsLogger } from "../../../utils/logger.js"; import { ElevationError } from "./exec-elevated.js"; import type { ManagerHost, RunOnHost } from "./types.js"; diff --git a/src/backend/hosts/managers/services.ts b/src/backend/hosts/metrics/managers/services.ts similarity index 100% rename from src/backend/hosts/managers/services.ts rename to src/backend/hosts/metrics/managers/services.ts diff --git a/src/backend/hosts/managers/simple-reads.ts b/src/backend/hosts/metrics/managers/simple-reads.ts similarity index 100% rename from src/backend/hosts/managers/simple-reads.ts rename to src/backend/hosts/metrics/managers/simple-reads.ts diff --git a/src/backend/hosts/managers/ssl.ts b/src/backend/hosts/metrics/managers/ssl.ts similarity index 100% rename from src/backend/hosts/managers/ssl.ts rename to src/backend/hosts/metrics/managers/ssl.ts diff --git a/src/backend/hosts/managers/tailscale.ts b/src/backend/hosts/metrics/managers/tailscale.ts similarity index 100% rename from src/backend/hosts/managers/tailscale.ts rename to src/backend/hosts/metrics/managers/tailscale.ts diff --git a/src/backend/hosts/managers/types.ts b/src/backend/hosts/metrics/managers/types.ts similarity index 100% rename from src/backend/hosts/managers/types.ts rename to src/backend/hosts/metrics/managers/types.ts diff --git a/src/backend/hosts/managers/users.ts b/src/backend/hosts/metrics/managers/users.ts similarity index 100% rename from src/backend/hosts/managers/users.ts rename to src/backend/hosts/metrics/managers/users.ts diff --git a/src/backend/hosts/managers/validation.ts b/src/backend/hosts/metrics/managers/validation.ts similarity index 100% rename from src/backend/hosts/managers/validation.ts rename to src/backend/hosts/metrics/managers/validation.ts diff --git a/src/backend/hosts/managers/wireguard.ts b/src/backend/hosts/metrics/managers/wireguard.ts similarity index 100% rename from src/backend/hosts/managers/wireguard.ts rename to src/backend/hosts/metrics/managers/wireguard.ts diff --git a/src/backend/hosts/host-metrics-preferences-routes.ts b/src/backend/hosts/metrics/preferences-routes.ts similarity index 97% rename from src/backend/hosts/host-metrics-preferences-routes.ts rename to src/backend/hosts/metrics/preferences-routes.ts index c3210c8d..63b983ad 100644 --- a/src/backend/hosts/host-metrics-preferences-routes.ts +++ b/src/backend/hosts/metrics/preferences-routes.ts @@ -1,12 +1,12 @@ import type { Express, RequestHandler } from "express"; -import type { AuthenticatedRequest } from "../../types/index.js"; -import { createCurrentHostMetricsPreferenceRepository } from "../database/repositories/factory.js"; -import { statsLogger } from "../utils/logger.js"; +import type { AuthenticatedRequest } from "../../../types/index.js"; +import { createCurrentHostMetricsPreferenceRepository } from "../../database/repositories/factory.js"; +import { statsLogger } from "../../utils/logger.js"; import { deriveEnabledWidgets, defaultLayoutFromWidgets, type HostMetricsLayout, -} from "../../types/host-metrics.js"; +} from "../../../types/host-metrics.js"; interface PrefStatsConfig { enabledWidgets?: string[]; diff --git a/src/backend/hosts/host-metrics-sessions.ts b/src/backend/hosts/metrics/sessions.ts similarity index 97% rename from src/backend/hosts/host-metrics-sessions.ts rename to src/backend/hosts/metrics/sessions.ts index fb9aa71f..c23b6f35 100644 --- a/src/backend/hosts/host-metrics-sessions.ts +++ b/src/backend/hosts/metrics/sessions.ts @@ -1,5 +1,5 @@ import type { Client, ConnectConfig } from "ssh2"; -import { statsLogger } from "../utils/logger.js"; +import { statsLogger } from "../../utils/logger.js"; export interface MetricsSession { client: Client; diff --git a/src/backend/hosts/host-metrics-settings-routes.ts b/src/backend/hosts/metrics/settings-routes.ts similarity index 98% rename from src/backend/hosts/host-metrics-settings-routes.ts rename to src/backend/hosts/metrics/settings-routes.ts index 5540b4d2..f7f64ace 100644 --- a/src/backend/hosts/host-metrics-settings-routes.ts +++ b/src/backend/hosts/metrics/settings-routes.ts @@ -1,6 +1,6 @@ import type { Express, RequestHandler } from "express"; -import { statsLogger } from "../utils/logger.js"; -import { createCurrentSettingsRepository } from "../database/repositories/factory.js"; +import { statsLogger } from "../../utils/logger.js"; +import { createCurrentSettingsRepository } from "../../database/repositories/factory.js"; type HostMetricsSettingsConfig = { statusCheckInterval: number; diff --git a/src/backend/hosts/host-metrics-state.ts b/src/backend/hosts/metrics/state.ts similarity index 100% rename from src/backend/hosts/host-metrics-state.ts rename to src/backend/hosts/metrics/state.ts diff --git a/src/backend/hosts/host-metrics-viewer-routes.ts b/src/backend/hosts/metrics/viewer-routes.ts similarity index 97% rename from src/backend/hosts/host-metrics-viewer-routes.ts rename to src/backend/hosts/metrics/viewer-routes.ts index c044833d..0467585f 100644 --- a/src/backend/hosts/host-metrics-viewer-routes.ts +++ b/src/backend/hosts/metrics/viewer-routes.ts @@ -1,7 +1,7 @@ import type { Express } from "express"; -import type { AuthenticatedRequest } from "../../types/index.js"; -import { statsLogger } from "../utils/logger.js"; -import { DataCrypto } from "../utils/data-crypto.js"; +import type { AuthenticatedRequest } from "../../../types/index.js"; +import { statsLogger } from "../../utils/logger.js"; +import { DataCrypto } from "../../utils/data-crypto.js"; type ViewerStatsConfig = { metricsEnabled: boolean; diff --git a/src/backend/hosts/widgets/common-utils.ts b/src/backend/hosts/metrics/widgets/common-utils.ts similarity index 100% rename from src/backend/hosts/widgets/common-utils.ts rename to src/backend/hosts/metrics/widgets/common-utils.ts diff --git a/src/backend/hosts/widgets/cpu-collector.ts b/src/backend/hosts/metrics/widgets/cpu-collector.ts similarity index 100% rename from src/backend/hosts/widgets/cpu-collector.ts rename to src/backend/hosts/metrics/widgets/cpu-collector.ts diff --git a/src/backend/hosts/widgets/disk-collector.ts b/src/backend/hosts/metrics/widgets/disk-collector.ts similarity index 100% rename from src/backend/hosts/widgets/disk-collector.ts rename to src/backend/hosts/metrics/widgets/disk-collector.ts diff --git a/src/backend/hosts/widgets/firewall-collector.ts b/src/backend/hosts/metrics/widgets/firewall-collector.ts similarity index 99% rename from src/backend/hosts/widgets/firewall-collector.ts rename to src/backend/hosts/metrics/widgets/firewall-collector.ts index 1043ee39..10d816ef 100644 --- a/src/backend/hosts/widgets/firewall-collector.ts +++ b/src/backend/hosts/metrics/widgets/firewall-collector.ts @@ -4,7 +4,7 @@ import type { FirewallMetrics, FirewallChain, FirewallRule, -} from "../../../types/stats-widgets.js"; +} from "../../../../types/stats-widgets.js"; function parseIptablesRule(line: string): FirewallRule | null { if (!line.startsWith("-A ")) return null; diff --git a/src/backend/hosts/widgets/login-stats-collector.ts b/src/backend/hosts/metrics/widgets/login-stats-collector.ts similarity index 100% rename from src/backend/hosts/widgets/login-stats-collector.ts rename to src/backend/hosts/metrics/widgets/login-stats-collector.ts diff --git a/src/backend/hosts/widgets/memory-collector.ts b/src/backend/hosts/metrics/widgets/memory-collector.ts similarity index 100% rename from src/backend/hosts/widgets/memory-collector.ts rename to src/backend/hosts/metrics/widgets/memory-collector.ts diff --git a/src/backend/hosts/widgets/network-collector.ts b/src/backend/hosts/metrics/widgets/network-collector.ts similarity index 100% rename from src/backend/hosts/widgets/network-collector.ts rename to src/backend/hosts/metrics/widgets/network-collector.ts diff --git a/src/backend/hosts/widgets/ports-collector.ts b/src/backend/hosts/metrics/widgets/ports-collector.ts similarity index 98% rename from src/backend/hosts/widgets/ports-collector.ts rename to src/backend/hosts/metrics/widgets/ports-collector.ts index 7406909e..15713761 100644 --- a/src/backend/hosts/widgets/ports-collector.ts +++ b/src/backend/hosts/metrics/widgets/ports-collector.ts @@ -3,7 +3,7 @@ import { execCommand } from "./common-utils.js"; import type { PortsMetrics, ListeningPort, -} from "../../../types/stats-widgets.js"; +} from "../../../../types/stats-widgets.js"; function parseSsOutput(output: string): ListeningPort[] { const ports: ListeningPort[] = []; diff --git a/src/backend/hosts/widgets/processes-collector.ts b/src/backend/hosts/metrics/widgets/processes-collector.ts similarity index 100% rename from src/backend/hosts/widgets/processes-collector.ts rename to src/backend/hosts/metrics/widgets/processes-collector.ts diff --git a/src/backend/hosts/widgets/system-collector.ts b/src/backend/hosts/metrics/widgets/system-collector.ts similarity index 100% rename from src/backend/hosts/widgets/system-collector.ts rename to src/backend/hosts/metrics/widgets/system-collector.ts diff --git a/src/backend/hosts/widgets/temperature-collector.ts b/src/backend/hosts/metrics/widgets/temperature-collector.ts similarity index 100% rename from src/backend/hosts/widgets/temperature-collector.ts rename to src/backend/hosts/metrics/widgets/temperature-collector.ts diff --git a/src/backend/hosts/widgets/uptime-collector.ts b/src/backend/hosts/metrics/widgets/uptime-collector.ts similarity index 100% rename from src/backend/hosts/widgets/uptime-collector.ts rename to src/backend/hosts/metrics/widgets/uptime-collector.ts diff --git a/src/backend/hosts/terminal.ts b/src/backend/hosts/terminal/index.ts similarity index 97% rename from src/backend/hosts/terminal.ts rename to src/backend/hosts/terminal/index.ts index 14b695cf..f23b2a10 100644 --- a/src/backend/hosts/terminal.ts +++ b/src/backend/hosts/terminal/index.ts @@ -5,36 +5,36 @@ import ssh2Pkg, { type PseudoTtyOptions, } from "ssh2"; const { Client, utils: ssh2Utils } = ssh2Pkg; -import { buildSSHAlgorithms } from "../utils/ssh-algorithms.js"; +import { buildSSHAlgorithms } from "../../utils/ssh-algorithms.js"; import axios from "axios"; -import { createCurrentHostResolutionRepository } from "../database/repositories/factory.js"; -import { sshLogger, authLogger } from "../utils/logger.js"; -import { logAudit } from "../utils/audit-logger.js"; -import { AuthManager } from "../utils/auth-manager.js"; -import { DataCrypto } from "../utils/data-crypto.js"; +import { createCurrentHostResolutionRepository } from "../../database/repositories/factory.js"; +import { sshLogger, authLogger } from "../../utils/logger.js"; +import { logAudit } from "../../utils/audit-logger.js"; +import { AuthManager } from "../../utils/auth-manager.js"; +import { DataCrypto } from "../../utils/data-crypto.js"; import { createSocks5Connection, type SOCKS5Config, -} from "../utils/socks5-helper.js"; -import { SSHAuthManager } from "./auth-manager.js"; -import type { ProxyNode } from "../../types/index.js"; -import { SSHHostKeyVerifier } from "./host-key-verifier.js"; -import { createJumpHostChain } from "./jump-host-chain.js"; -import { sessionManager } from "./terminal-session-manager.js"; +} from "../../utils/socks5-helper.js"; +import { SSHAuthManager } from "../auth-manager.js"; +import type { ProxyNode } from "../../../types/index.js"; +import { SSHHostKeyVerifier } from "../host-key-verifier.js"; +import { createJumpHostChain } from "../jump-host-chain.js"; +import { sessionManager } from "./session-manager.js"; import { detectTmux, attachOrCreateTmuxSession, waitForTmuxSession, -} from "./tmux-helper.js"; +} from "../tmux/helper.js"; import { MemoryAgent, performPortKnocking, resolveAgentSocket, -} from "./terminal-auth-helpers.js"; -import { isWindowsSftpPath, sftpPathToLocalPath } from "./transfer-paths.js"; -import { preparePrivateKeyForSSH2 } from "../utils/ssh-key-utils.js"; -import { triggerLoginAlert } from "../utils/alert-trigger.js"; -import { isRetriableDnsError, resolveHostForSshConnect } from "./ssh-dns.js"; +} from "../terminal-auth-helpers.js"; +import { isWindowsSftpPath, sftpPathToLocalPath } from "../transfer-paths.js"; +import { preparePrivateKeyForSSH2 } from "../../utils/ssh-key-utils.js"; +import { triggerLoginAlert } from "../../utils/alert-trigger.js"; +import { isRetriableDnsError, resolveHostForSshConnect } from "../ssh-dns.js"; interface ConnectToHostData { cols: number; @@ -781,9 +781,9 @@ wss.on("connection", async (ws: WebSocket, req) => { case "opkssh_start_auth": { const opksshData = data as { hostId: number }; try { - const { startOPKSSHAuth } = await import("./opkssh-auth.js"); + const { startOPKSSHAuth } = await import("../opkssh-auth.js"); const { getRequestOrigin } = - await import("../utils/request-origin.js"); + await import("../../utils/request-origin.js"); const host = await createCurrentHostResolutionRepository().findHostById( opksshData.hostId, @@ -836,7 +836,7 @@ wss.on("connection", async (ws: WebSocket, req) => { case "opkssh_cancel": { const cancelData = data as { requestId: string }; try { - const { cancelAuthSession } = await import("./opkssh-auth.js"); + const { cancelAuthSession } = await import("../opkssh-auth.js"); cancelAuthSession(cancelData.requestId); resetConnectionState(); } catch (error) { @@ -898,9 +898,9 @@ wss.on("connection", async (ws: WebSocket, req) => { const vaultData = data as { hostId: number }; try { const { loadVaultProfileForHost, startVaultAuth } = - await import("./vault-oidc-auth.js"); + await import("../vault-oidc-auth.js"); const { getRequestOrigin } = - await import("../utils/request-origin.js"); + await import("../../utils/request-origin.js"); const profile = await loadVaultProfileForHost( vaultData.hostId, userId, @@ -947,7 +947,7 @@ wss.on("connection", async (ws: WebSocket, req) => { const cancelData = data as { hostId: number }; try { const { cancelVaultAuthByHost } = - await import("./vault-oidc-auth.js"); + await import("../vault-oidc-auth.js"); cancelVaultAuthByHost(userId, cancelData.hostId); resetConnectionState(); } catch (error) { @@ -1155,7 +1155,7 @@ wss.on("connection", async (ws: WebSocket, req) => { if (id && userId) { try { - const { resolveHostById } = await import("./host-resolver.js"); + const { resolveHostById } = await import("../host-resolver.js"); resolvedHostData = (await resolveHostById( id, userId, @@ -1892,7 +1892,7 @@ wss.on("connection", async (ws: WebSocket, req) => { (async () => { try { - const { invalidateOPKSSHToken } = await import("./opkssh-auth.js"); + const { invalidateOPKSSHToken } = await import("../opkssh-auth.js"); await invalidateOPKSSHToken(userId, id, "SSH auth failed"); } catch (invalidateError) { sshLogger.error("Failed to invalidate OPKSSH token", { @@ -1945,7 +1945,7 @@ wss.on("connection", async (ws: WebSocket, req) => { )?.id; if (profileId) { const { deleteVaultCert } = - await import("./vault-signer-auth.js"); + await import("../vault-signer-auth.js"); await deleteVaultCert(userId, profileId); } } catch (invalidateError) { @@ -2377,7 +2377,7 @@ wss.on("connection", async (ws: WebSocket, req) => { resolvedCredentials.certPublicKey.trim() ) { try { - const { setupCACertAuth } = await import("./opkssh-cert-auth.js"); + const { setupCACertAuth } = await import("../opkssh-cert-auth.js"); await setupCACertAuth( connectConfig, sshConn, @@ -2440,7 +2440,7 @@ wss.on("connection", async (ws: WebSocket, req) => { } else if (resolvedCredentials.authType === "opkssh") { sendLog("auth", "info", "Using OPKSSH certificate authentication"); try { - const { getOPKSSHToken } = await import("./opkssh-auth.js"); + const { getOPKSSHToken } = await import("../opkssh-auth.js"); const token = await getOPKSSHToken(userId, id); if (!token) { @@ -2460,7 +2460,7 @@ wss.on("connection", async (ws: WebSocket, req) => { sendLog("auth", "info", "Using cached OPKSSH certificate"); - const { setupOPKSSHCertAuth } = await import("./opkssh-cert-auth.js"); + const { setupOPKSSHCertAuth } = await import("../opkssh-cert-auth.js"); await setupOPKSSHCertAuth(connectConfig, sshConn, token, username); } catch (opksshError) { sshLogger.error("OPKSSH authentication error", opksshError, { @@ -2490,7 +2490,7 @@ wss.on("connection", async (ws: WebSocket, req) => { throw new Error("Host has no Vault signer profile configured"); } - const { getVaultCert } = await import("./vault-signer-auth.js"); + const { getVaultCert } = await import("../vault-signer-auth.js"); const cert = await getVaultCert(userId, vaultProfile.id); if (!cert) { @@ -2510,7 +2510,7 @@ wss.on("connection", async (ws: WebSocket, req) => { sendLog("auth", "info", "Using cached Vault-signed certificate"); - const { setupOPKSSHCertAuth } = await import("./opkssh-cert-auth.js"); + const { setupOPKSSHCertAuth } = await import("../opkssh-cert-auth.js"); await setupOPKSSHCertAuth( connectConfig, sshConn, diff --git a/src/backend/hosts/terminal-session-manager.ts b/src/backend/hosts/terminal/session-manager.ts similarity index 99% rename from src/backend/hosts/terminal-session-manager.ts rename to src/backend/hosts/terminal/session-manager.ts index 1d83de9f..1e1d3845 100644 --- a/src/backend/hosts/terminal-session-manager.ts +++ b/src/backend/hosts/terminal/session-manager.ts @@ -2,11 +2,11 @@ import { type Client, type ClientChannel } from "ssh2"; import { WebSocket } from "ws"; import fs from "fs"; import path from "path"; -import { sshLogger } from "../utils/logger.js"; +import { sshLogger } from "../../utils/logger.js"; import { getCurrentSettingValue, createCurrentSessionRecordingRepository, -} from "../database/repositories/factory.js"; +} from "../../database/repositories/factory.js"; const MAX_BUFFER_BYTES = 512 * 1024; const DATA_DIR = process.env.DATA_DIR ?? "./db/data"; diff --git a/src/backend/hosts/tmux-helper.ts b/src/backend/hosts/tmux/helper.ts similarity index 99% rename from src/backend/hosts/tmux-helper.ts rename to src/backend/hosts/tmux/helper.ts index ae07ce9a..22b886c8 100644 --- a/src/backend/hosts/tmux-helper.ts +++ b/src/backend/hosts/tmux/helper.ts @@ -1,5 +1,5 @@ import type { Client, ClientChannel } from "ssh2"; -import { sshLogger } from "../utils/logger.js"; +import { sshLogger } from "../../utils/logger.js"; export interface TmuxSessionInfo { name: string; diff --git a/src/backend/hosts/tmux-monitor.ts b/src/backend/hosts/tmux/index.ts similarity index 96% rename from src/backend/hosts/tmux-monitor.ts rename to src/backend/hosts/tmux/index.ts index aca506d7..c50bf7bd 100644 --- a/src/backend/hosts/tmux-monitor.ts +++ b/src/backend/hosts/tmux/index.ts @@ -1,28 +1,28 @@ import express from "express"; import cookieParser from "cookie-parser"; import { Client, type ConnectConfig } from "ssh2"; -import { createCorsMiddleware } from "../utils/cors-config.js"; -import { AuthManager } from "../utils/auth-manager.js"; -import { DataCrypto } from "../utils/data-crypto.js"; +import { createCorsMiddleware } from "../../utils/cors-config.js"; +import { AuthManager } from "../../utils/auth-manager.js"; +import { DataCrypto } from "../../utils/data-crypto.js"; import { createCurrentTmuxSessionTagRepository, createCurrentUserRepository, -} from "../database/repositories/factory.js"; -import { logAudit, getRequestMeta } from "../utils/audit-logger.js"; -import { sshLogger } from "../utils/logger.js"; -import { SSH_ALGORITHMS } from "../utils/ssh-algorithms.js"; -import { preparePrivateKeyForSSH2 } from "../utils/ssh-key-utils.js"; -import { SSHHostKeyVerifier } from "./host-key-verifier.js"; -import { resolveHostById, checkHostAccess } from "./host-resolver.js"; -import { createJumpHostChain } from "./jump-host-chain.js"; -import { applyAgentAuth } from "./terminal-auth-helpers.js"; +} from "../../database/repositories/factory.js"; +import { logAudit, getRequestMeta } from "../../utils/audit-logger.js"; +import { sshLogger } from "../../utils/logger.js"; +import { SSH_ALGORITHMS } from "../../utils/ssh-algorithms.js"; +import { preparePrivateKeyForSSH2 } from "../../utils/ssh-key-utils.js"; +import { SSHHostKeyVerifier } from "../host-key-verifier.js"; +import { resolveHostById, checkHostAccess } from "../host-resolver.js"; +import { createJumpHostChain } from "../jump-host-chain.js"; +import { applyAgentAuth } from "../terminal-auth-helpers.js"; import { createSocks5Connection, type SOCKS5Config, -} from "../utils/socks5-helper.js"; -import { withConnection } from "./ssh-connection-pool.js"; -import { resolveSshConnectConfigHost } from "./ssh-dns.js"; -import { execCommand, tmuxCommand } from "./tmux-helper.js"; +} from "../../utils/socks5-helper.js"; +import { withConnection } from "../ssh-connection-pool.js"; +import { resolveSshConnectConfigHost } from "../ssh-dns.js"; +import { execCommand, tmuxCommand } from "./helper.js"; import { SEP, parseSessions, @@ -37,8 +37,8 @@ import { type TmuxSessionSummary, type TmuxWindow, type PaneMetrics, -} from "./tmux-monitor-helpers.js"; -import type { SSHHost, AuthenticatedRequest } from "../../types/index.js"; +} from "./monitor-helpers.js"; +import type { SSHHost, AuthenticatedRequest } from "../../../types/index.js"; const PANE_ID_RE = /^%\d+$/; // tmux session names cannot contain ":" or "."; keep to a conservative @@ -124,7 +124,7 @@ export function connectToHost(host: SSHHost): () => Promise { if (host.authType === "vault") { const { setupVaultSshSignerAuth } = - await import("./vault-ssh-connect.js"); + await import("../vault-ssh-connect.js"); await setupVaultSshSignerAuth(config, client, host); } diff --git a/src/backend/hosts/tmux-monitor-helpers.ts b/src/backend/hosts/tmux/monitor-helpers.ts similarity index 100% rename from src/backend/hosts/tmux-monitor-helpers.ts rename to src/backend/hosts/tmux/monitor-helpers.ts diff --git a/src/backend/hosts/tunnel-c2s-relay-utils.ts b/src/backend/hosts/tunnel/c2s-relay-utils.ts similarity index 100% rename from src/backend/hosts/tunnel-c2s-relay-utils.ts rename to src/backend/hosts/tunnel/c2s-relay-utils.ts diff --git a/src/backend/hosts/tunnel-c2s-relay.ts b/src/backend/hosts/tunnel/c2s-relay.ts similarity index 96% rename from src/backend/hosts/tunnel-c2s-relay.ts rename to src/backend/hosts/tunnel/c2s-relay.ts index af71f67c..1d03d870 100644 --- a/src/backend/hosts/tunnel-c2s-relay.ts +++ b/src/backend/hosts/tunnel/c2s-relay.ts @@ -1,9 +1,9 @@ import { Client, type ClientChannel } from "ssh2"; import type { WebSocket } from "ws"; -import type { TunnelConfig } from "../../types/index.js"; -import { createSocks5Connection } from "../utils/socks5-helper.js"; -import { tunnelLogger } from "../utils/logger.js"; -import { PermissionManager } from "../utils/permission-manager.js"; +import type { TunnelConfig } from "../../../types/index.js"; +import { createSocks5Connection } from "../../utils/socks5-helper.js"; +import { tunnelLogger } from "../../utils/logger.js"; +import { PermissionManager } from "../../utils/permission-manager.js"; import { applyAuthOptions, bindForwardIn, @@ -11,12 +11,9 @@ import { forwardOut, getManagedTunnelAlgorithms, unbindForwardIn, -} from "./tunnel-ssh-primitives.js"; -import { - sendC2SMessage, - writeC2SRemoteChunk, -} from "./tunnel-c2s-relay-utils.js"; -import { getTunnelMode } from "./tunnel-utils.js"; +} from "./ssh-primitives.js"; +import { sendC2SMessage, writeC2SRemoteChunk } from "./c2s-relay-utils.js"; +import { getTunnelMode } from "./utils.js"; export type C2SOpenMessage = { type: "open" | "test"; @@ -45,7 +42,7 @@ async function resolveC2STunnelSource( throw new Error("Access denied to this host"); } - const { resolveHostById } = await import("./host-resolver.js"); + const { resolveHostById } = await import("../host-resolver.js"); const resolvedHost = await resolveHostById(tunnelConfig.sourceHostId, userId); if (!resolvedHost) { throw new Error("Endpoint SSH host not found"); diff --git a/src/backend/hosts/tunnel/index.ts b/src/backend/hosts/tunnel/index.ts index 555328e0..bbbfc4fb 100644 --- a/src/backend/hosts/tunnel/index.ts +++ b/src/backend/hosts/tunnel/index.ts @@ -12,12 +12,12 @@ import { describeC2SRelayError, extractRequestToken, sendC2SError, -} from "../tunnel-c2s-relay-utils.js"; +} from "./c2s-relay-utils.js"; import { handleC2SRelayOpen, handleC2SRelayTest, type C2SOpenMessage, -} from "../tunnel-c2s-relay.js"; +} from "./c2s-relay.js"; import { registerTunnelRoutes } from "./routes.js"; import { initializeAutoStartTunnels } from "./manager.js"; diff --git a/src/backend/hosts/tunnel/manager.ts b/src/backend/hosts/tunnel/manager.ts index e6ec2217..527c5934 100644 --- a/src/backend/hosts/tunnel/manager.ts +++ b/src/backend/hosts/tunnel/manager.ts @@ -31,7 +31,7 @@ import { getManagedTunnelAlgorithms, pipeTunnelStreams, unbindForwardIn, -} from "../tunnel-ssh-primitives.js"; +} from "./ssh-primitives.js"; import { classifyTunnelError, getTunnelBindHost, @@ -39,10 +39,10 @@ import { getTunnelMode, getTunnelScope, normalizeTunnelName, -} from "../tunnel-utils.js"; +} from "./utils.js"; import { resolveSshConnectConfigHost } from "../ssh-dns.js"; -import { handleSocks5Connect } from "../tunnel-socks5-relay.js"; +import { handleSocks5Connect } from "./socks5-relay.js"; export const activeTunnels = new Map(); export const retryCounters = new Map(); diff --git a/src/backend/hosts/tunnel/routes.ts b/src/backend/hosts/tunnel/routes.ts index 4cb44d04..9e9d77cd 100644 --- a/src/backend/hosts/tunnel/routes.ts +++ b/src/backend/hosts/tunnel/routes.ts @@ -12,7 +12,7 @@ import { SystemCrypto } from "../../utils/system-crypto.js"; import { AuthManager } from "../../utils/auth-manager.js"; import { PermissionManager } from "../../utils/permission-manager.js"; -import { getTunnelMode, validateTunnelConfig } from "../tunnel-utils.js"; +import { getTunnelMode, validateTunnelConfig } from "./utils.js"; import { tunnelConfigs, diff --git a/src/backend/hosts/tunnel-socks5-relay.ts b/src/backend/hosts/tunnel/socks5-relay.ts similarity index 98% rename from src/backend/hosts/tunnel-socks5-relay.ts rename to src/backend/hosts/tunnel/socks5-relay.ts index fa615745..958ce7a6 100644 --- a/src/backend/hosts/tunnel-socks5-relay.ts +++ b/src/backend/hosts/tunnel/socks5-relay.ts @@ -1,5 +1,5 @@ import type { Duplex } from "stream"; -import { tunnelLogger } from "../utils/logger.js"; +import { tunnelLogger } from "../../utils/logger.js"; function parseSocksAddress(buffer: Buffer): { address: string; diff --git a/src/backend/hosts/tunnel-ssh-primitives.ts b/src/backend/hosts/tunnel/ssh-primitives.ts similarity index 97% rename from src/backend/hosts/tunnel-ssh-primitives.ts rename to src/backend/hosts/tunnel/ssh-primitives.ts index 62b1bed0..96d2abbf 100644 --- a/src/backend/hosts/tunnel-ssh-primitives.ts +++ b/src/backend/hosts/tunnel/ssh-primitives.ts @@ -1,7 +1,7 @@ import { Client, type ClientChannel } from "ssh2"; import type { Duplex } from "stream"; -import { SSH_ALGORITHMS } from "../utils/ssh-algorithms.js"; -import { tunnelLogger } from "../utils/logger.js"; +import { SSH_ALGORITHMS } from "../../utils/ssh-algorithms.js"; +import { tunnelLogger } from "../../utils/logger.js"; export function getManagedTunnelAlgorithms() { return { diff --git a/src/backend/hosts/tunnel-utils.ts b/src/backend/hosts/tunnel/utils.ts similarity index 96% rename from src/backend/hosts/tunnel-utils.ts rename to src/backend/hosts/tunnel/utils.ts index 1d879272..d489e447 100644 --- a/src/backend/hosts/tunnel-utils.ts +++ b/src/backend/hosts/tunnel/utils.ts @@ -1,5 +1,5 @@ -import type { ErrorType, TunnelConfig } from "../../types/index.js"; -import { tunnelLogger } from "../utils/logger.js"; +import type { ErrorType, TunnelConfig } from "../../../types/index.js"; +import { tunnelLogger } from "../../utils/logger.js"; export function classifyTunnelError(errorMessage: string): ErrorType { if (!errorMessage) return "UNKNOWN"; diff --git a/src/backend/starter.ts b/src/backend/starter.ts index 113fb29a..b7058045 100644 --- a/src/backend/starter.ts +++ b/src/backend/starter.ts @@ -154,13 +154,13 @@ import { const dbServer = await import("./database/database.js"); await (dbServer as unknown as { serverReady: Promise }).serverReady; - await import("./hosts/terminal.js"); + await import("./hosts/terminal/index.js"); await import("./hosts/tunnel/index.js"); - await import("./hosts/file-manager.js"); - await import("./hosts/host-metrics.js"); + await import("./hosts/file-manager/index.js"); + await import("./hosts/metrics/index.js"); await import("./hosts/docker/index.js"); await import("./hosts/docker/console.js"); - await import("./hosts/tmux-monitor.js"); // --- tmux-monitor --- + await import("./hosts/tmux/index.js"); // --- tmux-monitor --- await import("./hosts/serial.js"); await import("./services/dashboard.js"); await import("./services/homepage.js"); diff --git a/src/backend/tests/hosts/file-manager-operation-commands.test.ts b/src/backend/tests/hosts/file-manager/operation-commands.test.ts similarity index 94% rename from src/backend/tests/hosts/file-manager-operation-commands.test.ts rename to src/backend/tests/hosts/file-manager/operation-commands.test.ts index 80de1170..472c2d24 100644 --- a/src/backend/tests/hosts/file-manager-operation-commands.test.ts +++ b/src/backend/tests/hosts/file-manager/operation-commands.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from "vitest"; -import { buildDeleteCommand } from "../../hosts/file-manager-operation-commands.js"; +import { buildDeleteCommand } from "../../../hosts/file-manager/operation-commands.js"; describe("buildDeleteCommand", () => { it("builds a PowerShell 5.1 compatible delete command for Windows files", () => { diff --git a/src/backend/tests/hosts/file-manager-utils.test.ts b/src/backend/tests/hosts/file-manager/utils.test.ts similarity index 99% rename from src/backend/tests/hosts/file-manager-utils.test.ts rename to src/backend/tests/hosts/file-manager/utils.test.ts index daf5507e..1d4360e6 100644 --- a/src/backend/tests/hosts/file-manager-utils.test.ts +++ b/src/backend/tests/hosts/file-manager/utils.test.ts @@ -6,7 +6,7 @@ import { getMimeType, detectBinary, parseLsDateToTimestamp, -} from "../../hosts/file-manager-utils.js"; +} from "../../../hosts/file-manager/utils.js"; describe("isExecutableFile", () => { it("flags scripts with execute permission", () => { diff --git a/src/backend/tests/hosts/managers/managers.test.ts b/src/backend/tests/hosts/managers/managers.test.ts index c878fedf..fa598ae7 100644 --- a/src/backend/tests/hosts/managers/managers.test.ts +++ b/src/backend/tests/hosts/managers/managers.test.ts @@ -2,8 +2,8 @@ import { describe, it, expect } from "vitest"; import { buildSudoCommand, shellSingleQuote, -} from "../../../hosts/managers/exec-elevated.js"; -import { parsePlatformProbe } from "../../../hosts/managers/platform.js"; +} from "../../../hosts/metrics/managers/exec-elevated.js"; +import { parsePlatformProbe } from "../../../hosts/metrics/managers/platform.js"; import { isValidSystemdUnit, isValidPid, @@ -15,47 +15,53 @@ import { isValidSignal, isValidServiceAction, isAllowedPath, -} from "../../../hosts/managers/validation.js"; +} from "../../../hosts/metrics/managers/validation.js"; import { parseServiceList, buildServiceActionCommand, -} from "../../../hosts/managers/services.js"; +} from "../../../hosts/metrics/managers/services.js"; import { parseProcessList, buildKillCommand, -} from "../../../hosts/managers/processes.js"; +} from "../../../hosts/metrics/managers/processes.js"; import { parseDfMounts, parseTopMemory, -} from "../../../hosts/managers/simple-reads.js"; +} from "../../../hosts/metrics/managers/simple-reads.js"; import { parseCrontab, serializeCrontab, isValidCronSchedule, buildApplyCrontabCommand, -} from "../../../hosts/managers/cron.js"; +} from "../../../hosts/metrics/managers/cron.js"; import { buildPackageActionCommand, parseUpgradable, buildListUpgradableCommand, -} from "../../../hosts/managers/packages.js"; +} from "../../../hosts/metrics/managers/packages.js"; import { buildIssueCommand, buildRenewCommand, buildRevokeCommand, isValidCertName, parseCertbotCertificates, -} from "../../../hosts/managers/ssl.js"; +} from "../../../hosts/metrics/managers/ssl.js"; import { buildIptablesRuleCommand, buildNftRuleCommand, -} from "../../../hosts/managers/firewall.js"; -import { parsePasswd, parseSudoers } from "../../../hosts/managers/users.js"; +} from "../../../hosts/metrics/managers/firewall.js"; +import { + parsePasswd, + parseSudoers, +} from "../../../hosts/metrics/managers/users.js"; import { buildHealthCheckCommand, parseHealthResult, -} from "../../../hosts/managers/health.js"; -import { buildTailCommand, clampLines } from "../../../hosts/managers/logs.js"; +} from "../../../hosts/metrics/managers/health.js"; +import { + buildTailCommand, + clampLines, +} from "../../../hosts/metrics/managers/logs.js"; describe("exec-elevated", () => { it("single-quotes and escapes for the shell", () => { diff --git a/src/backend/tests/hosts/host-metrics-helpers.test.ts b/src/backend/tests/hosts/metrics/helpers.test.ts similarity index 97% rename from src/backend/tests/hosts/host-metrics-helpers.test.ts rename to src/backend/tests/hosts/metrics/helpers.test.ts index d32b6588..1fd0e280 100644 --- a/src/backend/tests/hosts/host-metrics-helpers.test.ts +++ b/src/backend/tests/hosts/metrics/helpers.test.ts @@ -4,8 +4,8 @@ import { supportsMetrics, isTcpPingEnabled, tcpPingThroughJumpHost, -} from "../../hosts/host-metrics-helpers.js"; -import { createConnectionLog } from "../../hosts/connection-log.js"; +} from "../../../hosts/metrics/helpers.js"; +import { createConnectionLog } from "../../../hosts/connection-log.js"; describe("supportsMetrics", () => { it("supports plain ssh hosts", () => { diff --git a/src/backend/tests/hosts/managers/exec-elevated.test.ts b/src/backend/tests/hosts/metrics/managers/exec-elevated.test.ts similarity index 96% rename from src/backend/tests/hosts/managers/exec-elevated.test.ts rename to src/backend/tests/hosts/metrics/managers/exec-elevated.test.ts index a66223a2..bed2bf2e 100644 --- a/src/backend/tests/hosts/managers/exec-elevated.test.ts +++ b/src/backend/tests/hosts/metrics/managers/exec-elevated.test.ts @@ -1,14 +1,14 @@ import { describe, it, expect, vi, beforeEach } from "vitest"; const execCommand = vi.fn(); -vi.mock("../../../hosts/widgets/common-utils.js", () => ({ +vi.mock("../../../../hosts/metrics/widgets/common-utils.js", () => ({ execCommand: (...args: unknown[]) => execCommand(...args), })); import { execElevated, ElevationError, -} from "../../../hosts/managers/exec-elevated.js"; +} from "../../../../hosts/metrics/managers/exec-elevated.js"; import type { Client } from "ssh2"; const fakeClient = {} as Client; diff --git a/src/backend/tests/hosts/host-metrics-state.test.ts b/src/backend/tests/hosts/metrics/state.test.ts similarity index 98% rename from src/backend/tests/hosts/host-metrics-state.test.ts rename to src/backend/tests/hosts/metrics/state.test.ts index 743eeeff..64068089 100644 --- a/src/backend/tests/hosts/host-metrics-state.test.ts +++ b/src/backend/tests/hosts/metrics/state.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it, vi } from "vitest"; import { ConcurrentLimiter, HostPollCache, -} from "../../hosts/host-metrics-state.js"; +} from "../../../hosts/metrics/state.js"; describe("ConcurrentLimiter", () => { it("never exceeds max concurrent runners", async () => { diff --git a/src/backend/tests/hosts/widgets/common-utils.test.ts b/src/backend/tests/hosts/metrics/widgets/common-utils.test.ts similarity index 89% rename from src/backend/tests/hosts/widgets/common-utils.test.ts rename to src/backend/tests/hosts/metrics/widgets/common-utils.test.ts index fbb0f4a7..ed64a916 100644 --- a/src/backend/tests/hosts/widgets/common-utils.test.ts +++ b/src/backend/tests/hosts/metrics/widgets/common-utils.test.ts @@ -1,5 +1,8 @@ import { describe, it, expect } from "vitest"; -import { toFixedNum, kibToGiB } from "../../../hosts/widgets/common-utils.js"; +import { + toFixedNum, + kibToGiB, +} from "../../../../hosts/metrics/widgets/common-utils.js"; describe("toFixedNum", () => { it("rounds to the requested digit count", () => { diff --git a/src/backend/tests/hosts/widgets/cpu-collector.test.ts b/src/backend/tests/hosts/metrics/widgets/cpu-collector.test.ts similarity index 92% rename from src/backend/tests/hosts/widgets/cpu-collector.test.ts rename to src/backend/tests/hosts/metrics/widgets/cpu-collector.test.ts index 7b809236..c4907d98 100644 --- a/src/backend/tests/hosts/widgets/cpu-collector.test.ts +++ b/src/backend/tests/hosts/metrics/widgets/cpu-collector.test.ts @@ -1,5 +1,5 @@ import { describe, it, expect } from "vitest"; -import { parseCpuLine } from "../../../hosts/widgets/cpu-collector.js"; +import { parseCpuLine } from "../../../../hosts/metrics/widgets/cpu-collector.js"; describe("parseCpuLine", () => { it("parses a standard /proc/stat cpu line", () => { diff --git a/src/backend/tests/hosts/widgets/temperature-collector.test.ts b/src/backend/tests/hosts/metrics/widgets/temperature-collector.test.ts similarity index 92% rename from src/backend/tests/hosts/widgets/temperature-collector.test.ts rename to src/backend/tests/hosts/metrics/widgets/temperature-collector.test.ts index 1218f18b..36757871 100644 --- a/src/backend/tests/hosts/widgets/temperature-collector.test.ts +++ b/src/backend/tests/hosts/metrics/widgets/temperature-collector.test.ts @@ -2,7 +2,7 @@ import { describe, expect, it } from "vitest"; import { parseSensorsOutput, parseSysfsThermalOutput, -} from "../../../hosts/widgets/temperature-collector.js"; +} from "../../../../hosts/metrics/widgets/temperature-collector.js"; describe("temperature collectors", () => { it("parses sysfs thermal zone output", () => { diff --git a/src/backend/tests/hosts/terminal-session-manager.test.ts b/src/backend/tests/hosts/terminal/session-manager.test.ts similarity index 94% rename from src/backend/tests/hosts/terminal-session-manager.test.ts rename to src/backend/tests/hosts/terminal/session-manager.test.ts index ad387f0c..9a369716 100644 --- a/src/backend/tests/hosts/terminal-session-manager.test.ts +++ b/src/backend/tests/hosts/terminal/session-manager.test.ts @@ -4,18 +4,18 @@ import { describe, it, expect, vi, beforeEach } from "vitest"; const mockCreate = vi.fn().mockResolvedValue({ id: 1 }); const mockUpdateEnded = vi.fn().mockResolvedValue(undefined); -vi.mock("../../database/db/index.js", () => ({ +vi.mock("../../../database/db/index.js", () => ({ getDb: () => ({}), })); -vi.mock("../../database/repositories/factory.js", () => ({ +vi.mock("../../../database/repositories/factory.js", () => ({ createCurrentSessionRecordingRepository: () => ({ create: mockCreate, updateEnded: mockUpdateEnded, }), })); -vi.mock("../../utils/logger.js", () => ({ +vi.mock("../../../utils/logger.js", () => ({ sshLogger: { info: vi.fn(), warn: vi.fn(), @@ -50,7 +50,7 @@ vi.mock("fs", () => ({ })); const { sessionManager } = - await import("../../hosts/terminal-session-manager.js"); + await import("../../../hosts/terminal/session-manager.js"); describe("TerminalSessionManager - session logging", () => { beforeEach(() => { diff --git a/src/backend/tests/hosts/tmux-helper.test.ts b/src/backend/tests/hosts/tmux/helper.test.ts similarity index 97% rename from src/backend/tests/hosts/tmux-helper.test.ts rename to src/backend/tests/hosts/tmux/helper.test.ts index 6c5b3baf..ccd60ac0 100644 --- a/src/backend/tests/hosts/tmux-helper.test.ts +++ b/src/backend/tests/hosts/tmux/helper.test.ts @@ -5,7 +5,7 @@ import { detectTmux, tmuxCommand, withTmuxPath, -} from "../../hosts/tmux-helper.js"; +} from "../../../hosts/tmux/helper.js"; describe("tmux command path handling", () => { it("adds common non-login shell tmux paths", () => { diff --git a/src/backend/tests/hosts/tmux-monitor-helpers.test.ts b/src/backend/tests/hosts/tmux/monitor-helpers.test.ts similarity index 99% rename from src/backend/tests/hosts/tmux-monitor-helpers.test.ts rename to src/backend/tests/hosts/tmux/monitor-helpers.test.ts index a698045d..a40059d5 100644 --- a/src/backend/tests/hosts/tmux-monitor-helpers.test.ts +++ b/src/backend/tests/hosts/tmux/monitor-helpers.test.ts @@ -9,7 +9,7 @@ import { buildPaneMetrics, attachPanesToWindows, shellEscape, -} from "../../hosts/tmux-monitor-helpers.js"; +} from "../../../hosts/tmux/monitor-helpers.js"; function join(...fields: (string | number)[]): string { return fields.join(SEP);