All files / context / log.ts

28.57% Branches 2/7
55.81% Lines 24/43
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
 
x2
x2
x2
 
 
 
 
 
 
 
 
 
 
 
 
 
x2
x5
 
 
 
 
 
x2091
 
 
x15
x5
x5
 
 
 
 
x5
x5
 
 
x2
x3
x3
x3
x3
x3
x3
x3
 
 
 
x3
x3
x3
 
 
 
 
 
x7
x3



















I


I

I
I































import type { Fn } from '../index.ts';
import { env, stdout, stderr, createLogUpdate, inspect } from '../deps.ts';
import { Name, joined, ANSI, stackTrace } from '../format.ts';
const { red, yellow, dim, gray } = ANSI;
/** Logging interface. */
export type Log = {
  prefix:     string,
  format?:    Fn<unknown[], string>,
  formatOne?: Fn<[string],  string>,
  info  (...args: unknown[]): unknown;
  log   (...args: unknown[]): unknown;
  debug (...args: unknown[]): unknown;
  warn  (...args: unknown[]): unknown;
  error (...args: unknown[]): unknown;
  trace (...args: unknown[]): unknown;
};
/** Create logger. */
export function Log <T extends Log> (context: Partial<T> = {}): T {
  context.prefix ??= '';
  context.format ??= (args: unknown[]) =>
    (context.prefix ? `${context.prefix} ` : '') +
      joined(' ', args.map(context.formatOne));
  context.formatOne ??= (x: unknown) => (typeof x === 'string') ? x :
    (x && (typeof x === 'object') && (x instanceof Error)) ? x.message :
    inspect(x, { depth: 10, colors: true });
  const logWidth = (stdout.getWindowSize()||[Number(env.COLUMNS)])[0]
    || Number(env.COLUMNS) || Infinity;
  const logUpdater = createLogUpdate(stdout, { defaultWidth: logWidth });
  context.info  = (...args: unknown[]) => logUpdater(context.format(args) as string);
  context.log   = (...args: unknown[]) => logUpdater.persist(context.format(args) as string);
  context.error = (...args: unknown[]) => logUpdater.persist(red(context.format(args)));
  context.warn  = (...args: unknown[]) => logUpdater.persist(yellow(context.format(args)));
  context.debug = (...args: unknown[]) => logUpdater.persist(dim(context.format(args)));
  context.trace = (...args: unknown[]) => console.trace(gray(5, context.format(args)+'\n'));
  return context as T;
}
/** Enable tracing for all `console.log` calls,
  * colorize them, and reroute to stderr. */
export function traceConsole () {
  if (!(console as { untrace?: Fn }).untrace) {
    const { log, info, warn, error } = globalThis.console;
    Object.assign(globalThis.console, {
      log:   traced(ANSI.yellow('log')),
      info:  traced(ANSI.blue('info')),
      warn:  traced(ANSI.yellow('warn')),
      error: traced(ANSI.red('error')),
      untrace: function fadromaUntraceConsole () {
        Object.assign(globalThis.console, { log, info, warn, error });
      }
    });
  }
  function traced (kind: string) {
    return (...args: unknown[]) => {
      const trace = ANSI.gray(8, stackTrace(3, 1).join('\n '));
      const line = args.map(x=>inspect(x, { depth: Infinity })).join(' ');
      stderr.write(`${kind} ${line} ${trace}\n`);
    };
  }
}