• 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

85.37
/src/utils/names.ts
1
import { createHash } from "crypto";
1✔
2
import { FlexiHumanHash } from "flexi-human-hash";
3

4
// Shared instance for random name generation
5
const fhh = new FlexiHumanHash("{{adjective}}-{{noun}}");
1✔
6

7
/**
8
 * Normalize command + env into a consistent hashable string.
9
 * Used to generate deterministic server names.
10
 * @param command - The command string
11
 * @param env - Optional environment variables
12
 * @returns A normalized string suitable for hashing
13
 */
14
export function normalizeForHash(command: string, env?: Record<string, string>): string {
1✔
15
  // Normalize command: trim and collapse multiple spaces
16
  const normalizedCommand = command.trim().replace(/\s+/g, " ");
64✔
17

18
  // Normalize env: sort keys, create deterministic string
19
  let envString = "";
64✔
20
  if (env && Object.keys(env).length > 0) {
64✔
21
    envString = Object.keys(env)
31✔
22
      .sort()
31✔
23
      .map((key) => `${key}=${env[key] ?? ""}`)
31!
24
      .join("&");
31✔
25
  }
31✔
26

27
  // Combine with pipe separator
28
  return envString ? `${normalizedCommand}|${envString}` : normalizedCommand;
64✔
29
}
64✔
30

31
/**
32
 * Generate a deterministic name from command and environment.
33
 * Same inputs always produce the same name.
34
 * Uses crypto hash for determinism, then FlexiHumanHash for human-readable output.
35
 * @param command - The command string
36
 * @param env - Optional environment variables
37
 * @returns A deterministic human-readable name in adjective-noun format
38
 */
39
export function generateDeterministicName(command: string, env?: Record<string, string>): string {
1✔
40
  const hashInput = normalizeForHash(command, env);
53✔
41
  // Create a deterministic hash first
42
  const hashHex = createHash("sha256").update(hashInput).digest("hex");
53✔
43
  // Create a fresh FlexiHumanHash instance for deterministic output
44
  // (the library has internal state that causes non-determinism with reused instances)
45
  const deterministicFhh = new FlexiHumanHash("{{adjective}}-{{noun}}");
53✔
46
  return deterministicFhh.hash(hashHex);
53✔
47
}
53✔
48

49
/**
50
 * Generate a human-readable name in adjective-noun format
51
 * @param existing - Set of existing names to avoid duplicates
52
 * @param maxAttempts - Maximum number of attempts to generate a unique name
53
 * @returns A unique human-readable name
54
 */
55
export function generateName(existing?: Set<string>, maxAttempts = 100): string {
1✔
56
  for (let i = 0; i < maxAttempts; i++) {
14✔
57
    const name = fhh.hash();
14✔
58

59
    if (!existing || !existing.has(name)) {
14✔
60
      return name;
14✔
61
    }
14✔
62
  }
14!
63

64
  // Fallback: add a unique suffix if we can't find a unique name
65
  const baseName = fhh.hash();
×
66
  const timestamp = Date.now().toString(36).slice(-4);
×
67
  return `${baseName}-${timestamp}`;
×
68
}
×
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