{"version":3,"file":"logger-72hM4JWZ.mjs","names":[],"sources":["../../shared/src/color.ts","../src/cli/shared/ascii-table.ts","../src/cli/shared/parse-boolean.ts","../src/cli/shared/logger.ts"],"sourcesContent":["import { stripVTControlCharacters, styleText } from \"node:util\";\n\n/** Applies a style to text */\nexport type StyleFn = (text: string) => string;\n\ntype StyleName = Exclude<Parameters<typeof styleText>[0], readonly unknown[] | unknown[]>;\n\nconst style =\n  (name: StyleName): StyleFn =>\n  (text) =>\n    styleText(name, text, { validateStream: false });\n\n/**\n * Style functions by name, so call sites read `color.bold(text)`. Styling is\n * always applied; `renderFor` drops it again when the destination stream has no\n * color support. Add a name here when a package needs one that is not listed.\n */\nexport const color = {\n  bold: style(\"bold\"),\n  dim: style(\"dim\"),\n  italic: style(\"italic\"),\n  gray: style(\"gray\"),\n  white: style(\"white\"),\n  red: style(\"red\"),\n  green: style(\"green\"),\n  yellow: style(\"yellow\"),\n  cyan: style(\"cyan\"),\n  magenta: style(\"magenta\"),\n  redBright: style(\"redBright\"),\n  greenBright: style(\"greenBright\"),\n  cyanBright: style(\"cyanBright\"),\n};\n\n// Node's rules for whether a destination gets colors, applied by hand. Asking\n// styleText instead would be shorter but only correct on Node: Bun ignores both\n// the stream option and NO_COLOR (reproduced on 1.3.14), so it reports every\n// destination as color-capable and escapes end up in redirected output.\n//\n// FORCE_COLOR decides on its own when set, which is how CI keeps colors through\n// a pipe. NO_COLOR counts as set at any non-empty value, \"0\" included.\nconst supportsColor = (stream: NodeJS.WriteStream): boolean => {\n  const forced = process.env.FORCE_COLOR;\n  if (forced !== undefined) return forced !== \"0\" && forced !== \"false\";\n  if (process.env.NODE_DISABLE_COLORS !== undefined) return false;\n  if ((process.env.NO_COLOR ?? \"\") !== \"\") return false;\n  if (process.env.TERM === \"dumb\") return false;\n  return stream.isTTY === true;\n};\n\n/**\n * Prepares styled text for the stream it is written to.\n * @param stream - Stream the text is written to\n * @param text - Styled text\n * @returns Text with styling removed when the stream has no color support\n */\nexport function renderFor(stream: NodeJS.WriteStream, text: string): string {\n  return supportsColor(stream) ? text : stripVTControlCharacters(text);\n}\n","import { eastAsianWidth } from \"get-east-asian-width\";\n\n// eslint-disable-next-line no-control-regex\nconst ANSI_ESCAPE_PATTERN = /\\x1b\\[[0-9;]*m/g;\nconst CARRIAGE_RETURN_PATTERN = /\\r\\n?/g;\n\nconst graphemeSegmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n\nexport interface AsciiTableConfig {\n  /** Suppress horizontal lines between rows, keeping only the outer border. */\n  singleLine?: boolean;\n  /** Decide whether to draw the horizontal line at `lineIndex` (range `[0, rowCount]` inclusive). */\n  drawHorizontalLine?: (lineIndex: number, rowCount: number) => boolean;\n}\n\ninterface CellLine {\n  text: string;\n  width: number;\n}\n\nfunction maxOf(values: number[], fallback = 0): number {\n  return values.reduce((max, value) => (value > max ? value : max), fallback);\n}\n\nconst TAB_WIDTH = 8;\n\nfunction isStrippableControlCharacter(char: string): boolean {\n  const codePoint = char.codePointAt(0) ?? 0;\n  if (char === \"\\n\") {\n    return false;\n  }\n  return codePoint <= 0x1f || codePoint === 0x7f;\n}\n\n// Only SGR (color/style) escape sequences are meant to survive; a bare ESC\n// that isn't part of a recognized SGR sequence (e.g. a screen-clear CSI\n// sequence, or a BEL-terminated OSC sequence) is treated like any other\n// control character below and stripped, rather than passed through to the\n// terminal or left with its terminator removed.\nfunction normalizeControlCharacters(value: string): string {\n  const sgrSequences = value.match(ANSI_ESCAPE_PATTERN) ?? [];\n  return value\n    .split(ANSI_ESCAPE_PATTERN)\n    .map((segment) => {\n      const chars: string[] = [];\n      for (const char of segment) {\n        if (char === \"\\t\") {\n          chars.push(\" \".repeat(TAB_WIDTH));\n        } else if (!isStrippableControlCharacter(char)) {\n          chars.push(char);\n        }\n      }\n      return chars.join(\"\");\n    })\n    .reduce((result, segment, i) => result + segment + (sgrSequences[i] ?? \"\"), \"\");\n}\n\nfunction sanitizeCell(cell: unknown): string {\n  return normalizeControlCharacters(String(cell ?? \"\").replace(CARRIAGE_RETURN_PATTERN, \"\\n\"));\n}\n\n// Clusters made up entirely of non-printing code points (lone joiners,\n// variation selectors, combining marks, etc.) render with no visible glyph.\nconst ZERO_WIDTH_CLUSTER_PATTERN =\n  /^(?:\\p{Default_Ignorable_Code_Point}|\\p{Control}|\\p{Format}|\\p{Nonspacing_Mark}|\\p{Enclosing_Mark}|\\p{Surrogate})+$/v;\n// RGI_Emoji covers flags, keycaps, and VS16-forced presentation sequences,\n// which render as 2 columns in terminals even though their first code point\n// alone would measure as narrow/neutral.\nconst RGI_EMOJI_PATTERN = /^\\p{RGI_Emoji}$/v;\n\nfunction displayWidth(value: string): number {\n  let width = 0;\n  for (const { segment } of graphemeSegmenter.segment(value.replace(ANSI_ESCAPE_PATTERN, \"\"))) {\n    if (ZERO_WIDTH_CLUSTER_PATTERN.test(segment)) {\n      continue;\n    }\n    if (RGI_EMOJI_PATTERN.test(segment)) {\n      width += 2;\n      continue;\n    }\n    const codePoint = segment.codePointAt(0);\n    width += codePoint === undefined ? 0 : eastAsianWidth(codePoint);\n  }\n  return width;\n}\n\nfunction toCellLines(cell: string): CellLine[] {\n  return cell.split(\"\\n\").map((text) => ({ text, width: displayWidth(text) }));\n}\n\nfunction padCell(cellLine: CellLine, width: number): string {\n  return cellLine.text + \" \".repeat(Math.max(0, width - cellLine.width));\n}\n\nfunction renderBorder(left: string, join: string, right: string, columnWidths: number[]): string {\n  return left + columnWidths.map((width) => \"─\".repeat(width + 2)).join(join) + right;\n}\n\nfunction validateConsistentColumnCount(rows: string[][]): void {\n  const columnCount = rows[0]?.length;\n  if (columnCount === undefined) {\n    return;\n  }\n  rows.forEach((row, index) => {\n    if (row.length !== columnCount) {\n      throw new Error(\n        `renderTable: all rows must have the same number of columns (expected ${columnCount}, row ${index} has ${row.length}).`,\n      );\n    }\n  });\n}\n\n/**\n * Renders a 2D array of values as a table using single-line Unicode box-drawing borders.\n * Column widths account for East Asian wide characters (measured per grapheme cluster,\n * so combining marks and ZWJ emoji sequences aren't overcounted, non-printing clusters\n * such as a lone joiner or combining mark measure as 0, and flags, keycaps, and\n * VS16-forced emoji presentation are measured as 2 columns) and strip ANSI SGR (color/style)\n * escape codes before measuring. Use this instead of importing a table-rendering package\n * directly.\n * @param data - Table rows; every row must have the same number of columns. Each cell is\n * stringified (`null`/`undefined` become an empty string rather than the literal text\n * \"null\"/\"undefined\"), may contain embedded newlines, has `\\r`/`\\r\\n` normalized to `\\n`,\n * has tabs expanded to spaces, and has other control characters stripped.\n * @param config - Rendering options\n * @returns The rendered table terminated with a trailing newline, or `\"\"` when there are no\n * rows or no columns to display\n */\nexport function renderTable(data: unknown[][], config: AsciiTableConfig = {}): string {\n  const rows = data.map((row) => row.map(sanitizeCell));\n  validateConsistentColumnCount(rows);\n\n  const rowCount = rows.length;\n  const columnCount = rows[0]?.length ?? 0;\n  if (rowCount === 0 || columnCount === 0) {\n    return \"\";\n  }\n\n  const rowsCellLines = rows.map((row) =>\n    Array.from({ length: columnCount }, (_, col) => toCellLines(row[col] ?? \"\")),\n  );\n  const columnWidths = Array.from({ length: columnCount }, (_, col) =>\n    maxOf(rowsCellLines.map((row) => maxOf((row[col] ?? []).map((line) => line.width)))),\n  );\n\n  const shouldDrawLine = (lineIndex: number): boolean =>\n    config.singleLine\n      ? lineIndex === 0 || lineIndex === rowCount\n      : (config.drawHorizontalLine ?? (() => true))(lineIndex, rowCount);\n\n  const lines: string[] = [];\n  if (shouldDrawLine(0)) {\n    lines.push(renderBorder(\"┌\", \"┬\", \"┐\", columnWidths));\n  }\n\n  rowsCellLines.forEach((cellLines, rowIndex) => {\n    const rowHeight = maxOf(\n      cellLines.map((columnLines) => columnLines.length),\n      1,\n    );\n    for (let line = 0; line < rowHeight; line++) {\n      const cells = cellLines.map((columnLines, col) =>\n        padCell(columnLines[line] ?? { text: \"\", width: 0 }, columnWidths[col] ?? 0),\n      );\n      lines.push(`│ ${cells.join(\" │ \")} │`);\n    }\n    if (rowIndex < rowCount - 1 && shouldDrawLine(rowIndex + 1)) {\n      lines.push(renderBorder(\"├\", \"┼\", \"┤\", columnWidths));\n    }\n  });\n\n  if (shouldDrawLine(rowCount)) {\n    lines.push(renderBorder(\"└\", \"┴\", \"┘\", columnWidths));\n  }\n\n  return `${lines.join(\"\\n\")}\\n`;\n}\n","const TRUTHY_VALUES = new Set([\"true\", \"t\", \"yes\", \"y\", \"on\", \"1\"]);\nconst FALSY_VALUES = new Set([\"false\", \"f\", \"no\", \"n\", \"off\", \"0\"]);\n\n/**\n * Parse a string value as a boolean.\n *\n * Recognized values (case-insensitive, trimmed) follow Python's\n * `distutils.util.strtobool` convention:\n * - truthy: `true, t, yes, y, on, 1`\n * - falsy: `false, f, no, n, off, 0`\n *\n * Undefined, empty strings, and unrecognized values return `undefined` so\n * that callers can fall back to their own defaults.\n * @param value - The input string (e.g. an environment variable or CLI flag value)\n * @returns `true`, `false`, or `undefined` when the value is unset or unrecognized\n */\nexport function parseBoolean(value: string | undefined): boolean | undefined {\n  if (value === undefined) return undefined;\n  const normalized = value.trim().toLowerCase();\n  if (normalized === \"\") return undefined;\n  if (TRUTHY_VALUES.has(normalized)) return true;\n  if (FALSY_VALUES.has(normalized)) return false;\n  return undefined;\n}\n","import { formatWithOptions, type InspectOptions } from \"node:util\";\nimport { color, renderFor } from \"@tailor-platform/shared/color\";\nimport { formatDistanceToNowStrict } from \"date-fns\";\nimport { renderTable } from \"./ascii-table\";\nimport { parseBoolean } from \"./parse-boolean\";\n\n/**\n * Error thrown when a prompt is attempted in a non-interactive environment\n */\nexport class CIPromptError extends Error {\n  constructor(message?: string) {\n    super(\n      message ??\n        \"Interactive prompts are not available in this environment. Provide the required options explicitly.\",\n    );\n    this.name = \"CIPromptError\";\n  }\n}\n\n/**\n * Semantic style functions for inline text styling\n */\nexport const styles = {\n  // Status colors\n  success: color.green,\n  error: color.red,\n  warning: color.yellow,\n  info: color.cyan,\n\n  // Action colors (for change sets)\n  create: color.green,\n  update: color.yellow,\n  delete: color.red,\n  replace: color.magenta,\n  unchanged: color.gray,\n\n  // Emphasis\n  bold: color.bold,\n  dim: color.gray,\n  highlight: color.cyanBright,\n  successBright: color.greenBright,\n  errorBright: color.redBright,\n\n  // Resource types\n  resourceType: color.bold,\n  resourceName: color.cyan,\n\n  // File paths\n  path: color.cyan,\n\n  // Values\n  value: color.white,\n  placeholder: (text: string) => color.italic(color.gray(text)),\n};\n\n/**\n * Standardized symbols for CLI output\n */\nexport const symbols = {\n  success: styles.success(\"\\u2713\"),\n  error: styles.error(\"\\u2716\"),\n  warning: styles.warning(\"\\u26a0\"),\n  info: styles.info(\"i\"),\n  create: styles.create(\"+\"),\n  update: styles.update(\"~\"),\n  delete: styles.delete(\"-\"),\n  replace: styles.replace(\"\\u00b1\"),\n  bullet: styles.dim(\"\\u2022\"),\n  arrow: styles.dim(\"\\u2192\"),\n};\n\n/**\n * Log output modes\n */\nexport type LogMode = \"default\" | \"stream\" | \"plain\";\n\nexport interface LogOptions {\n  /** Output mode (default: \"default\") */\n  mode?: LogMode;\n  /** Number of spaces to indent the entire line (default: 0) */\n  indent?: number;\n}\n\n/** Field transformer function. null excludes the field from table output. */\nexport type FieldTransformer = ((value: unknown, item: object) => string) | null;\n\nexport interface OutOptions {\n  /** Table display field transform/exclude settings. Only applied in table mode (not JSON). */\n  display?: Record<string, FieldTransformer>;\n\n  /** Show null values in table output (default: false) */\n  showNull?: boolean;\n}\n\n// In JSON mode, all logs go to stderr to keep stdout clean for JSON data\nlet _jsonMode = false;\nlet _verbose = false;\n\n// Values registered via `logger.registerSecret()`, redacted from diagnostic log output\nconst _secrets = new Set<string>();\nconst REDACTED_PLACEHOLDER = \"<redacted>\";\n// Below this length, a registered value is too likely to match unrelated text.\nconst MIN_SECRET_LENGTH = 4;\n\n/**\n * Aho-Corasick trie node. Indexed by individual UTF-16 code units (not Unicode code\n * points), matching how `string.indexOf`/`.slice` already index this file's strings — a\n * surrogate-pair character occupies two nodes, same as it occupies two `string` indices.\n */\ninterface TrieNode {\n  children: Map<string, TrieNode>;\n  fail: TrieNode;\n  /** Secrets ending at this node, including those reached via `fail` links (precomputed). */\n  outputs: string[];\n}\n\n/**\n * Builds a multi-pattern matcher for every registered secret, so `findSecretSpans` below\n * can find all of their occurrences in one pass over the text (`O(text.length + matches)`)\n * instead of scanning the full text once per registered secret. Rebuilt only when\n * `registerSecret` adds a genuinely new value (see `_automaton` below), so its\n * `O(total secret length)` construction cost is amortized across every log line redacted\n * while the secret set doesn't change.\n * @param secrets - Currently registered secrets\n * @returns Root of the built trie\n */\nfunction buildAutomaton(secrets: ReadonlySet<string>): TrieNode {\n  const root: TrieNode = {\n    children: new Map(),\n    fail: undefined as unknown as TrieNode,\n    outputs: [],\n  };\n  root.fail = root;\n\n  for (const secret of secrets) {\n    let node = root;\n    for (let i = 0; i < secret.length; i++) {\n      const ch = secret[i] as string;\n      let next = node.children.get(ch);\n      if (!next) {\n        next = { children: new Map(), fail: root, outputs: [] };\n        node.children.set(ch, next);\n      }\n      node = next;\n    }\n    node.outputs.push(secret);\n  }\n\n  // A head index instead of Array#shift(): shift() re-indexes every remaining element on\n  // each call, which would make this loop quadratic in the number of trie nodes rather than\n  // the linear BFS this is meant to be.\n  const queue: TrieNode[] = [...root.children.values()];\n  for (let head = 0; head < queue.length; head++) {\n    const parent = queue[head] as TrieNode;\n    for (const [ch, child] of parent.children) {\n      let fail = parent.fail;\n      while (fail !== root && !fail.children.has(ch)) fail = fail.fail;\n      child.fail = fail.children.get(ch) ?? root;\n      child.outputs = child.outputs.concat(child.fail.outputs);\n      queue.push(child);\n    }\n  }\n  return root;\n}\n\n// Cached automaton for the current `_secrets` contents; `null` means rebuild on next use.\n// Invalidated only when `registerSecret` actually grows `_secrets` (Set#add on an existing\n// value is a no-op), so re-registering an already-known secret never triggers a rebuild.\nlet _automaton: TrieNode | null = null;\n\nfunction getAutomaton(): TrieNode {\n  _automaton ??= buildAutomaton(_secrets);\n  return _automaton;\n}\n\n/**\n * Finds every occurrence of every registered secret in `text`, including overlapping ones,\n * in a single pass over `text` via the Aho-Corasick automaton.\n * @param text - Text to search\n * @returns Match spans as `[start, end)` pairs, in the order found\n */\nfunction findSecretSpans(text: string): Array<[start: number, end: number]> {\n  const spans: Array<[start: number, end: number]> = [];\n  const root = getAutomaton();\n  let node = root;\n  for (let i = 0; i < text.length; i++) {\n    const ch = text[i] as string;\n    while (node !== root && !node.children.has(ch)) node = node.fail;\n    node = node.children.get(ch) ?? root;\n    for (const secret of node.outputs) {\n      spans.push([i + 1 - secret.length, i + 1]);\n    }\n  }\n  return spans;\n}\n\n/**\n * Redacts every registered secret from `text` in a single pass over the original text.\n *\n * Matches are found against the original text only - never against text a previous\n * replacement produced - and overlapping/adjacent matches (whether one secret contains\n * another, or two secrets merely cross, e.g. registering \"abcde\" and \"defghi\" against\n * \"abcdefghi\") are merged into one contiguous span before any substitution happens. This\n * avoids two failure modes an iterative \"replace one secret, then the next\" approach has:\n * a later secret re-matching inside a placeholder a previous replacement already inserted,\n * and a crossing (non-nested) overlap leaving a fragment of one secret unredacted.\n *\n * Idempotent: a match that falls inside an occurrence of `<redacted>` already present in\n * `text` is discarded rather than substituted again. Without this, calling this function\n * twice on the same text (which happens whenever something already redacted, such as a\n * `--json` error envelope, is later passed to a diagnostic log call) could corrupt the\n * placeholder itself if a registered secret happens to be one of its substrings (e.g. a\n * secret literally containing \"redact\").\n * @param text - Text to redact\n * @returns `text` with every registered secret occurrence replaced by `<redacted>`\n */\nexport function redactSecrets(text: string): string {\n  if (_secrets.size === 0) return text;\n\n  const protectedSpans: Array<[start: number, end: number]> = [];\n  for (let from = 0, index: number; (index = text.indexOf(REDACTED_PLACEHOLDER, from)) !== -1;) {\n    protectedSpans.push([index, index + REDACTED_PLACEHOLDER.length]);\n    from = index + REDACTED_PLACEHOLDER.length;\n  }\n\n  // Only a match wholly inside a protected placeholder is discarded (it can only be the\n  // placeholder's own text, e.g. a registered secret that is a substring of \"redacted\").\n  // A match that merely overlaps one — extending outside it, e.g. a registered secret that\n  // happens to be \"leak<redacted>\" — still has real secret content outside the placeholder\n  // and must still be replaced.\n  //\n  // A registered secret wholly contained in the placeholder (up to and including a secret\n  // equal to \"<redacted>\" itself) is indistinguishable from the placeholder in rendered\n  // output either way: substituting REDACTED_PLACEHOLDER for text that already reads\n  // REDACTED_PLACEHOLDER is a no-op. Discarding the match here (rather than \"fixing\" it to\n  // substitute anyway) isn't a redaction gap — it just skips redundant work on text that's\n  // already the safe, masked form.\n  const spans = findSecretSpans(text).filter(\n    ([start, end]) => !protectedSpans.some(([pStart, pEnd]) => start >= pStart && end <= pEnd),\n  );\n  if (spans.length === 0) return text;\n  spans.sort(([a], [b]) => a - b);\n\n  const merged: Array<[start: number, end: number]> = [];\n  for (const span of spans) {\n    const last = merged.at(-1);\n    if (last && span[0] <= last[1]) {\n      last[1] = Math.max(last[1], span[1]);\n    } else {\n      merged.push(span);\n    }\n  }\n\n  let result = \"\";\n  let cursor = 0;\n  for (const [start, end] of merged) {\n    result += text.slice(cursor, start) + REDACTED_PLACEHOLDER;\n    cursor = end;\n  }\n  return result + text.slice(cursor);\n}\n\n/**\n * Reset the registered-secret redaction state. Used for testing.\n *\n * `_secrets` is process-lifetime, module-level state with no production unregister API\n * (a real process should never stop hiding a secret it once saw). Test files that call\n * `logger.registerSecret()` and run in a Vitest project with `isolate: false` share this\n * state across files, so a value registered in one file's test can still be redacted in an\n * unrelated later file's assertions unless cleared between tests.\n */\nexport function resetSecretRegistry(): void {\n  _secrets.clear();\n  _automaton = null;\n}\n\n// Type icons for log output\nconst TYPE_ICONS: Record<string, string> = {\n  info: \"ℹ\",\n  success: \"✔\",\n  warn: \"⚠\",\n  error: \"✖\",\n  debug: \"⚙\",\n  trace: \"→\",\n  log: \"\",\n};\n\n// Color functions for icon and message text\nconst TYPE_COLORS: Record<string, (text: string) => string> = {\n  info: styles.info,\n  success: styles.success,\n  warn: styles.warning,\n  error: styles.error,\n  debug: styles.dim,\n  trace: styles.dim,\n  log: (text) => text,\n};\n\ninterface FormatLogLineOptions {\n  mode: string;\n  indent: number;\n  type: string;\n  message: string;\n  timestamp?: string;\n}\n\n/**\n * Formats a log line with the appropriate prefix and indentation\n * @param opts - Formatting options\n * @returns Formatted log line\n */\nexport function formatLogLine(opts: FormatLogLineOptions): string {\n  const { mode, indent, type, message, timestamp } = opts;\n  const indentPrefix = indent > 0 ? \" \".repeat(indent) : \"\";\n  const colorFn = TYPE_COLORS[type] || ((text: string) => text);\n\n  // Plain mode: color only, no icon, no timestamp\n  if (mode === \"plain\") {\n    return `${indentPrefix}${colorFn(message)}\\n`;\n  }\n\n  // Default/Stream mode: with icon and color\n  const icon = TYPE_ICONS[type] || \"\";\n  const prefix = icon ? `${icon} ` : \"\";\n  const coloredOutput = colorFn(`${prefix}${message}`);\n  const timestampPrefix = timestamp ?? \"\";\n\n  return `${indentPrefix}${timestampPrefix}${coloredOutput}\\n`;\n}\n\n/**\n * Writes a formatted log line to stderr.\n * @param type - Log type (info, success, warn, error, log)\n * @param message - Log message\n * @param opts - Log options (mode and indent)\n */\nfunction writeLog(type: string, message: string, opts?: LogOptions): void {\n  const mode = opts?.mode ?? \"default\";\n  const indent = opts?.indent ?? 0;\n  const inspectOpts: InspectOptions = {\n    breakLength: process.stdout.columns || 80,\n  };\n  const formattedMessage = formatWithOptions(inspectOpts, message);\n  const timestamp = mode === \"stream\" ? `${new Date().toLocaleTimeString()} ` : \"\";\n  const output = formatLogLine({ mode, indent, type, message: formattedMessage, timestamp });\n  process.stderr.write(renderFor(process.stderr, redactSecrets(output)));\n}\n\n/**\n * The CLI logger. Diagnostics go to stderr; `out()` writes primary output to\n * stdout as a table, or as JSON when `jsonMode` is on. `--json` and\n * `--verbose` feed the `jsonMode` / `verbose` state, which CLI plugins share\n * with the SDK code paths they call.\n */\nexport const logger = {\n  get jsonMode(): boolean {\n    return _jsonMode;\n  },\n  set jsonMode(value: boolean) {\n    _jsonMode = value;\n  },\n\n  get verbose(): boolean {\n    return _verbose || parseBoolean(process.env.DEBUG) === true || process.env.RUNNER_DEBUG === \"1\";\n  },\n  set verbose(value: boolean) {\n    _verbose = value;\n  },\n\n  info(message: string, opts?: LogOptions): void {\n    writeLog(\"info\", message, opts);\n  },\n\n  success(message: string, opts?: LogOptions): void {\n    writeLog(\"success\", message, opts);\n  },\n\n  warn(message: string, opts?: LogOptions): void {\n    writeLog(\"warn\", message, opts);\n  },\n\n  error(message: string, opts?: LogOptions): void {\n    writeLog(\"error\", message, opts);\n  },\n\n  log(message: string): void {\n    writeLog(\"log\", message, { mode: \"plain\" });\n  },\n\n  newline(): void {\n    process.stderr.write(\"\\n\");\n  },\n\n  debug(message: string): void {\n    if (logger.verbose) {\n      writeLog(\"log\", styles.dim(message), { mode: \"plain\" });\n    }\n  },\n\n  /**\n   * Registers a value to be redacted from diagnostic log output (`info`/`success`/`warn`/\n   * `error`/`log`/`debug`). Any occurrence of `value` — or of its JSON-string-escaped form\n   * (so a value embedded in `JSON.stringify`d output, e.g. `--json` mode error envelopes, is\n   * also caught) or its `application/x-www-form-urlencoded` form (so a value that reached the\n   * process via a URL query string, e.g. an OAuth authorization code decoded from a callback\n   * URL via `URLSearchParams`, is still caught if that same URL — still encoded — is later\n   * echoed into a diagnostic message) — is replaced with `<redacted>` before it reaches\n   * stderr. Does not affect `out()`, since some commands intentionally print secret values as\n   * their primary result.\n   *\n   * Values shorter than 4 characters are ignored, since they are too likely to match\n   * unrelated text. A non-string value (e.g. `undefined` from an unvalidated external\n   * payload cast to a typed shape) is ignored the same way, rather than throwing, since a\n   * logging call must never be what crashes the process.\n   * @param value - The secret value to redact from future log output\n   */\n  registerSecret(value: string): void {\n    // Counts Unicode code points, not UTF-16 code units, so a value made of surrogate-pair\n    // characters (e.g. emoji) isn't undercounted as longer than it actually is.\n    if (typeof value !== \"string\" || [...value].length < MIN_SECRET_LENGTH) return;\n    const sizeBefore = _secrets.size;\n    _secrets.add(value);\n    const jsonEscaped = JSON.stringify(value).slice(1, -1);\n    if (jsonEscaped !== value) _secrets.add(jsonEscaped);\n    // Uses URLSearchParams rather than encodeURIComponent: form-urlencoding (what\n    // URLSearchParams produces, and what a URL query string actually contains) encodes a\n    // space as \"+\", not \"%20\", and unlike encodeURIComponent it never throws on a lone\n    // surrogate (invalid UTF-16) — it substitutes U+FFFD instead, matching how the URL\n    // itself would already have encoded that same malformed input.\n    const formEncoded = new URLSearchParams([[\"v\", value]]).toString().slice(2);\n    if (formEncoded !== value) _secrets.add(formEncoded);\n    // Set#add on an already-registered value is a no-op, so this only invalidates the\n    // cached automaton (see findSecretSpans) when a genuinely new secret was added.\n    if (_secrets.size !== sizeBefore) _automaton = null;\n  },\n\n  out(data: string | object | object[], options?: OutOptions): void {\n    if (typeof data === \"string\") {\n      process.stdout.write(renderFor(process.stdout, data.endsWith(\"\\n\") ? data : data + \"\\n\"));\n      return;\n    }\n\n    if (this.jsonMode) {\n      // eslint-disable-next-line no-restricted-syntax\n      console.log(JSON.stringify(data));\n      return;\n    }\n\n    const display = options?.display;\n\n    // Helper to format a value for table display\n    const formatValue = (value: unknown, pretty = false): string => {\n      if (options?.showNull && value === null) return \"NULL\";\n      if (value === null || value === undefined) return \"N/A\";\n      if (value instanceof Date) {\n        return formatDistanceToNowStrict(value, { addSuffix: true });\n      }\n      if (typeof value === \"object\") {\n        return pretty ? JSON.stringify(value, null, 2) : JSON.stringify(value);\n      }\n      return String(value);\n    };\n\n    // Helper to check if field should be excluded\n    const isExcluded = (key: string): boolean => {\n      return display !== undefined && key in display && display[key] === null;\n    };\n\n    // Helper to apply transformer or default formatting\n    const transformValue = (key: string, value: unknown, item: object, pretty = false): string => {\n      if (display && key in display) {\n        const transformer = display[key];\n        if (transformer) {\n          return transformer(value, item);\n        }\n      }\n      return formatValue(value, pretty);\n    };\n\n    if (!Array.isArray(data)) {\n      const entries = Object.entries(data).filter(([key]) => !isExcluded(key));\n      const formattedEntries = entries.map(([key, value]) => [\n        key,\n        transformValue(key, value, data, true),\n      ]);\n      const t = renderTable(formattedEntries, { singleLine: false });\n      process.stdout.write(renderFor(process.stdout, t));\n      return;\n    }\n\n    if (data.length === 0) {\n      return;\n    }\n\n    const allHeaders = Array.from(new Set(data.flatMap((item) => Object.keys(item))));\n    const headers = allHeaders.filter((h) => !isExcluded(h));\n    if (headers.length === 0) {\n      return;\n    }\n    const rows = data.map((item) =>\n      headers.map((header) =>\n        transformValue(header, (item as Record<string, unknown>)[header], item),\n      ),\n    );\n\n    const t = renderTable([headers, ...rows], {\n      drawHorizontalLine: (lineIndex, rowCount) => {\n        return lineIndex === 0 || lineIndex === 1 || lineIndex === rowCount;\n      },\n    });\n    process.stdout.write(renderFor(process.stdout, t));\n  },\n};\n"],"mappings":"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"}