File size: 2,332 Bytes
e1ae2c6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
77
78
79
function parseBooleanEnv(value) {
  if (value === undefined || value === null || value === '') return false;
  const v = String(value).trim().toLowerCase();
  return v === '1' || v === 'true' || v === 'yes' || v === 'y' || v === 'on';
}

function isVerbose() {
  return parseBooleanEnv(process.env.MENAV_VERBOSE) || parseBooleanEnv(process.env.DEBUG);
}

function isColorEnabled() {
  if (process.env.NO_COLOR) return false;
  if (parseBooleanEnv(process.env.FORCE_COLOR)) return true;
  return Boolean(
    (process.stdout && process.stdout.isTTY) || (process.stderr && process.stderr.isTTY)
  );
}

function colorize(text, ansiCode) {
  if (!ansiCode || !isColorEnabled()) return text;
  return `\x1b[${ansiCode}m${text}\x1b[0m`;
}

function formatMeta(meta) {
  if (!meta || typeof meta !== 'object') return '';
  const entries = Object.entries(meta)
    .filter(([, value]) => value !== undefined && value !== null && value !== '')
    .map(([key, value]) => `${key}=${String(value)}`);
  if (entries.length === 0) return '';
  return ` (${entries.join(', ')})`;
}

function formatPrefix(level) {
  const base = `[${level}]`;
  if (level === 'ERROR') return colorize(base, 31);
  if (level === 'WARN') return colorize(base, 33);
  if (level === 'OK') return colorize(base, 32);
  return base;
}

function writeLine(level, scope, message, meta) {
  const prefix = formatPrefix(level);
  const scopePart = scope ? ` ${scope}:` : '';
  const line = `${prefix}${scopePart} ${message}${formatMeta(meta)}`;

  if (level === 'ERROR') {
    console.error(line);
  } else if (level === 'WARN') {
    console.warn(line);
  } else {
    console.log(line);
  }
}

function createLogger(scope) {
  const normalized = scope ? String(scope) : '';
  return {
    info: (message, meta) => writeLine('INFO', normalized, message, meta),
    warn: (message, meta) => writeLine('WARN', normalized, message, meta),
    error: (message, meta) => writeLine('ERROR', normalized, message, meta),
    ok: (message, meta) => writeLine('OK', normalized, message, meta),
  };
}

function startTimer() {
  const startedAt = process.hrtime.bigint();
  return () => Number((process.hrtime.bigint() - startedAt) / 1_000_000n);
}

module.exports = {
  createLogger,
  formatMeta,
  formatPrefix,
  isColorEnabled,
  isVerbose,
  parseBooleanEnv,
  startTimer,
};