All files / src/server cliUtils.ts

100% Statements 11/11
100% Branches 12/12
100% Functions 2/2
100% Lines 11/11

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73                                        3x                                       44x 22x   22x   22x 11x   11x 11x 3x   8x                                   22x    
/**
 * Lightweight CLI utility functions.
 *
 * This module intentionally has **no** imports from the EP client or
 * heavyweight server modules, so it can be loaded by `src/main.ts`
 * **before** the EP API client singleton is constructed.
 *
 * `timeout.ts` is a lightweight utility with zero heavyweight deps,
 * so importing {@link DEFAULT_TIMEOUTS} is safe here.
 *
 * @module server/cliUtils
 */
 
import { DEFAULT_TIMEOUTS } from '../utils/timeout.js';
 
/**
 * Default EP API request timeout in milliseconds — derived from the centralized
 * {@link DEFAULT_TIMEOUTS.EP_API_REQUEST_MS} constant in `timeout.ts` so there
 * is a single source of truth for the EP API request timeout value.
 */
export const DEFAULT_REQUEST_TIMEOUT_MS = DEFAULT_TIMEOUTS.EP_API_REQUEST_MS;
 
/**
 * Parse and validate a timeout string value.
 *
 * Accepts only strings consisting entirely of digits (`/^\d+$/`), then
 * verifies the resulting integer is positive and finite.
 *
 * @param value - Raw string value (e.g. from `--timeout` argument or env var)
 * @returns Parsed positive integer, or `undefined` if invalid
 *
 * @example
 * ```typescript
 * parseTimeoutValue('90000'); // 90000
 * parseTimeoutValue('10s');   // undefined (non-digit characters)
 * parseTimeoutValue('0');     // undefined (not positive)
 * parseTimeoutValue('');      // undefined
 * ```
 */
export function parseTimeoutValue(value: string | undefined): number | undefined {
  if (value === undefined || value.trim().length === 0) {
    return undefined;
  }
  const trimmed = value.trim();
  // Strict digits-only check — reject partially-numeric values like "10s"
  if (!/^\d+$/.test(trimmed)) {
    return undefined;
  }
  const parsed = Number.parseInt(trimmed, 10);
  if (!Number.isFinite(parsed) || parsed <= 0) {
    return undefined;
  }
  return parsed;
}
 
/**
 * Resolve the effective timeout value in milliseconds from the environment.
 *
 * This function only resolves the **environment-level** precedence:
 *   `EP_REQUEST_TIMEOUT_MS` env var → {@link DEFAULT_REQUEST_TIMEOUT_MS}
 *
 * The full precedence chain (including the `--timeout` CLI argument) is
 * handled by `applyTimeoutArg()` in `src/main.ts`, which sets the env var
 * **before** modules are loaded.
 *
 * Invalid / empty env values are silently ignored (fall through to default).
 *
 * @returns Effective timeout in milliseconds
 */
export function resolveEffectiveTimeout(): number {
  return parseTimeoutValue(process.env['EP_REQUEST_TIMEOUT_MS']) ?? DEFAULT_REQUEST_TIMEOUT_MS;
}