{"version":3,"file":"console-log.mjs","names":[],"sources":["../../../../../../../@warlock.js/logger/src/channels/console-log.ts"],"sourcesContent":["import { colors } from \"@mongez/copper\";\r\nimport { inspect } from \"util\";\r\nimport { LogChannel } from \"../log-channel\";\r\nimport type { BasicLogConfigurations, LoggingData, LogLevel } from \"../types\";\r\n\r\nexport type ConsoleLogConfig = BasicLogConfigurations & {\r\n  /**\r\n   * Render the log entry's `context` object on a second line after the main\r\n   * message. When `false`, context is silently dropped (the historical\r\n   * behavior). When `true`, contexts are pretty-printed with `util.inspect`\r\n   * — colored, depth-limited, ideal for development. Persistent channels\r\n   * (`FileLog`, `JSONFileLog`) always retain context regardless of this flag.\r\n   *\r\n   * @default false\r\n   */\r\n  showContext?: boolean;\r\n  /**\r\n   * Depth passed to `util.inspect` when rendering context. Only applies when\r\n   * `showContext` is enabled.\r\n   *\r\n   * @default 4\r\n   */\r\n  contextDepth?: number;\r\n};\r\n\r\n/**\r\n * The longest level name (`success`) sets the tag column width. Padding every\r\n * level name to this width keeps the timestamp / module / action columns\r\n * aligned across lines. The level icons are bare (text-style, single-cell)\r\n * glyphs, so padding the name alone produces true columns.\r\n */\r\nconst LEVEL_NAME_WIDTH = 7;\r\n\r\n/**\r\n * Per-level console presentation: the colored, fixed-width `{icon} {name}` tag\r\n * and the function that colors the message body.\r\n */\r\ntype LevelStyle = {\r\n  tag: string;\r\n  message: (message: LoggingData[\"message\"]) => string;\r\n};\r\n\r\n/**\r\n * Build a single-color, fixed-width tag — `{icon} {name}` with the name padded\r\n * so every tag spans the same number of columns.\r\n */\r\nfunction buildTag(\r\n  icon: string,\r\n  name: string,\r\n  color: (text: string) => string,\r\n): string {\r\n  return color(`${icon} ${name.padEnd(LEVEL_NAME_WIDTH)}`);\r\n}\r\n\r\n/**\r\n * Console styling per log level. The `fatal` tag is a bright-red background\r\n * badge — the same column width as the others (`\" ☠ fatal \"` is 9 cells, like\r\n * `{icon} {name.padEnd(7)}`), but impossible to miss in a wall of red `error`\r\n * lines, where a plain red tag would blend in.\r\n */\r\nconst LEVEL_STYLES: Record<LogLevel, LevelStyle> = {\r\n  debug: {\r\n    tag: buildTag(\"⚙\", \"debug\", colors.magentaBright),\r\n    message: colors.magentaBright,\r\n  },\r\n  info: {\r\n    tag: buildTag(\"ℹ\", \"info\", colors.blueBright),\r\n    message: colors.blueBright,\r\n  },\r\n  warn: {\r\n    tag: buildTag(\"⚠\", \"warn\", colors.yellow),\r\n    message: colors.yellowBright,\r\n  },\r\n  error: {\r\n    tag: buildTag(\"✗\", \"error\", colors.red),\r\n    message: colors.redBright,\r\n  },\r\n  success: {\r\n    tag: buildTag(\"✓\", \"success\", colors.green),\r\n    message: colors.greenBright,\r\n  },\r\n  fatal: {\r\n    tag: colors.bgRedBright(colors.whiteBright(colors.bold(\" ☠ fatal \"))),\r\n    message: colors.redBright.bold,\r\n  },\r\n};\r\n\r\n/**\r\n * Fallback for an unrecognized level — a plain `[log]` tag padded to the same\r\n * width so the columns stay aligned.\r\n */\r\nconst DEFAULT_STYLE: LevelStyle = {\r\n  tag: \"[log]\".padEnd(LEVEL_NAME_WIDTH + 2),\r\n  message: message => message as string,\r\n};\r\n\r\nexport class ConsoleLog extends LogChannel<ConsoleLogConfig> {\r\n  /**\r\n   * {@inheritdoc}\r\n   */\r\n  public name = \"console\";\r\n\r\n  /**\r\n   * Determine if channel is logging in terminal\r\n   */\r\n  public terminal = true;\r\n\r\n  /**\r\n   * {@inheritdoc}\r\n   */\r\n  public log(data: LoggingData) {\r\n    const { module, action, message, type: level } = data;\r\n\r\n    if (!this.shouldBeLogged(data)) return;\r\n\r\n    // Console shows time-only (HH:mm:ss.SSS) — within a dev session the date\r\n    // rarely changes, so the full ISO date + `T`/`Z` are just noise. Persistent\r\n    // channels (FileLog / JSONFileLog) keep the full ISO timestamp.\r\n    const time = new Date().toISOString().slice(11, 23); // i.e. \"10:22:00.000\"\r\n\r\n    const style = LEVEL_STYLES[level] ?? DEFAULT_STYLE;\r\n\r\n    // The slate timestamp recedes so the colored level + message lead the eye;\r\n    // module (cyan) and action (magenta) stay colored for subsystem scanning.\r\n    // `slate` (256-color neutral gray) reads cleaner than bright-black `gray`,\r\n    // which sits too close to the background on most terminal themes.\r\n    console.log(\r\n      style.tag,\r\n      colors.slate(`(${time})`),\r\n      colors.cyan(`[${module}]`),\r\n      colors.magenta(`[${action}]`),\r\n      style.message(message),\r\n    );\r\n\r\n    if (typeof message === \"object\") {\r\n      console.log(message);\r\n    }\r\n\r\n    // Render context on a second line when explicitly enabled. We only\r\n    // attempt rendering if there's anything meaningful to show — empty\r\n    // objects clutter the terminal without adding signal.\r\n    if (this.config(\"showContext\") && data.context && Object.keys(data.context).length > 0) {\r\n      const depth = this.config(\"contextDepth\") ?? 4;\r\n      console.log(\r\n        colors.slate(\"  ↳\"),\r\n        inspect(data.context, { colors: true, depth, breakLength: 80 }),\r\n      );\r\n    }\r\n  }\r\n}\r\n"],"mappings":";;;;;;;;;;;AA+BA,MAAM,mBAAmB;;;;;AAezB,SAAS,SACP,MACA,MACA,OACQ;CACR,OAAO,MAAM,GAAG,KAAK,GAAG,KAAK,OAAO,gBAAgB,GAAG;AACzD;;;;;;;AAQA,MAAM,eAA6C;CACjD,OAAO;EACL,KAAK,SAAS,KAAK,SAAS,OAAO,aAAa;EAChD,SAAS,OAAO;CAClB;CACA,MAAM;EACJ,KAAK,SAAS,KAAK,QAAQ,OAAO,UAAU;EAC5C,SAAS,OAAO;CAClB;CACA,MAAM;EACJ,KAAK,SAAS,KAAK,QAAQ,OAAO,MAAM;EACxC,SAAS,OAAO;CAClB;CACA,OAAO;EACL,KAAK,SAAS,KAAK,SAAS,OAAO,GAAG;EACtC,SAAS,OAAO;CAClB;CACA,SAAS;EACP,KAAK,SAAS,KAAK,WAAW,OAAO,KAAK;EAC1C,SAAS,OAAO;CAClB;CACA,OAAO;EACL,KAAK,OAAO,YAAY,OAAO,YAAY,OAAO,KAAK,WAAW,CAAC,CAAC;EACpE,SAAS,OAAO,UAAU;CAC5B;AACF;;;;;AAMA,MAAM,gBAA4B;CAChC,KAAK,QAAQ,OAAO,CAAoB;CACxC,UAAS,YAAW;AACtB;AAEA,IAAa,aAAb,cAAgC,WAA6B;;;cAI7C;kBAKI;;;;;CAKlB,AAAO,IAAI,MAAmB;EAC5B,MAAM,EAAE,QAAQ,QAAQ,SAAS,MAAM,UAAU;EAEjD,IAAI,CAAC,KAAK,eAAe,IAAI,GAAG;EAKhC,MAAM,wBAAO,IAAI,KAAK,EAAC,CAAC,YAAY,CAAC,CAAC,MAAM,IAAI,EAAE;EAElD,MAAM,QAAQ,aAAa,UAAU;EAMrC,QAAQ,IACN,MAAM,KACN,OAAO,MAAM,IAAI,KAAK,EAAE,GACxB,OAAO,KAAK,IAAI,OAAO,EAAE,GACzB,OAAO,QAAQ,IAAI,OAAO,EAAE,GAC5B,MAAM,QAAQ,OAAO,CACvB;EAEA,IAAI,OAAO,YAAY,UACrB,QAAQ,IAAI,OAAO;EAMrB,IAAI,KAAK,OAAO,aAAa,KAAK,KAAK,WAAW,OAAO,KAAK,KAAK,OAAO,CAAC,CAAC,SAAS,GAAG;GACtF,MAAM,QAAQ,KAAK,OAAO,cAAc,KAAK;GAC7C,QAAQ,IACN,OAAO,MAAM,KAAK,GAClB,QAAQ,KAAK,SAAS;IAAE,QAAQ;IAAM;IAAO,aAAa;GAAG,CAAC,CAChE;EACF;CACF;AACF"}