{"version":3,"sources":["../src/cli/utils/formatting.ts"],"sourcesContent":["import chalk from \"chalk\";\n\n/**\n * Strips ANSI escape codes from a string for accurate length calculation.\n */\nexport const stripAnsi = (str: string): string => {\n  // eslint-disable-next-line no-control-regex\n  return str.replace(/\\u001b\\[[0-9;]*m/g, \"\");\n};\n\nexport type ColumnColorMap = Record<string, (value: string) => string>;\n\n/**\n * Prints a formatted table to stdout with column-aligned headers, separator,\n * and optional per-column color functions.\n *\n * Columns not in the colorMap default to chalk.gray.\n */\nexport const formatTable = ({\n  data,\n  headers,\n  colorMap = {},\n  emptyMessage = \"No data found\",\n}: {\n  data: Array<Record<string, string>>;\n  headers: string[];\n  colorMap?: ColumnColorMap;\n  emptyMessage?: string;\n}): void => {\n  if (data.length === 0) {\n    console.log(chalk.gray(emptyMessage));\n    return;\n  }\n\n  const colWidths: Record<string, number> = {};\n  headers.forEach((header) => {\n    colWidths[header] = Math.max(\n      header.length,\n      ...data.map((row) => stripAnsi(row[header] ?? \"\").length),\n    );\n  });\n\n  const headerRow = headers\n    .map((header) => chalk.bold(header.padEnd(colWidths[header]!)))\n    .join(\"  \");\n  console.log(headerRow);\n\n  const separator = headers\n    .map((header) => \"─\".repeat(colWidths[header]!))\n    .join(\"  \");\n  console.log(chalk.gray(separator));\n\n  data.forEach((row) => {\n    const dataRow = headers\n      .map((header) => {\n        const value = row[header] ?? \"\";\n        const strippedLength = stripAnsi(value).length;\n        const paddingNeeded = colWidths[header]! - strippedLength;\n        const paddedValue = value + \" \".repeat(Math.max(0, paddingNeeded));\n\n        const colorFn = colorMap[header] ?? chalk.gray;\n        return colorFn(paddedValue);\n      })\n      .join(\"  \");\n    console.log(dataRow);\n  });\n};\n\n/**\n * Formats a date string as a human-readable relative time (e.g. \"3d ago\").\n *\n * Returns \"—\" for invalid dates. Clamps future dates to \"just now\".\n */\nexport const formatRelativeTime = (dateString: string): string => {\n  const date = new Date(dateString);\n  if (Number.isNaN(date.getTime())) return \"—\";\n\n  const now = new Date();\n  const diffMs = Math.max(0, now.getTime() - date.getTime());\n\n  const seconds = Math.floor(diffMs / 1000);\n  const minutes = Math.floor(seconds / 60);\n  const hours = Math.floor(minutes / 60);\n  const days = Math.floor(hours / 24);\n  const months = Math.floor(days / 30);\n  const years = Math.floor(days / 365);\n\n  if (years > 0) return `${years}y ago`;\n  if (months > 0) return `${months}mo ago`;\n  if (days > 0) return `${days}d ago`;\n  if (hours > 0) return `${hours}h ago`;\n  if (minutes > 0) return `${minutes}m ago`;\n  return seconds === 0 ? \"just now\" : `${seconds}s ago`;\n};\n"],"mappings":";AAAA,OAAO,WAAW;AAKX,IAAM,YAAY,CAAC,QAAwB;AAEhD,SAAO,IAAI,QAAQ,qBAAqB,EAAE;AAC5C;AAUO,IAAM,cAAc,CAAC;AAAA,EAC1B;AAAA,EACA;AAAA,EACA,WAAW,CAAC;AAAA,EACZ,eAAe;AACjB,MAKY;AACV,MAAI,KAAK,WAAW,GAAG;AACrB,YAAQ,IAAI,MAAM,KAAK,YAAY,CAAC;AACpC;AAAA,EACF;AAEA,QAAM,YAAoC,CAAC;AAC3C,UAAQ,QAAQ,CAAC,WAAW;AAC1B,cAAU,MAAM,IAAI,KAAK;AAAA,MACvB,OAAO;AAAA,MACP,GAAG,KAAK,IAAI,CAAC,QAAK;AAtCxB;AAsC2B,0BAAU,SAAI,MAAM,MAAV,YAAe,EAAE,EAAE;AAAA,OAAM;AAAA,IAC1D;AAAA,EACF,CAAC;AAED,QAAM,YAAY,QACf,IAAI,CAAC,WAAW,MAAM,KAAK,OAAO,OAAO,UAAU,MAAM,CAAE,CAAC,CAAC,EAC7D,KAAK,IAAI;AACZ,UAAQ,IAAI,SAAS;AAErB,QAAM,YAAY,QACf,IAAI,CAAC,WAAW,SAAI,OAAO,UAAU,MAAM,CAAE,CAAC,EAC9C,KAAK,IAAI;AACZ,UAAQ,IAAI,MAAM,KAAK,SAAS,CAAC;AAEjC,OAAK,QAAQ,CAAC,QAAQ;AACpB,UAAM,UAAU,QACb,IAAI,CAAC,WAAW;AAtDvB;AAuDQ,YAAM,SAAQ,SAAI,MAAM,MAAV,YAAe;AAC7B,YAAM,iBAAiB,UAAU,KAAK,EAAE;AACxC,YAAM,gBAAgB,UAAU,MAAM,IAAK;AAC3C,YAAM,cAAc,QAAQ,IAAI,OAAO,KAAK,IAAI,GAAG,aAAa,CAAC;AAEjE,YAAM,WAAU,cAAS,MAAM,MAAf,YAAoB,MAAM;AAC1C,aAAO,QAAQ,WAAW;AAAA,IAC5B,CAAC,EACA,KAAK,IAAI;AACZ,YAAQ,IAAI,OAAO;AAAA,EACrB,CAAC;AACH;AAOO,IAAM,qBAAqB,CAAC,eAA+B;AAChE,QAAM,OAAO,IAAI,KAAK,UAAU;AAChC,MAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,EAAG,QAAO;AAEzC,QAAM,MAAM,oBAAI,KAAK;AACrB,QAAM,SAAS,KAAK,IAAI,GAAG,IAAI,QAAQ,IAAI,KAAK,QAAQ,CAAC;AAEzD,QAAM,UAAU,KAAK,MAAM,SAAS,GAAI;AACxC,QAAM,UAAU,KAAK,MAAM,UAAU,EAAE;AACvC,QAAM,QAAQ,KAAK,MAAM,UAAU,EAAE;AACrC,QAAM,OAAO,KAAK,MAAM,QAAQ,EAAE;AAClC,QAAM,SAAS,KAAK,MAAM,OAAO,EAAE;AACnC,QAAM,QAAQ,KAAK,MAAM,OAAO,GAAG;AAEnC,MAAI,QAAQ,EAAG,QAAO,GAAG,KAAK;AAC9B,MAAI,SAAS,EAAG,QAAO,GAAG,MAAM;AAChC,MAAI,OAAO,EAAG,QAAO,GAAG,IAAI;AAC5B,MAAI,QAAQ,EAAG,QAAO,GAAG,KAAK;AAC9B,MAAI,UAAU,EAAG,QAAO,GAAG,OAAO;AAClC,SAAO,YAAY,IAAI,aAAa,GAAG,OAAO;AAChD;","names":[]}