All files / src/cli/output tty.ts

100% Statements 18/18
100% Branches 22/22
100% Functions 4/4
100% Lines 18/18

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 74 75 76                                        32x     32x 32x   32x       32x 18x 14x 1x 13x 1x   12x       32x 30x     32x   32x                     762x               108x             9x    
import chalk from 'chalk';
 
/**
 * Output mode configuration based on terminal capabilities.
 */
export interface OutputMode {
  /** Whether stdout is a TTY */
  isTTY: boolean;
  /** Whether colors are supported */
  supportsColor: boolean;
  /** Terminal width in columns */
  columns: number;
}
 
/**
 * Detect terminal capabilities.
 * @param colorOverride - Optional override for color support (--color / --no-color)
 */
export function detectOutputMode(colorOverride?: boolean): OutputMode {
  // Check both stderr and stdout for TTY - some environments have TTY on one but not the other
  const streamIsTTY = (process.stderr.isTTY || process.stdout.isTTY) ?? false;
 
  // Treat dumb terminals as non-TTY (e.g., TERM=dumb used by some editors/agents)
  const term = process.env['TERM'] ?? '';
  const isDumbTerminal = term === 'dumb' || term === '';
 
  const isTTY = streamIsTTY && !isDumbTerminal;
 
  // Determine color support
  let supportsColor: boolean;
  if (colorOverride !== undefined) {
    supportsColor = colorOverride;
  } else if (process.env['NO_COLOR']) {
    supportsColor = false;
  } else if (process.env['FORCE_COLOR']) {
    supportsColor = true;
  } else {
    supportsColor = isTTY && chalk.level > 0;
  }
 
  // Configure chalk based on color support
  if (!supportsColor) {
    chalk.level = 0;
  }
 
  const columns = process.stderr.columns ?? process.stdout.columns ?? 80;
 
  return {
    isTTY,
    supportsColor,
    columns,
  };
}
 
/**
 * Get a timestamp for CI/non-TTY output.
 */
export function timestamp(): string {
  return new Date().toISOString();
}
 
/**
 * Log a timestamped action message to stderr.
 * Used by action workflow steps (dedup, fix eval, stale resolution) for consistent output.
 */
export function logAction(message: string): void {
  console.error(`[${timestamp()}] warden: ${message}`);
}
 
/**
 * Log a timestamped warning to stderr.
 */
export function warnAction(message: string): void {
  console.error(`[${timestamp()}] warden: WARN: ${message}`);
}