• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

apowers313 / servherd / 20961701317

13 Jan 2026 03:07PM UTC coverage: 82.727% (+1.2%) from 81.563%
20961701317

push

github

apowers313
test: improved test coverage to 81.56%

901 of 1027 branches covered (87.73%)

Branch coverage included in aggregate %.

3601 of 4415 relevant lines covered (81.56%)

13.72 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

64.44
/src/cli/commands/info.ts
1
import { RegistryService } from "../../services/registry.service.js";
1✔
2
import { ProcessService } from "../../services/process.service.js";
3
import type { ServerStatus } from "../../types/registry.js";
4
import { formatServerInfo } from "../output/formatters.js";
5
import { formatAsJson, formatErrorAsJson } from "../output/json-formatter.js";
6
import { logger } from "../../utils/logger.js";
7
import { ServherdError, ServherdErrorCode } from "../../types/errors.js";
8

9
export interface InfoCommandOptions {
10
  name: string;
11
}
12

13
export interface InfoCommandResult {
14
  name: string;
15
  status: ServerStatus;
16
  url: string;
17
  cwd: string;
18
  command: string;
19
  resolvedCommand: string;
20
  port: number;
21
  hostname: string;
22
  protocol: string;
23
  pid?: number;
24
  uptime?: number;
25
  restarts?: number;
26
  memory?: number;
27
  cpu?: number;
28
  tags?: string[];
29
  description?: string;
30
  env?: Record<string, string>;
31
  createdAt: string;
32
  pm2Name: string;
33
  outLogPath?: string;
34
  errLogPath?: string;
35
}
36

37
/**
38
 * Execute the info command
39
 */
40
export async function executeInfo(options: InfoCommandOptions): Promise<InfoCommandResult> {
12✔
41
  const registryService = new RegistryService();
12✔
42
  const processService = new ProcessService();
12✔
43

44
  try {
12✔
45
    // Load registry
46
    await registryService.load();
12✔
47

48
    // Find server by name
49
    const server = registryService.findByName(options.name);
12✔
50

51
    if (!server) {
12✔
52
      throw new ServherdError(
4✔
53
        ServherdErrorCode.SERVER_NOT_FOUND,
4✔
54
        `Server "${options.name}" not found`,
4✔
55
      );
4✔
56
    }
4✔
57

58
    // Connect to PM2 to get process details
59
    await processService.connect();
8✔
60

61
    // Get process info from PM2
62
    const procDesc = await processService.describe(server.pm2Name);
8✔
63

64
    // Build result
65
    const result: InfoCommandResult = {
8✔
66
      name: server.name,
8✔
67
      status: "unknown",
8✔
68
      url: `${server.protocol}://${server.hostname}:${server.port}`,
8✔
69
      cwd: server.cwd,
8✔
70
      command: server.command,
8✔
71
      resolvedCommand: server.resolvedCommand,
8✔
72
      port: server.port,
8✔
73
      hostname: server.hostname,
8✔
74
      protocol: server.protocol,
8✔
75
      tags: server.tags,
8✔
76
      description: server.description,
8✔
77
      env: server.env,
8✔
78
      createdAt: server.createdAt,
8✔
79
      pm2Name: server.pm2Name,
8✔
80
    };
8✔
81

82
    if (procDesc) {
10✔
83
      // Process exists in PM2
84
      const pm2Env = procDesc.pm2_env;
6✔
85

86
      result.status = pm2Env.status === "online" ? "online"
6✔
87
        : pm2Env.status === "stopped" || pm2Env.status === "stopping" ? "stopped"
1!
88
          : pm2Env.status === "errored" ? "errored"
×
89
            : "unknown";
×
90

91
      result.pid = procDesc.pid;
6✔
92
      result.uptime = pm2Env.pm_uptime;
6✔
93
      result.restarts = pm2Env.restart_time;
6✔
94
      result.outLogPath = pm2Env.pm_out_log_path;
6✔
95
      result.errLogPath = pm2Env.pm_err_log_path;
6✔
96

97
      if (procDesc.monit) {
6✔
98
        result.memory = procDesc.monit.memory;
6✔
99
        result.cpu = procDesc.monit.cpu;
6✔
100
      }
6✔
101
    }
6✔
102

103
    return result;
8✔
104
  } finally {
12✔
105
    processService.disconnect();
12✔
106
  }
12✔
107
}
12✔
108

109
/**
110
 * CLI action handler for info command
111
 */
112
export async function infoAction(name: string, options?: { json?: boolean }): Promise<void> {
×
113
  try {
×
114
    if (!name) {
×
115
      if (options?.json) {
×
116
        console.log(formatErrorAsJson(new Error("Server name is required")));
×
117
      } else {
×
118
        console.error("Error: Server name is required");
×
119
      }
×
120
      process.exitCode = 1;
×
121
      return;
×
122
    }
×
123

124
    const result = await executeInfo({ name });
×
125

126
    if (options?.json) {
×
127
      console.log(formatAsJson(result));
×
128
    } else {
×
129
      console.log(formatServerInfo(result));
×
130
    }
×
131
  } catch (error) {
×
132
    if (options?.json) {
×
133
      console.log(formatErrorAsJson(error));
×
134
    } else {
×
135
      const message = error instanceof Error ? error.message : String(error);
×
136
      console.error(`Error: ${message}`);
×
137
    }
×
138
    logger.error({ error }, "Info command failed");
×
139
    process.exitCode = 1;
×
140
  }
×
141
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc