@andy2639/jest-context 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/coverage-context.ts","../../src/core/constants.ts","../../src/core/platform.ts","../../src/core/exec.ts","../../src/core/jest.ts","../../src/core/export.ts","../../src/core/cli.ts","../../src/core/ui.ts","../../src/bin/coverage-context.ts"],"sourcesContent":["import path from \"node:path\";\n\nimport {\n createSpinner,\n displayBanner,\n displayHelp,\n exitWithError,\n handleExportOrDisplay,\n JEST_PATTERNS,\n parseExportCliArgs,\n runJest,\n shouldShowUI,\n validateCliArgs,\n logWarning,\n} from \"../core\";\n\nfunction parseCoverage(text: string) {\n const lines = text.split(\"\\n\");\n const rows: Array<{\n folder: string;\n file: string;\n stmts: number;\n branch: number;\n funcs: number;\n lines: number;\n uncovered?: string;\n }> = [];\n\n let currentFolder: string | null = null;\n\n for (const line of lines) {\n const match = line.match(JEST_PATTERNS.COVERAGE_LINE);\n if (!match) continue;\n\n const [, rawFile, stmts, branch, funcs, linesPct, uncovered] = match;\n const normalized = rawFile.trim();\n\n if (normalized === \"All files\") continue;\n\n const isFile = /\\.(ts|tsx)$/.test(normalized);\n if (!isFile) {\n currentFolder = normalized;\n continue;\n }\n\n if (/index\\.(ts|tsx)$/.test(normalized)) continue;\n if (!currentFolder) currentFolder = path.dirname(normalized);\n\n rows.push({\n folder: currentFolder,\n file: path.basename(normalized),\n stmts: Number(stmts),\n branch: Number(branch),\n funcs: Number(funcs),\n lines: Number(linesPct),\n uncovered: uncovered?.trim(),\n });\n }\n\n return rows;\n}\n\nfunction filterIncomplete(rows: ReturnType<typeof parseCoverage>, threshold = 100) {\n return rows.filter(\n (r) => !(r.stmts >= threshold && r.branch >= threshold && r.funcs >= threshold && r.lines >= threshold)\n );\n}\n\nfunction groupByFolder(rows: ReturnType<typeof parseCoverage>) {\n const grouped: Record<string, Array<{ file: string; coverage: Omit<(typeof rows)[number], \"folder\" | \"file\"> }>> = {};\n\n for (const row of rows) {\n const { folder, file, ...rest } = row;\n if (!grouped[folder]) grouped[folder] = [];\n grouped[folder].push({ file, coverage: rest });\n }\n\n return grouped;\n}\n\nfunction formatCoverageOutput(grouped: ReturnType<typeof groupByFolder>): string {\n let output = \"\";\n\n for (const folder of Object.keys(grouped)) {\n output += `📁 Folder: ${folder}\\n`;\n\n for (const item of grouped[folder]) {\n const { file, coverage } = item;\n output += ` 📄 File: ${file}\\n`;\n output += `- Coverage:\\n`;\n output += ` - Stmts: ${coverage.stmts}\\n`;\n output += ` - Branch: ${coverage.branch}\\n`;\n output += ` - Funcs: ${coverage.funcs}\\n`;\n output += ` - Lines: ${coverage.lines}\\n`;\n output += ` - Uncovered: ${coverage.uncovered || \"N/A\"}\\n\\n`;\n }\n\n output += \"\\n\";\n }\n\n return output.trim();\n}\n\nexport async function runCoverageContext(argv = process.argv.slice(2)): Promise<void> {\n if (argv.includes(\"-h\") || argv.includes(\"--help\")) {\n displayHelp(\"Coverage Context Script\", {\n description: \"Run Jest coverage and print files below threshold.\",\n usage: [\"coverage-context\", \"coverage-context --threshold=90\"],\n options: [\n \"--threshold=0..100 Minimum percentage for stmts/branch/funcs/lines (default: 100)\",\n \"--export Export output as txt\",\n \"--export=txt|md Export output in selected format\",\n \"--no-banner Disable fancy terminal UI\",\n \"-h, --help Show this help\",\n ],\n examples: [\"coverage-context --threshold=90 --export=md\"],\n });\n }\n\n const noBanner = argv.includes(\"--no-banner\");\n const args = argv.filter((arg) => arg !== \"--no-banner\");\n\n const { exportFormat, exportArgs } = parseExportCliArgs(args);\n const { parsed, unknownArgs } = validateCliArgs(args, {\n threshold: {\n prefix: \"--threshold=\",\n allowedValues: Array.from({ length: 101 }, (_, i) => String(i)),\n },\n });\n\n const exportArgSet = new Set(exportArgs);\n const filteredUnknownArgs = unknownArgs.filter((arg) => !exportArgSet.has(arg));\n if (filteredUnknownArgs.length > 0) {\n logWarning(`Unknown arguments ignored: ${filteredUnknownArgs.join(\", \")}`);\n }\n\n const threshold = parsed.threshold ? Number(parsed.threshold) : 100;\n const showUI = shouldShowUI(exportFormat, noBanner);\n\n if (showUI) {\n displayBanner({\n text: \"JEST\",\n subtitle: \"COVERAGE\",\n info: {\n Threshold: `>=${threshold}%`,\n },\n colors: [\"magenta\", \"blue\"],\n });\n }\n\n const spinner = showUI ? createSpinner(\"Running Jest coverage...\", \"magenta\") : null;\n spinner?.start();\n\n const result = await runJest([], {\n coverage: true,\n coverageReporters: [\"text\", \"text-summary\"],\n ignoreErrors: true,\n });\n\n const rows = parseCoverage(result.output);\n if (rows.length === 0) {\n spinner?.warn(\"No coverage rows parsed\");\n\n handleExportOrDisplay(\"No coverage rows parsed from Jest output.\", {\n exportFormat,\n prefix: \"export-coverage-context\",\n title: \"Coverage Context\",\n });\n\n return;\n }\n\n const incomplete = filterIncomplete(rows, threshold);\n const grouped = groupByFolder(incomplete);\n\n if (Object.keys(grouped).length === 0) {\n spinner?.succeed(`All files meet threshold >= ${threshold}%`);\n\n handleExportOrDisplay(`All files meet threshold >= ${threshold}%`, {\n exportFormat,\n prefix: \"export-coverage-context\",\n title: \"Coverage Context\",\n });\n\n return;\n }\n\n const formatted = formatCoverageOutput(grouped);\n spinner?.warn(`Found ${incomplete.length} file(s) below threshold`);\n\n handleExportOrDisplay(formatted, {\n exportFormat,\n prefix: \"export-coverage-context\",\n title: \"Coverage Context\",\n });\n}\n","export const VALID_MODES = [\"--all\", \"--related\", \"--tests\"] as const;\n\nexport const VALID_EXPORT_FORMATS = [\"txt\", \"md\"] as const;\n\nexport const VALID_TEST_EXTENSIONS = /\\.(test|spec)\\.(ts|tsx|js|jsx)$/;\n\nexport const CONSOLE_LOG_TYPES = {\n ERROR: \"console.error\",\n WARN: \"console.warn\",\n LOG: \"console.log\",\n DEBUG: \"console.debug\",\n} as const;\n\nexport const JEST_PATTERNS = {\n FAIL_LINE: /^FAIL\\s+/,\n PASS_LINE: /^PASS\\s+/,\n TEST_FILE: /^(PASS|FAIL)\\s+(.+\\.(test|spec)\\.tsx?)/,\n COVERAGE_LINE:\n /^(.+?)\\s+\\|\\s+([\\d.]+)\\s+\\|\\s+([\\d.]+)\\s+\\|\\s+([\\d.]+)\\s+\\|\\s+([\\d.]+)(?:\\s+\\|\\s+(.+))?$/,\n BULLET_POINT: /^●\\s+/,\n CODE_LINE: /^>?\\s*\\d*\\s*\\|/,\n STACK_TRACE: /^\\s+at\\s+/,\n};\n","export function getPlatform(): NodeJS.Platform {\n return process.platform;\n}\n\nexport function isWindows(): boolean {\n return process.platform === \"win32\";\n}\n\nexport function isMac(): boolean {\n return process.platform === \"darwin\";\n}\n\nexport function isLinux(): boolean {\n return process.platform === \"linux\";\n}\n\nexport function resolveCommand(cmd: string): string {\n if (!isWindows()) return cmd;\n\n const windowsCommands: Record<string, string> = {\n git: \"git.exe\",\n node: \"node.exe\",\n npm: \"npm.cmd\",\n npx: \"npx.cmd\",\n yarn: \"yarn.cmd\",\n pnpm: \"pnpm.cmd\",\n };\n\n return windowsCommands[cmd] ?? cmd;\n}\n","import { spawn } from \"node:child_process\";\n\nimport { resolveCommand } from \"./platform\";\nimport type { ExecResult } from \"../types\";\n\nexport async function execCommand(\n cmd: string,\n args: string[] = [],\n options: { shell?: boolean; ignoreErrors?: boolean } = {}\n): Promise<ExecResult> {\n return new Promise((resolve, reject) => {\n const resolvedCmd = resolveCommand(cmd);\n const child = spawn(resolvedCmd, args, {\n shell: options.shell ?? false,\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n child.stdout?.on(\"data\", (d) => {\n stdout += d.toString();\n });\n\n child.stderr?.on(\"data\", (d) => {\n stderr += d.toString();\n });\n\n child.on(\"close\", (code) => {\n const result: ExecResult = {\n stdout,\n stderr,\n output: `${stdout}\\n${stderr}`,\n code,\n };\n\n if (code !== 0 && !options.ignoreErrors) {\n reject(new Error(`Command failed with code ${code}: ${cmd} ${args.join(\" \")}`));\n return;\n }\n\n resolve(result);\n });\n\n child.on(\"error\", (error) => {\n reject(new Error(`Failed to execute command: ${error.message}`));\n });\n });\n}\n","import { spawn } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\nimport { isWindows } from \"./platform\";\nimport { filterTestFiles, getStagedFiles } from \"./git\";\nimport type { ExecutionMode, ExecResult, RunJestOptions } from \"../types\";\n\ntype ResolvedJestRunner = {\n command: string;\n argsPrefix: string[];\n};\n\nfunction resolveJestRunner(): ResolvedJestRunner {\n const cwd = process.cwd();\n const attempts: string[] = [];\n\n try {\n const jestPackageJsonPath = require.resolve(\"jest/package.json\", { paths: [cwd] });\n attempts.push(`Resolved jest package: ${jestPackageJsonPath}`);\n\n const jestPackageDir = path.dirname(jestPackageJsonPath);\n const jestPackage = JSON.parse(readFileSync(jestPackageJsonPath, \"utf-8\")) as {\n bin?: string | Record<string, string>;\n };\n\n const binField = jestPackage.bin;\n let binEntry: string | undefined;\n if (typeof binField === \"string\") {\n binEntry = binField;\n } else if (binField && typeof binField === \"object\") {\n binEntry = binField.jest ?? Object.values(binField)[0];\n }\n\n if (binEntry) {\n const binPath = path.resolve(jestPackageDir, binEntry);\n if (existsSync(binPath)) {\n return {\n command: process.execPath,\n argsPrefix: [binPath],\n };\n }\n attempts.push(`Jest bin from package.json not found: ${binPath}`);\n } else {\n attempts.push(\"Jest package.json has no usable bin field.\");\n }\n } catch {\n attempts.push(\"Could not resolve jest/package.json from current cwd.\");\n }\n\n try {\n const legacyBinPath = require.resolve(\"jest/bin/jest.js\", { paths: [cwd] });\n attempts.push(`Resolved legacy jest bin: ${legacyBinPath}`);\n return {\n command: process.execPath,\n argsPrefix: [legacyBinPath],\n };\n } catch {\n attempts.push(\"Could not resolve legacy path jest/bin/jest.js.\");\n }\n\n const localBinPath = path.resolve(cwd, \"node_modules\", \".bin\", isWindows() ? \"jest.cmd\" : \"jest\");\n if (existsSync(localBinPath)) {\n attempts.push(`Resolved local .bin executable: ${localBinPath}`);\n return {\n command: localBinPath,\n argsPrefix: [],\n };\n }\n attempts.push(`Local .bin executable not found: ${localBinPath}`);\n\n throw new Error(\n [\n \"Could not resolve Jest from the current project.\",\n \"Install `jest@^29` in the package where you run this command.\",\n \"Examples: `npm i -D jest@^29`, `pnpm add -D jest@^29`, `yarn add -D jest@^29`.\",\n `cwd: ${cwd}`,\n ...attempts,\n ].join(\"\\n\")\n );\n}\n\nexport async function runJest(args: string[] = [], options: RunJestOptions = {}): Promise<ExecResult> {\n const {\n verbose = false,\n coverage = false,\n ignoreErrors = true,\n disableVerbose = false,\n } = options;\n\n const runner = resolveJestRunner();\n const command = runner.command;\n const jestArgs = [...runner.argsPrefix];\n\n if (verbose && !disableVerbose) {\n jestArgs.push(\"--verbose\");\n }\n\n if (coverage) {\n jestArgs.push(\"--coverage\");\n\n if (options.coverageReporters) {\n for (const reporter of options.coverageReporters) {\n jestArgs.push(`--coverageReporters=${reporter}`);\n }\n }\n }\n\n if (isWindows()) {\n jestArgs.push(\"--no-watchman\");\n }\n\n jestArgs.push(...args);\n\n return new Promise((resolve, reject) => {\n const child = spawn(command, jestArgs, {\n shell: false,\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n child.stdout.on(\"data\", (d) => {\n stdout += d.toString();\n });\n\n child.stderr.on(\"data\", (d) => {\n stderr += d.toString();\n });\n\n child.on(\"close\", (code) => {\n const result: ExecResult = {\n stdout,\n stderr,\n output: `${stdout}\\n${stderr}`,\n code,\n };\n\n if (code !== 0 && !ignoreErrors) {\n reject(new Error(`Jest failed with code ${code}`));\n return;\n }\n\n resolve(result);\n });\n\n child.on(\"error\", reject);\n });\n}\n\nexport async function buildJestArgsForMode(mode: ExecutionMode): Promise<string[]> {\n if (mode === \"all\") {\n return [];\n }\n\n const staged = await getStagedFiles();\n if (staged.length === 0) {\n throw new Error(`No staged files found for mode: ${mode}`);\n }\n\n if (mode === \"tests\") {\n const testFiles = filterTestFiles(staged);\n if (testFiles.length === 0) {\n throw new Error(\"No test files found in staged files\");\n }\n\n return testFiles;\n }\n\n return [\"--findRelatedTests\", ...staged];\n}\n","import { writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\nimport { VALID_EXPORT_FORMATS } from \"./constants\";\nimport type { ExportFormat, OutputOptions } from \"../types\";\n\nexport function getDisplayTimestamp(locale = \"en-US\"): string {\n return new Date().toLocaleString(locale, {\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: false,\n });\n}\n\nexport function getFilenameTimestamp(): string {\n const now = new Date();\n const pad = (value: number) => String(value).padStart(2, \"0\");\n\n return (\n [now.getFullYear(), pad(now.getMonth() + 1), pad(now.getDate())].join(\"-\") +\n \"_\" +\n [pad(now.getHours()), pad(now.getMinutes()), pad(now.getSeconds())].join(\"-\")\n );\n}\n\nexport function buildTimestampedPath(prefix: string, extension: string, dir = process.cwd()): string {\n const timestamp = getFilenameTimestamp();\n const filename = `${prefix}-${timestamp}.${extension}`;\n\n return path.resolve(dir, filename);\n}\n\nexport function formatAsMarkdown(content: string, title: string, timestamp: string | null = null): string {\n const lines = [`# ${title}`, \"\"];\n\n if (timestamp) {\n lines.push(`Generated: ${timestamp}`, \"\");\n }\n\n lines.push(\"```text\", content.trimEnd(), \"```\", \"\");\n\n return lines.join(\"\\n\");\n}\n\nexport function exportToFile(\n content: string,\n options: { prefix: string; format: ExportFormat; title?: string; dir?: string }\n): string {\n const { prefix, format, title, dir = process.cwd() } = options;\n const filePath = buildTimestampedPath(prefix, format, dir);\n\n let finalContent = content;\n if (format === \"md\" && title) {\n finalContent = formatAsMarkdown(content, title, getDisplayTimestamp());\n }\n\n writeFileSync(filePath, finalContent, \"utf-8\");\n\n return filePath;\n}\n\nexport function parseExportCliArgs(args: string[]): { exportFormat: ExportFormat | null; exportArgs: string[] } {\n let exportFormat: ExportFormat | null = null;\n const exportArgs: string[] = [];\n\n for (const arg of args) {\n if (arg === \"--export\") {\n exportFormat = \"txt\";\n exportArgs.push(arg);\n continue;\n }\n\n if (!arg.startsWith(\"--export=\")) {\n continue;\n }\n\n const value = arg.slice(\"--export=\".length).trim().toLowerCase();\n if (!value || !VALID_EXPORT_FORMATS.includes(value as ExportFormat)) {\n throw new Error(`Invalid value for --export: ${value || \"(empty)\"}. Valid values: txt, md`);\n }\n\n exportFormat = value as ExportFormat;\n exportArgs.push(arg);\n }\n\n return { exportFormat, exportArgs };\n}\n\nexport function handleExportOrDisplay(content: string, config: OutputOptions): string | null {\n const { exportFormat, prefix, title } = config;\n\n if (!exportFormat) {\n console.log(content);\n\n return null;\n }\n\n const outputPath = exportToFile(content, {\n prefix,\n format: exportFormat,\n title,\n });\n\n console.log(`Output exported to: ${outputPath}`);\n\n return outputPath;\n}\n","type SchemaEntry = {\n values?: string[];\n default?: string;\n exclusive?: boolean;\n prefix?: string;\n allowedValues?: string[];\n};\n\nexport function validateCliArgs(\n args: string[],\n schema: Record<string, SchemaEntry>\n): { parsed: Record<string, string | undefined>; unknownArgs: string[] } {\n const parsed: Record<string, string | undefined> = {};\n const unknownArgs: string[] = [];\n\n for (const [key, config] of Object.entries(schema)) {\n if (config.default !== undefined) {\n parsed[key] = config.default;\n }\n }\n\n for (const arg of args) {\n let matched = false;\n\n for (const [key, config] of Object.entries(schema)) {\n if (config.values?.includes(arg)) {\n if (config.exclusive && parsed[key] !== undefined && parsed[key] !== config.default) {\n throw new Error(`Multiple values provided for ${key}: ${parsed[key]} and ${arg}`);\n }\n\n parsed[key] = arg;\n matched = true;\n break;\n }\n\n if (config.prefix && arg.startsWith(config.prefix)) {\n const value = arg.slice(config.prefix.length).trim().toLowerCase();\n\n if (!value) {\n parsed[key] = \"true\";\n matched = true;\n break;\n }\n\n if (config.allowedValues && !config.allowedValues.includes(value)) {\n throw new Error(\n `Invalid value for ${config.prefix}: ${value}. Valid values: ${config.allowedValues.join(\", \")}`\n );\n }\n\n parsed[key] = value;\n matched = true;\n break;\n }\n }\n\n if (!matched && arg.startsWith(\"--\")) {\n unknownArgs.push(arg);\n }\n }\n\n return { parsed, unknownArgs };\n}\n\nexport function displayHelp(\n title: string,\n content: { description?: string; usage?: string[]; options?: string[]; examples?: string[] }\n): never {\n console.log(`\\n${title}\\n`);\n\n if (content.description) {\n console.log(`${content.description}\\n`);\n }\n\n if (content.usage?.length) {\n console.log(\"Usage:\");\n content.usage.forEach((line) => console.log(` ${line}`));\n console.log(\"\");\n }\n\n if (content.options?.length) {\n console.log(\"Options:\");\n content.options.forEach((line) => console.log(` ${line}`));\n console.log(\"\");\n }\n\n if (content.examples?.length) {\n console.log(\"Examples:\");\n content.examples.forEach((line) => console.log(` ${line}`));\n console.log(\"\");\n }\n\n process.exit(0);\n}\n\nexport function exitWithError(message: string, code = 1): never {\n console.error(`❌ ${message}`);\n process.exit(code);\n}\n\nexport function logWarning(message: string): void {\n console.warn(`⚠️ ${message}`);\n}\n\nexport function logInfo(message: string): void {\n console.log(`ℹ️ ${message}`);\n}\n\nexport function logSuccess(message: string): void {\n console.log(`✅ ${message}`);\n}\n","import { getDisplayTimestamp } from \"./export\";\n\ntype Spinner = {\n start: () => Spinner;\n stop: () => Spinner;\n succeed: (message?: string) => Spinner;\n warn: (message?: string) => Spinner;\n fail: (message?: string) => Spinner;\n};\n\ntype ProgressBar = {\n update: (value: number, payload?: Record<string, string>) => void;\n stop: () => void;\n};\n\nconst NOOP_PROGRESS_BAR: ProgressBar = {\n update: () => {},\n stop: () => {},\n};\n\nlet hasWarnedSpinnerFallback = false;\nlet hasWarnedProgressFallback = false;\n\nexport function shouldShowUI(exportMode: string | null, noBanner = false): boolean {\n return !exportMode && !noBanner && Boolean(process.stdout.isTTY);\n}\n\nexport function displayBanner(config: {\n text: string;\n subtitle?: string;\n info?: Record<string, string>;\n colors?: string[];\n font?: string;\n}): void {\n const { text, subtitle, info = {}, colors = [\"cyan\"], font = \"block\" } = config;\n const bannerText = [text, subtitle].filter(Boolean).join(\" \").trim();\n\n // Lazy load to avoid breaking non-interactive execution.\n const cfonts = require(\"cfonts\") as {\n render: (message: string, options: Record<string, unknown>) => { string: string };\n };\n const boxenModule = require(\"boxen\") as\n | ((text: string, options: Record<string, unknown>) => string)\n | { default: (text: string, options: Record<string, unknown>) => string };\n const boxen = typeof boxenModule === \"function\" ? boxenModule : boxenModule.default;\n\n const renderedBanner = cfonts.render(bannerText, {\n font,\n colors,\n align: \"left\",\n background: \"transparent\",\n letterSpacing: 1,\n lineHeight: 1,\n space: false,\n maxLength: \"0\",\n env: \"node\",\n });\n\n const infoLine = Object.entries(info)\n .map(([key, value]) => `${key}: ${value}`)\n .join(\" | \");\n\n const contentLines = [renderedBanner.string.trimEnd()];\n if (infoLine) {\n contentLines.push(\"\", ` ${infoLine}`);\n }\n contentLines.push(` Date: ${getDisplayTimestamp()}`);\n\n const boxed = boxen(contentLines.join(\"\\n\"), {\n padding: {\n top: 0,\n right: 1,\n bottom: 0,\n left: 1,\n },\n margin: {\n top: 0,\n right: 0,\n bottom: 1,\n left: 0,\n },\n borderStyle: \"round\",\n borderColor: colors[0] ?? \"cyan\",\n });\n\n console.log(boxed);\n}\n\nexport function createSpinner(text: string, color: string = \"cyan\"): Spinner {\n try {\n const ora = require(\"ora\") as (config: Record<string, unknown>) => Spinner;\n\n return ora({ text, color, spinner: \"dots\" });\n } catch {\n if (!hasWarnedSpinnerFallback) {\n hasWarnedSpinnerFallback = true;\n console.warn(\"Warning: spinner UI unavailable, continuing without spinner.\");\n }\n\n return {\n start: () => NOOP_SPINNER,\n stop: () => NOOP_SPINNER,\n succeed: () => NOOP_SPINNER,\n warn: () => NOOP_SPINNER,\n fail: () => NOOP_SPINNER,\n } as Spinner;\n }\n}\n\nconst NOOP_SPINNER: Spinner = {\n start: () => NOOP_SPINNER,\n stop: () => NOOP_SPINNER,\n succeed: () => NOOP_SPINNER,\n warn: () => NOOP_SPINNER,\n fail: () => NOOP_SPINNER,\n};\n\nexport function createProgressBar(total = 100, task = \"Progress\"): ProgressBar {\n if (!hasWarnedProgressFallback) {\n hasWarnedProgressFallback = true;\n console.warn(\n `Warning: progress bar UI is no longer used. Ignoring createProgressBar(${total}, ${JSON.stringify(task)}).`\n );\n }\n\n return NOOP_PROGRESS_BAR;\n}\n","#!/usr/bin/env node\n\nimport { runCoverageContext } from \"../commands/coverage-context\";\n\nrunCoverageContext().catch((error) => {\n console.error(`❌ ${(error as Error).message}`);\n process.exit(1);\n});\n"],"mappings":"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","names":["import_node_path","import_node_child_process","path","import_node_fs","import_node_path","path","path"]}
1
+ {"version":3,"sources":["../../src/commands/coverage-context.ts","../../src/core/constants.ts","../../src/core/platform.ts","../../src/core/exec.ts","../../src/core/jest.ts","../../src/core/export.ts","../../src/core/cli.ts","../../src/core/ui.ts","../../src/bin/coverage-context.ts"],"sourcesContent":["import path from \"node:path\";\n\nimport {\n createSpinner,\n displayBanner,\n displayHelp,\n exitWithError,\n handleExportOrDisplay,\n JEST_PATTERNS,\n parseExportCliArgs,\n runJest,\n shouldShowUI,\n validateCliArgs,\n logWarning,\n} from \"../core\";\n\nfunction parseCoverage(text: string) {\n const lines = text.split(\"\\n\");\n const rows: Array<{\n folder: string;\n file: string;\n stmts: number;\n branch: number;\n funcs: number;\n lines: number;\n uncovered?: string;\n }> = [];\n\n let currentFolder: string | null = null;\n\n for (const line of lines) {\n const match = line.match(JEST_PATTERNS.COVERAGE_LINE);\n if (!match) continue;\n\n const [, rawFile, stmts, branch, funcs, linesPct, uncovered] = match;\n const normalized = rawFile.trim();\n\n if (normalized === \"All files\") continue;\n\n const isFile = /\\.(ts|tsx)$/.test(normalized);\n if (!isFile) {\n currentFolder = normalized;\n continue;\n }\n\n if (/index\\.(ts|tsx)$/.test(normalized)) continue;\n if (!currentFolder) currentFolder = path.dirname(normalized);\n\n rows.push({\n folder: currentFolder,\n file: path.basename(normalized),\n stmts: Number(stmts),\n branch: Number(branch),\n funcs: Number(funcs),\n lines: Number(linesPct),\n uncovered: uncovered?.trim(),\n });\n }\n\n return rows;\n}\n\nfunction filterIncomplete(rows: ReturnType<typeof parseCoverage>, threshold = 100) {\n return rows.filter(\n (r) => !(r.stmts >= threshold && r.branch >= threshold && r.funcs >= threshold && r.lines >= threshold)\n );\n}\n\nfunction groupByFolder(rows: ReturnType<typeof parseCoverage>) {\n const grouped: Record<string, Array<{ file: string; coverage: Omit<(typeof rows)[number], \"folder\" | \"file\"> }>> = {};\n\n for (const row of rows) {\n const { folder, file, ...rest } = row;\n if (!grouped[folder]) grouped[folder] = [];\n grouped[folder].push({ file, coverage: rest });\n }\n\n return grouped;\n}\n\nfunction formatCoverageOutput(grouped: ReturnType<typeof groupByFolder>): string {\n let output = \"\";\n\n for (const folder of Object.keys(grouped)) {\n output += `📁 Folder: ${folder}\\n`;\n\n for (const item of grouped[folder]) {\n const { file, coverage } = item;\n output += ` 📄 File: ${file}\\n`;\n output += `- Coverage:\\n`;\n output += ` - Stmts: ${coverage.stmts}\\n`;\n output += ` - Branch: ${coverage.branch}\\n`;\n output += ` - Funcs: ${coverage.funcs}\\n`;\n output += ` - Lines: ${coverage.lines}\\n`;\n output += ` - Uncovered: ${coverage.uncovered || \"N/A\"}\\n\\n`;\n }\n\n output += \"\\n\";\n }\n\n return output.trim();\n}\n\nfunction outputCoverageContext(content: string, options: { exportFormat: \"txt\" | \"md\" | null }): void {\n const { exportFormat } = options;\n\n if (!exportFormat) {\n handleExportOrDisplay(content, {\n exportFormat,\n prefix: \"export-coverage-context\",\n title: \"Coverage Context\",\n });\n\n return;\n }\n\n const exportSpinner = createSpinner(\"Exporting coverage context...\", \"magenta\");\n exportSpinner.start();\n\n handleExportOrDisplay(content, {\n exportFormat,\n prefix: \"export-coverage-context\",\n title: \"Coverage Context\",\n });\n\n exportSpinner.succeed(\"Coverage context exported\");\n}\n\nexport async function runCoverageContext(argv = process.argv.slice(2)): Promise<void> {\n if (argv.includes(\"-h\") || argv.includes(\"--help\")) {\n displayHelp(\"Coverage Context Script\", {\n description: \"Run Jest coverage and print files below threshold.\",\n usage: [\"coverage-context\", \"coverage-context --threshold=90\"],\n options: [\n \"--threshold=0..100 Minimum percentage for stmts/branch/funcs/lines (default: 100)\",\n \"--export Export output as txt\",\n \"--export=txt|md Export output in selected format\",\n \"--no-banner Disable fancy terminal UI\",\n \"-h, --help Show this help\",\n ],\n examples: [\"coverage-context --threshold=90 --export=md\"],\n });\n }\n\n const noBanner = argv.includes(\"--no-banner\");\n const args = argv.filter((arg) => arg !== \"--no-banner\");\n\n const { exportFormat, exportArgs } = parseExportCliArgs(args);\n const { parsed, unknownArgs } = validateCliArgs(args, {\n threshold: {\n prefix: \"--threshold=\",\n allowedValues: Array.from({ length: 101 }, (_, i) => String(i)),\n },\n });\n\n const exportArgSet = new Set(exportArgs);\n const filteredUnknownArgs = unknownArgs.filter((arg) => !exportArgSet.has(arg));\n if (filteredUnknownArgs.length > 0) {\n logWarning(`Unknown arguments ignored: ${filteredUnknownArgs.join(\", \")}`);\n }\n\n const threshold = parsed.threshold ? Number(parsed.threshold) : 100;\n const showBanner = shouldShowUI(exportFormat, noBanner);\n\n if (showBanner) {\n displayBanner({\n text: \"JEST\",\n subtitle: \"COVERAGE\",\n info: {\n Threshold: `>=${threshold}%`,\n },\n colors: [\"magenta\", \"blue\"],\n });\n }\n\n const spinner = createSpinner(\"Running Jest coverage...\", \"magenta\");\n spinner.start();\n\n const result = await runJest([], {\n coverage: true,\n coverageReporters: [\"text\", \"text-summary\"],\n ignoreErrors: true,\n });\n\n const rows = parseCoverage(result.output);\n if (rows.length === 0) {\n spinner.warn(\"No coverage rows parsed\");\n\n outputCoverageContext(\"No coverage rows parsed from Jest output.\", { exportFormat });\n\n return;\n }\n\n const incomplete = filterIncomplete(rows, threshold);\n const grouped = groupByFolder(incomplete);\n\n if (Object.keys(grouped).length === 0) {\n spinner.succeed(`All files meet threshold >= ${threshold}%`);\n\n outputCoverageContext(`All files meet threshold >= ${threshold}%`, { exportFormat });\n\n return;\n }\n\n const formatted = formatCoverageOutput(grouped);\n spinner.warn(`Found ${incomplete.length} file(s) below threshold`);\n\n outputCoverageContext(formatted, { exportFormat });\n}\n","export const VALID_MODES = [\"--all\", \"--related\", \"--tests\"] as const;\n\nexport const VALID_EXPORT_FORMATS = [\"txt\", \"md\"] as const;\n\nexport const VALID_TEST_EXTENSIONS = /\\.(test|spec)\\.(ts|tsx|js|jsx)$/;\n\nexport const CONSOLE_LOG_TYPES = {\n ERROR: \"console.error\",\n WARN: \"console.warn\",\n LOG: \"console.log\",\n DEBUG: \"console.debug\",\n} as const;\n\nexport const JEST_PATTERNS = {\n FAIL_LINE: /^FAIL\\s+/,\n PASS_LINE: /^PASS\\s+/,\n TEST_FILE: /^(PASS|FAIL)\\s+(.+\\.(test|spec)\\.tsx?)/,\n COVERAGE_LINE:\n /^(.+?)\\s+\\|\\s+([\\d.]+)\\s+\\|\\s+([\\d.]+)\\s+\\|\\s+([\\d.]+)\\s+\\|\\s+([\\d.]+)(?:\\s+\\|\\s+(.+))?$/,\n BULLET_POINT: /^●\\s+/,\n CODE_LINE: /^>?\\s*\\d*\\s*\\|/,\n STACK_TRACE: /^\\s+at\\s+/,\n};\n","export function getPlatform(): NodeJS.Platform {\n return process.platform;\n}\n\nexport function isWindows(): boolean {\n return process.platform === \"win32\";\n}\n\nexport function isMac(): boolean {\n return process.platform === \"darwin\";\n}\n\nexport function isLinux(): boolean {\n return process.platform === \"linux\";\n}\n\nexport function resolveCommand(cmd: string): string {\n if (!isWindows()) return cmd;\n\n const windowsCommands: Record<string, string> = {\n git: \"git.exe\",\n node: \"node.exe\",\n npm: \"npm.cmd\",\n npx: \"npx.cmd\",\n yarn: \"yarn.cmd\",\n pnpm: \"pnpm.cmd\",\n };\n\n return windowsCommands[cmd] ?? cmd;\n}\n","import { spawn } from \"node:child_process\";\n\nimport { resolveCommand } from \"./platform\";\nimport type { ExecResult } from \"../types\";\n\nexport async function execCommand(\n cmd: string,\n args: string[] = [],\n options: { shell?: boolean; ignoreErrors?: boolean } = {}\n): Promise<ExecResult> {\n return new Promise((resolve, reject) => {\n const resolvedCmd = resolveCommand(cmd);\n const child = spawn(resolvedCmd, args, {\n shell: options.shell ?? false,\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n child.stdout?.on(\"data\", (d) => {\n stdout += d.toString();\n });\n\n child.stderr?.on(\"data\", (d) => {\n stderr += d.toString();\n });\n\n child.on(\"close\", (code) => {\n const result: ExecResult = {\n stdout,\n stderr,\n output: `${stdout}\\n${stderr}`,\n code,\n };\n\n if (code !== 0 && !options.ignoreErrors) {\n reject(new Error(`Command failed with code ${code}: ${cmd} ${args.join(\" \")}`));\n return;\n }\n\n resolve(result);\n });\n\n child.on(\"error\", (error) => {\n reject(new Error(`Failed to execute command: ${error.message}`));\n });\n });\n}\n","import { spawn } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\nimport { isWindows } from \"./platform\";\nimport { filterTestFiles, getStagedFiles } from \"./git\";\nimport type { ExecutionMode, ExecResult, RunJestOptions } from \"../types\";\n\ntype ResolvedJestRunner = {\n command: string;\n argsPrefix: string[];\n};\n\nfunction resolveJestRunner(): ResolvedJestRunner {\n const cwd = process.cwd();\n const attempts: string[] = [];\n\n try {\n const jestPackageJsonPath = require.resolve(\"jest/package.json\", { paths: [cwd] });\n attempts.push(`Resolved jest package: ${jestPackageJsonPath}`);\n\n const jestPackageDir = path.dirname(jestPackageJsonPath);\n const jestPackage = JSON.parse(readFileSync(jestPackageJsonPath, \"utf-8\")) as {\n bin?: string | Record<string, string>;\n };\n\n const binField = jestPackage.bin;\n let binEntry: string | undefined;\n if (typeof binField === \"string\") {\n binEntry = binField;\n } else if (binField && typeof binField === \"object\") {\n binEntry = binField.jest ?? Object.values(binField)[0];\n }\n\n if (binEntry) {\n const binPath = path.resolve(jestPackageDir, binEntry);\n if (existsSync(binPath)) {\n return {\n command: process.execPath,\n argsPrefix: [binPath],\n };\n }\n attempts.push(`Jest bin from package.json not found: ${binPath}`);\n } else {\n attempts.push(\"Jest package.json has no usable bin field.\");\n }\n } catch {\n attempts.push(\"Could not resolve jest/package.json from current cwd.\");\n }\n\n try {\n const legacyBinPath = require.resolve(\"jest/bin/jest.js\", { paths: [cwd] });\n attempts.push(`Resolved legacy jest bin: ${legacyBinPath}`);\n return {\n command: process.execPath,\n argsPrefix: [legacyBinPath],\n };\n } catch {\n attempts.push(\"Could not resolve legacy path jest/bin/jest.js.\");\n }\n\n const localBinPath = path.resolve(cwd, \"node_modules\", \".bin\", isWindows() ? \"jest.cmd\" : \"jest\");\n if (existsSync(localBinPath)) {\n attempts.push(`Resolved local .bin executable: ${localBinPath}`);\n return {\n command: localBinPath,\n argsPrefix: [],\n };\n }\n attempts.push(`Local .bin executable not found: ${localBinPath}`);\n\n throw new Error(\n [\n \"Could not resolve Jest from the current project.\",\n \"Install `jest@^29` in the package where you run this command.\",\n \"Examples: `npm i -D jest@^29`, `pnpm add -D jest@^29`, `yarn add -D jest@^29`.\",\n `cwd: ${cwd}`,\n ...attempts,\n ].join(\"\\n\")\n );\n}\n\nexport async function runJest(args: string[] = [], options: RunJestOptions = {}): Promise<ExecResult> {\n const {\n verbose = false,\n coverage = false,\n ignoreErrors = true,\n disableVerbose = false,\n } = options;\n\n const runner = resolveJestRunner();\n const command = runner.command;\n const jestArgs = [...runner.argsPrefix];\n\n if (verbose && !disableVerbose) {\n jestArgs.push(\"--verbose\");\n }\n\n if (coverage) {\n jestArgs.push(\"--coverage\");\n\n if (options.coverageReporters) {\n for (const reporter of options.coverageReporters) {\n jestArgs.push(`--coverageReporters=${reporter}`);\n }\n }\n }\n\n if (isWindows()) {\n jestArgs.push(\"--no-watchman\");\n }\n\n jestArgs.push(...args);\n\n return new Promise((resolve, reject) => {\n const child = spawn(command, jestArgs, {\n shell: false,\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n child.stdout.on(\"data\", (d) => {\n stdout += d.toString();\n });\n\n child.stderr.on(\"data\", (d) => {\n stderr += d.toString();\n });\n\n child.on(\"close\", (code) => {\n const result: ExecResult = {\n stdout,\n stderr,\n output: `${stdout}\\n${stderr}`,\n code,\n };\n\n if (code !== 0 && !ignoreErrors) {\n reject(new Error(`Jest failed with code ${code}`));\n return;\n }\n\n resolve(result);\n });\n\n child.on(\"error\", reject);\n });\n}\n\nexport async function buildJestArgsForMode(mode: ExecutionMode): Promise<string[]> {\n if (mode === \"all\") {\n return [];\n }\n\n const staged = await getStagedFiles();\n if (staged.length === 0) {\n throw new Error(`No staged files found for mode: ${mode}`);\n }\n\n if (mode === \"tests\") {\n const testFiles = filterTestFiles(staged);\n if (testFiles.length === 0) {\n throw new Error(\"No test files found in staged files\");\n }\n\n return testFiles;\n }\n\n return [\"--findRelatedTests\", ...staged];\n}\n","import { writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\nimport { VALID_EXPORT_FORMATS } from \"./constants\";\nimport type { ExportFormat, OutputOptions } from \"../types\";\n\nexport function getDisplayTimestamp(locale = \"en-US\"): string {\n return new Date().toLocaleString(locale, {\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: false,\n });\n}\n\nexport function getFilenameTimestamp(): string {\n const now = new Date();\n const pad = (value: number) => String(value).padStart(2, \"0\");\n\n return (\n [now.getFullYear(), pad(now.getMonth() + 1), pad(now.getDate())].join(\"-\") +\n \"_\" +\n [pad(now.getHours()), pad(now.getMinutes()), pad(now.getSeconds())].join(\"-\")\n );\n}\n\nexport function buildTimestampedPath(prefix: string, extension: string, dir = process.cwd()): string {\n const timestamp = getFilenameTimestamp();\n const filename = `${prefix}-${timestamp}.${extension}`;\n\n return path.resolve(dir, filename);\n}\n\nexport function formatAsMarkdown(content: string, title: string, timestamp: string | null = null): string {\n const lines = [`# ${title}`, \"\"];\n\n if (timestamp) {\n lines.push(`Generated: ${timestamp}`, \"\");\n }\n\n lines.push(\"```text\", content.trimEnd(), \"```\", \"\");\n\n return lines.join(\"\\n\");\n}\n\nexport function exportToFile(\n content: string,\n options: { prefix: string; format: ExportFormat; title?: string; dir?: string }\n): string {\n const { prefix, format, title, dir = process.cwd() } = options;\n const filePath = buildTimestampedPath(prefix, format, dir);\n\n let finalContent = content;\n if (format === \"md\" && title) {\n finalContent = formatAsMarkdown(content, title, getDisplayTimestamp());\n }\n\n writeFileSync(filePath, finalContent, \"utf-8\");\n\n return filePath;\n}\n\nexport function parseExportCliArgs(args: string[]): { exportFormat: ExportFormat | null; exportArgs: string[] } {\n let exportFormat: ExportFormat | null = null;\n const exportArgs: string[] = [];\n\n for (const arg of args) {\n if (arg === \"--export\") {\n exportFormat = \"txt\";\n exportArgs.push(arg);\n continue;\n }\n\n if (!arg.startsWith(\"--export=\")) {\n continue;\n }\n\n const value = arg.slice(\"--export=\".length).trim().toLowerCase();\n if (!value || !VALID_EXPORT_FORMATS.includes(value as ExportFormat)) {\n throw new Error(`Invalid value for --export: ${value || \"(empty)\"}. Valid values: txt, md`);\n }\n\n exportFormat = value as ExportFormat;\n exportArgs.push(arg);\n }\n\n return { exportFormat, exportArgs };\n}\n\nexport function handleExportOrDisplay(content: string, config: OutputOptions): string | null {\n const { exportFormat, prefix, title } = config;\n\n if (!exportFormat) {\n console.log(content);\n\n return null;\n }\n\n const outputPath = exportToFile(content, {\n prefix,\n format: exportFormat,\n title,\n });\n\n console.log(`Output exported to: ${outputPath}`);\n\n return outputPath;\n}\n","type SchemaEntry = {\n values?: string[];\n default?: string;\n exclusive?: boolean;\n prefix?: string;\n allowedValues?: string[];\n};\n\nexport function validateCliArgs(\n args: string[],\n schema: Record<string, SchemaEntry>\n): { parsed: Record<string, string | undefined>; unknownArgs: string[] } {\n const parsed: Record<string, string | undefined> = {};\n const unknownArgs: string[] = [];\n\n for (const [key, config] of Object.entries(schema)) {\n if (config.default !== undefined) {\n parsed[key] = config.default;\n }\n }\n\n for (const arg of args) {\n let matched = false;\n\n for (const [key, config] of Object.entries(schema)) {\n if (config.values?.includes(arg)) {\n if (config.exclusive && parsed[key] !== undefined && parsed[key] !== config.default) {\n throw new Error(`Multiple values provided for ${key}: ${parsed[key]} and ${arg}`);\n }\n\n parsed[key] = arg;\n matched = true;\n break;\n }\n\n if (config.prefix && arg.startsWith(config.prefix)) {\n const value = arg.slice(config.prefix.length).trim().toLowerCase();\n\n if (!value) {\n parsed[key] = \"true\";\n matched = true;\n break;\n }\n\n if (config.allowedValues && !config.allowedValues.includes(value)) {\n throw new Error(\n `Invalid value for ${config.prefix}: ${value}. Valid values: ${config.allowedValues.join(\", \")}`\n );\n }\n\n parsed[key] = value;\n matched = true;\n break;\n }\n }\n\n if (!matched && arg.startsWith(\"--\")) {\n unknownArgs.push(arg);\n }\n }\n\n return { parsed, unknownArgs };\n}\n\nexport function displayHelp(\n title: string,\n content: { description?: string; usage?: string[]; options?: string[]; examples?: string[] }\n): never {\n console.log(`\\n${title}\\n`);\n\n if (content.description) {\n console.log(`${content.description}\\n`);\n }\n\n if (content.usage?.length) {\n console.log(\"Usage:\");\n content.usage.forEach((line) => console.log(` ${line}`));\n console.log(\"\");\n }\n\n if (content.options?.length) {\n console.log(\"Options:\");\n content.options.forEach((line) => console.log(` ${line}`));\n console.log(\"\");\n }\n\n if (content.examples?.length) {\n console.log(\"Examples:\");\n content.examples.forEach((line) => console.log(` ${line}`));\n console.log(\"\");\n }\n\n process.exit(0);\n}\n\nexport function exitWithError(message: string, code = 1): never {\n console.error(`❌ ${message}`);\n process.exit(code);\n}\n\nexport function logWarning(message: string): void {\n console.warn(`⚠️ ${message}`);\n}\n\nexport function logInfo(message: string): void {\n console.log(`ℹ️ ${message}`);\n}\n\nexport function logSuccess(message: string): void {\n console.log(`✅ ${message}`);\n}\n","import { getDisplayTimestamp } from \"./export\";\n\ntype Spinner = {\n start: () => Spinner;\n stop: () => Spinner;\n succeed: (message?: string) => Spinner;\n warn: (message?: string) => Spinner;\n fail: (message?: string) => Spinner;\n};\n\ntype ProgressBar = {\n update: (value: number, payload?: Record<string, string>) => void;\n stop: () => void;\n};\n\nconst NOOP_PROGRESS_BAR: ProgressBar = {\n update: () => {},\n stop: () => {},\n};\n\nlet hasWarnedSpinnerFallback = false;\nlet hasWarnedProgressFallback = false;\n\nexport function shouldShowUI(exportMode: string | null, noBanner = false): boolean {\n return !noBanner;\n}\n\nexport function displayBanner(config: {\n text: string;\n subtitle?: string;\n info?: Record<string, string>;\n colors?: string[];\n font?: string;\n}): void {\n const { text, subtitle, info = {}, colors = [\"cyan\"], font = \"block\" } = config;\n\n // Lazy load to avoid breaking non-interactive execution.\n const cfonts = require(\"cfonts\") as {\n render: (message: string, options: Record<string, unknown>) => { string: string };\n };\n const boxenModule = require(\"boxen\") as\n | ((text: string, options: Record<string, unknown>) => string)\n | { default: (text: string, options: Record<string, unknown>) => string };\n const boxen = typeof boxenModule === \"function\" ? boxenModule : boxenModule.default;\n\n const renderedTitle = cfonts.render(text, {\n font,\n colors: [colors[0] ?? \"cyan\"],\n align: \"left\",\n background: \"transparent\",\n letterSpacing: 1,\n lineHeight: 1,\n space: false,\n maxLength: \"0\",\n env: \"node\",\n });\n\n const renderedSubtitle = subtitle\n ? cfonts.render(subtitle, {\n font,\n colors: [colors[1] ?? colors[0] ?? \"cyan\"],\n align: \"left\",\n background: \"transparent\",\n letterSpacing: 1,\n lineHeight: 1,\n space: false,\n maxLength: \"0\",\n env: \"node\",\n })\n : null;\n\n const stripAnsi = (value: string): string => value.replace(/\\x1b\\[[0-9;]*m/g, \"\");\n const centerLines = (lines: string[], width: number): string[] => {\n return lines.map((line) => {\n const visibleLength = stripAnsi(line).length;\n const leftPad = Math.max(0, Math.floor((width - visibleLength) / 2));\n\n return `${\" \".repeat(leftPad)}${line}`;\n });\n };\n\n const titleLines = renderedTitle.string.trimEnd().split(\"\\n\");\n const subtitleLines = renderedSubtitle ? renderedSubtitle.string.trimEnd().split(\"\\n\") : [];\n const centeredWidth = Math.max(\n ...titleLines.map((line) => stripAnsi(line).length),\n ...(subtitleLines.length > 0 ? subtitleLines : [\"\"]).map((line) => stripAnsi(line).length)\n );\n\n const infoLine = Object.entries(info)\n .map(([key, value]) => `${key}: ${value}`)\n .join(\" | \");\n\n const contentLines = [...centerLines(titleLines, centeredWidth)];\n if (subtitleLines.length > 0) {\n contentLines.push(\"\", ...centerLines(subtitleLines, centeredWidth));\n }\n\n contentLines.push(\"\");\n if (infoLine) {\n contentLines.push(` ${infoLine}`);\n }\n contentLines.push(` Date: ${getDisplayTimestamp()}`);\n\n const boxed = boxen(contentLines.join(\"\\n\"), {\n padding: {\n top: 0,\n right: 1,\n bottom: 0,\n left: 1,\n },\n margin: {\n top: 0,\n right: 0,\n bottom: 1,\n left: 0,\n },\n borderStyle: \"round\",\n borderColor: colors[0] ?? \"cyan\",\n });\n\n console.log(boxed);\n}\n\nexport function createSpinner(text: string, color: string = \"cyan\"): Spinner {\n try {\n const ora = require(\"ora\") as (config: Record<string, unknown>) => Spinner;\n\n return ora({ text, color, spinner: \"dots\" });\n } catch {\n if (!hasWarnedSpinnerFallback) {\n hasWarnedSpinnerFallback = true;\n console.warn(\"Warning: spinner UI unavailable, continuing without spinner.\");\n }\n\n return {\n start: () => NOOP_SPINNER,\n stop: () => NOOP_SPINNER,\n succeed: () => NOOP_SPINNER,\n warn: () => NOOP_SPINNER,\n fail: () => NOOP_SPINNER,\n } as Spinner;\n }\n}\n\nconst NOOP_SPINNER: Spinner = {\n start: () => NOOP_SPINNER,\n stop: () => NOOP_SPINNER,\n succeed: () => NOOP_SPINNER,\n warn: () => NOOP_SPINNER,\n fail: () => NOOP_SPINNER,\n};\n\nexport function createProgressBar(total = 100, task = \"Progress\"): ProgressBar {\n if (!hasWarnedProgressFallback) {\n hasWarnedProgressFallback = true;\n console.warn(\n `Warning: progress bar UI is no longer used. Ignoring createProgressBar(${total}, ${JSON.stringify(task)}).`\n );\n }\n\n return NOOP_PROGRESS_BAR;\n}\n","#!/usr/bin/env node\n\nimport { runCoverageContext } from \"../commands/coverage-context\";\n\nrunCoverageContext().catch((error) => {\n console.error(`❌ ${(error as Error).message}`);\n process.exit(1);\n});\n"],"mappings":"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","names":["import_node_path","import_node_child_process","path","import_node_fs","import_node_path","path","path"]}
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runCoverageContext
4
- } from "../chunk-DMN6LBSV.mjs";
5
- import "../chunk-44SYPQVJ.mjs";
4
+ } from "../chunk-TQVH7JRM.mjs";
5
+ import "../chunk-2B6NO7WQ.mjs";
6
6
 
7
7
  // src/bin/coverage-context.ts
8
8
  runCoverageContext().catch((error) => {
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runInitContextScripts
4
- } from "../chunk-54T2WTJJ.mjs";
5
- import "../chunk-44SYPQVJ.mjs";
4
+ } from "../chunk-MRWQAVS4.mjs";
5
+ import "../chunk-2B6NO7WQ.mjs";
6
6
 
7
7
  // src/bin/jest-context-init.ts
8
8
  try {
@@ -426,17 +426,16 @@ function logWarning(message) {
426
426
  // src/core/ui.ts
427
427
  var hasWarnedSpinnerFallback = false;
428
428
  function shouldShowUI(exportMode, noBanner = false) {
429
- return !exportMode && !noBanner && Boolean(process.stdout.isTTY);
429
+ return !noBanner;
430
430
  }
431
431
  function displayBanner(config) {
432
432
  const { text, subtitle, info = {}, colors = ["cyan"], font = "block" } = config;
433
- const bannerText = [text, subtitle].filter(Boolean).join(" ").trim();
434
433
  const cfonts = require("cfonts");
435
434
  const boxenModule = require("boxen");
436
435
  const boxen = typeof boxenModule === "function" ? boxenModule : boxenModule.default;
437
- const renderedBanner = cfonts.render(bannerText, {
436
+ const renderedTitle = cfonts.render(text, {
438
437
  font,
439
- colors,
438
+ colors: [colors[0] ?? "cyan"],
440
439
  align: "left",
441
440
  background: "transparent",
442
441
  letterSpacing: 1,
@@ -445,10 +444,39 @@ function displayBanner(config) {
445
444
  maxLength: "0",
446
445
  env: "node"
447
446
  });
447
+ const renderedSubtitle = subtitle ? cfonts.render(subtitle, {
448
+ font,
449
+ colors: [colors[1] ?? colors[0] ?? "cyan"],
450
+ align: "left",
451
+ background: "transparent",
452
+ letterSpacing: 1,
453
+ lineHeight: 1,
454
+ space: false,
455
+ maxLength: "0",
456
+ env: "node"
457
+ }) : null;
458
+ const stripAnsi2 = (value) => value.replace(/\x1b\[[0-9;]*m/g, "");
459
+ const centerLines = (lines, width) => {
460
+ return lines.map((line) => {
461
+ const visibleLength = stripAnsi2(line).length;
462
+ const leftPad = Math.max(0, Math.floor((width - visibleLength) / 2));
463
+ return `${" ".repeat(leftPad)}${line}`;
464
+ });
465
+ };
466
+ const titleLines = renderedTitle.string.trimEnd().split("\n");
467
+ const subtitleLines = renderedSubtitle ? renderedSubtitle.string.trimEnd().split("\n") : [];
468
+ const centeredWidth = Math.max(
469
+ ...titleLines.map((line) => stripAnsi2(line).length),
470
+ ...(subtitleLines.length > 0 ? subtitleLines : [""]).map((line) => stripAnsi2(line).length)
471
+ );
448
472
  const infoLine = Object.entries(info).map(([key, value]) => `${key}: ${value}`).join(" | ");
449
- const contentLines = [renderedBanner.string.trimEnd()];
473
+ const contentLines = [...centerLines(titleLines, centeredWidth)];
474
+ if (subtitleLines.length > 0) {
475
+ contentLines.push("", ...centerLines(subtitleLines, centeredWidth));
476
+ }
477
+ contentLines.push("");
450
478
  if (infoLine) {
451
- contentLines.push("", ` ${infoLine}`);
479
+ contentLines.push(` ${infoLine}`);
452
480
  }
453
481
  contentLines.push(` Date: ${getDisplayTimestamp()}`);
454
482
  const boxed = boxen(contentLines.join("\n"), {
@@ -496,6 +524,25 @@ var NOOP_SPINNER = {
496
524
  };
497
525
 
498
526
  // src/commands/test-context.ts
527
+ function outputTestContext(content, options) {
528
+ const { exportFormat } = options;
529
+ if (!exportFormat) {
530
+ handleExportOrDisplay(content, {
531
+ exportFormat,
532
+ prefix: "export-test-context",
533
+ title: "Test Context"
534
+ });
535
+ return;
536
+ }
537
+ const exportSpinner = createSpinner("Exporting test context...", "cyan");
538
+ exportSpinner.start();
539
+ handleExportOrDisplay(content, {
540
+ exportFormat,
541
+ prefix: "export-test-context",
542
+ title: "Test Context"
543
+ });
544
+ exportSpinner.succeed("Test context exported");
545
+ }
499
546
  function extractFailures(raw) {
500
547
  const lines = raw.split("\n");
501
548
  const temp = [];
@@ -579,8 +626,8 @@ async function runTestContext(argv = process.argv.slice(2)) {
579
626
  }
580
627
  const modeArg = parsed.mode ?? "--all";
581
628
  const mode = modeArg === "--related" ? "related" : modeArg === "--tests" ? "tests" : "all";
582
- const showUI = shouldShowUI(exportFormat, noBanner);
583
- if (showUI) {
629
+ const showBanner = shouldShowUI(exportFormat, noBanner);
630
+ if (showBanner) {
584
631
  displayBanner({
585
632
  text: "JEST",
586
633
  subtitle: "TEST",
@@ -596,28 +643,22 @@ async function runTestContext(argv = process.argv.slice(2)) {
596
643
  } catch (error) {
597
644
  exitWithError(error.message);
598
645
  }
599
- const spinner = showUI ? createSpinner("Running Jest tests...") : null;
600
- spinner?.start();
646
+ const spinner = createSpinner("Running Jest tests...");
647
+ spinner.start();
601
648
  const result = await runJest(jestArgs, {
602
649
  verbose: true,
603
650
  ignoreErrors: true
604
651
  });
605
652
  const output = stripAnsi(result.output);
606
653
  const hadFailures = output.includes("FAIL") || output.includes("\u25CF");
607
- if (spinner) {
608
- if (hadFailures) {
609
- spinner.warn("Tests completed with failures");
610
- } else {
611
- spinner.succeed("All tests passed!");
612
- }
654
+ if (hadFailures) {
655
+ spinner.warn("Tests completed with failures");
656
+ } else {
657
+ spinner.succeed("All tests passed!");
613
658
  }
614
659
  if (!hadFailures) {
615
660
  const passMessage = "All tests passed!";
616
- handleExportOrDisplay(passMessage, {
617
- exportFormat,
618
- prefix: "export-test-context",
619
- title: "Test Context"
620
- });
661
+ outputTestContext(passMessage, { exportFormat });
621
662
  return;
622
663
  }
623
664
  const failures = extractFailures(output);
@@ -635,11 +676,7 @@ async function runTestContext(argv = process.argv.slice(2)) {
635
676
  lines.push("");
636
677
  }
637
678
  lines.push("=== LLM TEST CONTEXT END ===");
638
- handleExportOrDisplay(lines.join("\n"), {
639
- exportFormat,
640
- prefix: "export-test-context",
641
- title: "Test Context"
642
- });
679
+ outputTestContext(lines.join("\n"), { exportFormat });
643
680
  }
644
681
 
645
682
  // src/bin/test-context.ts
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/constants.ts","../../src/core/platform.ts","../../src/core/exec.ts","../../src/core/git.ts","../../src/core/jest.ts","../../src/core/parsing.ts","../../src/core/export.ts","../../src/core/cli.ts","../../src/core/ui.ts","../../src/commands/test-context.ts","../../src/bin/test-context.ts"],"sourcesContent":["export const VALID_MODES = [\"--all\", \"--related\", \"--tests\"] as const;\n\nexport const VALID_EXPORT_FORMATS = [\"txt\", \"md\"] as const;\n\nexport const VALID_TEST_EXTENSIONS = /\\.(test|spec)\\.(ts|tsx|js|jsx)$/;\n\nexport const CONSOLE_LOG_TYPES = {\n ERROR: \"console.error\",\n WARN: \"console.warn\",\n LOG: \"console.log\",\n DEBUG: \"console.debug\",\n} as const;\n\nexport const JEST_PATTERNS = {\n FAIL_LINE: /^FAIL\\s+/,\n PASS_LINE: /^PASS\\s+/,\n TEST_FILE: /^(PASS|FAIL)\\s+(.+\\.(test|spec)\\.tsx?)/,\n COVERAGE_LINE:\n /^(.+?)\\s+\\|\\s+([\\d.]+)\\s+\\|\\s+([\\d.]+)\\s+\\|\\s+([\\d.]+)\\s+\\|\\s+([\\d.]+)(?:\\s+\\|\\s+(.+))?$/,\n BULLET_POINT: /^●\\s+/,\n CODE_LINE: /^>?\\s*\\d*\\s*\\|/,\n STACK_TRACE: /^\\s+at\\s+/,\n};\n","export function getPlatform(): NodeJS.Platform {\n return process.platform;\n}\n\nexport function isWindows(): boolean {\n return process.platform === \"win32\";\n}\n\nexport function isMac(): boolean {\n return process.platform === \"darwin\";\n}\n\nexport function isLinux(): boolean {\n return process.platform === \"linux\";\n}\n\nexport function resolveCommand(cmd: string): string {\n if (!isWindows()) return cmd;\n\n const windowsCommands: Record<string, string> = {\n git: \"git.exe\",\n node: \"node.exe\",\n npm: \"npm.cmd\",\n npx: \"npx.cmd\",\n yarn: \"yarn.cmd\",\n pnpm: \"pnpm.cmd\",\n };\n\n return windowsCommands[cmd] ?? cmd;\n}\n","import { spawn } from \"node:child_process\";\n\nimport { resolveCommand } from \"./platform\";\nimport type { ExecResult } from \"../types\";\n\nexport async function execCommand(\n cmd: string,\n args: string[] = [],\n options: { shell?: boolean; ignoreErrors?: boolean } = {}\n): Promise<ExecResult> {\n return new Promise((resolve, reject) => {\n const resolvedCmd = resolveCommand(cmd);\n const child = spawn(resolvedCmd, args, {\n shell: options.shell ?? false,\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n child.stdout?.on(\"data\", (d) => {\n stdout += d.toString();\n });\n\n child.stderr?.on(\"data\", (d) => {\n stderr += d.toString();\n });\n\n child.on(\"close\", (code) => {\n const result: ExecResult = {\n stdout,\n stderr,\n output: `${stdout}\\n${stderr}`,\n code,\n };\n\n if (code !== 0 && !options.ignoreErrors) {\n reject(new Error(`Command failed with code ${code}: ${cmd} ${args.join(\" \")}`));\n return;\n }\n\n resolve(result);\n });\n\n child.on(\"error\", (error) => {\n reject(new Error(`Failed to execute command: ${error.message}`));\n });\n });\n}\n","import { execCommand } from \"./exec\";\nimport { VALID_TEST_EXTENSIONS } from \"./constants\";\n\nlet cachedGitAvailability: boolean | null = null;\nlet cachedStagedFiles: string[] | null = null;\nlet cachedStagedFilesAt = 0;\nconst STAGED_FILES_CACHE_TTL_MS = 1000;\n\nexport async function hasGit(): Promise<boolean> {\n if (cachedGitAvailability !== null) {\n return cachedGitAvailability;\n }\n\n try {\n const result = await execCommand(\"git\", [\"--version\"], { ignoreErrors: true });\n cachedGitAvailability = result.code === 0;\n\n return cachedGitAvailability;\n } catch {\n cachedGitAvailability = false;\n\n return false;\n }\n}\n\nexport async function getStagedFiles(): Promise<string[]> {\n const now = Date.now();\n if (cachedStagedFiles && now - cachedStagedFilesAt <= STAGED_FILES_CACHE_TTL_MS) {\n return cachedStagedFiles;\n }\n\n const gitAvailable = await hasGit();\n if (!gitAvailable) {\n throw new Error(\"Git is not installed or not available in PATH\");\n }\n\n const result = await execCommand(\"git\", [\"diff\", \"--name-only\", \"--cached\"], {\n ignoreErrors: true,\n });\n\n const files = result.stdout\n .split(\"\\n\")\n .map((f) => f.trim())\n .filter(Boolean);\n\n cachedStagedFiles = files;\n cachedStagedFilesAt = now;\n\n return files;\n}\n\nexport function filterTestFiles(files: string[]): string[] {\n return files.filter((file) => VALID_TEST_EXTENSIONS.test(file));\n}\n","import { spawn } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\nimport { isWindows } from \"./platform\";\nimport { filterTestFiles, getStagedFiles } from \"./git\";\nimport type { ExecutionMode, ExecResult, RunJestOptions } from \"../types\";\n\ntype ResolvedJestRunner = {\n command: string;\n argsPrefix: string[];\n};\n\nfunction resolveJestRunner(): ResolvedJestRunner {\n const cwd = process.cwd();\n const attempts: string[] = [];\n\n try {\n const jestPackageJsonPath = require.resolve(\"jest/package.json\", { paths: [cwd] });\n attempts.push(`Resolved jest package: ${jestPackageJsonPath}`);\n\n const jestPackageDir = path.dirname(jestPackageJsonPath);\n const jestPackage = JSON.parse(readFileSync(jestPackageJsonPath, \"utf-8\")) as {\n bin?: string | Record<string, string>;\n };\n\n const binField = jestPackage.bin;\n let binEntry: string | undefined;\n if (typeof binField === \"string\") {\n binEntry = binField;\n } else if (binField && typeof binField === \"object\") {\n binEntry = binField.jest ?? Object.values(binField)[0];\n }\n\n if (binEntry) {\n const binPath = path.resolve(jestPackageDir, binEntry);\n if (existsSync(binPath)) {\n return {\n command: process.execPath,\n argsPrefix: [binPath],\n };\n }\n attempts.push(`Jest bin from package.json not found: ${binPath}`);\n } else {\n attempts.push(\"Jest package.json has no usable bin field.\");\n }\n } catch {\n attempts.push(\"Could not resolve jest/package.json from current cwd.\");\n }\n\n try {\n const legacyBinPath = require.resolve(\"jest/bin/jest.js\", { paths: [cwd] });\n attempts.push(`Resolved legacy jest bin: ${legacyBinPath}`);\n return {\n command: process.execPath,\n argsPrefix: [legacyBinPath],\n };\n } catch {\n attempts.push(\"Could not resolve legacy path jest/bin/jest.js.\");\n }\n\n const localBinPath = path.resolve(cwd, \"node_modules\", \".bin\", isWindows() ? \"jest.cmd\" : \"jest\");\n if (existsSync(localBinPath)) {\n attempts.push(`Resolved local .bin executable: ${localBinPath}`);\n return {\n command: localBinPath,\n argsPrefix: [],\n };\n }\n attempts.push(`Local .bin executable not found: ${localBinPath}`);\n\n throw new Error(\n [\n \"Could not resolve Jest from the current project.\",\n \"Install `jest@^29` in the package where you run this command.\",\n \"Examples: `npm i -D jest@^29`, `pnpm add -D jest@^29`, `yarn add -D jest@^29`.\",\n `cwd: ${cwd}`,\n ...attempts,\n ].join(\"\\n\")\n );\n}\n\nexport async function runJest(args: string[] = [], options: RunJestOptions = {}): Promise<ExecResult> {\n const {\n verbose = false,\n coverage = false,\n ignoreErrors = true,\n disableVerbose = false,\n } = options;\n\n const runner = resolveJestRunner();\n const command = runner.command;\n const jestArgs = [...runner.argsPrefix];\n\n if (verbose && !disableVerbose) {\n jestArgs.push(\"--verbose\");\n }\n\n if (coverage) {\n jestArgs.push(\"--coverage\");\n\n if (options.coverageReporters) {\n for (const reporter of options.coverageReporters) {\n jestArgs.push(`--coverageReporters=${reporter}`);\n }\n }\n }\n\n if (isWindows()) {\n jestArgs.push(\"--no-watchman\");\n }\n\n jestArgs.push(...args);\n\n return new Promise((resolve, reject) => {\n const child = spawn(command, jestArgs, {\n shell: false,\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n child.stdout.on(\"data\", (d) => {\n stdout += d.toString();\n });\n\n child.stderr.on(\"data\", (d) => {\n stderr += d.toString();\n });\n\n child.on(\"close\", (code) => {\n const result: ExecResult = {\n stdout,\n stderr,\n output: `${stdout}\\n${stderr}`,\n code,\n };\n\n if (code !== 0 && !ignoreErrors) {\n reject(new Error(`Jest failed with code ${code}`));\n return;\n }\n\n resolve(result);\n });\n\n child.on(\"error\", reject);\n });\n}\n\nexport async function buildJestArgsForMode(mode: ExecutionMode): Promise<string[]> {\n if (mode === \"all\") {\n return [];\n }\n\n const staged = await getStagedFiles();\n if (staged.length === 0) {\n throw new Error(`No staged files found for mode: ${mode}`);\n }\n\n if (mode === \"tests\") {\n const testFiles = filterTestFiles(staged);\n if (testFiles.length === 0) {\n throw new Error(\"No test files found in staged files\");\n }\n\n return testFiles;\n }\n\n return [\"--findRelatedTests\", ...staged];\n}\n","import { CONSOLE_LOG_TYPES, JEST_PATTERNS } from \"./constants\";\n\nexport function stripAnsi(text: string): string {\n return text.replace(/\\x1b\\[[0-9;]*m/g, \"\");\n}\n\nexport function isCodeSnippetLine(line: string): boolean {\n return JEST_PATTERNS.CODE_LINE.test(stripAnsi(line).trim());\n}\n\nexport function isStackTraceLine(line: string): boolean {\n return JEST_PATTERNS.STACK_TRACE.test(stripAnsi(line));\n}\n\nexport function isConsoleTypeLine(line: string): boolean {\n const clean = stripAnsi(line).trim();\n return Object.values(CONSOLE_LOG_TYPES).includes(clean as (typeof CONSOLE_LOG_TYPES)[keyof typeof CONSOLE_LOG_TYPES]);\n}\n\nexport function extractConsoleType(line: string): string | null {\n const clean = stripAnsi(line).trim();\n return Object.values(CONSOLE_LOG_TYPES).find((type) => type === clean) ?? null;\n}\n","import { writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\nimport { VALID_EXPORT_FORMATS } from \"./constants\";\nimport type { ExportFormat, OutputOptions } from \"../types\";\n\nexport function getDisplayTimestamp(locale = \"en-US\"): string {\n return new Date().toLocaleString(locale, {\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: false,\n });\n}\n\nexport function getFilenameTimestamp(): string {\n const now = new Date();\n const pad = (value: number) => String(value).padStart(2, \"0\");\n\n return (\n [now.getFullYear(), pad(now.getMonth() + 1), pad(now.getDate())].join(\"-\") +\n \"_\" +\n [pad(now.getHours()), pad(now.getMinutes()), pad(now.getSeconds())].join(\"-\")\n );\n}\n\nexport function buildTimestampedPath(prefix: string, extension: string, dir = process.cwd()): string {\n const timestamp = getFilenameTimestamp();\n const filename = `${prefix}-${timestamp}.${extension}`;\n\n return path.resolve(dir, filename);\n}\n\nexport function formatAsMarkdown(content: string, title: string, timestamp: string | null = null): string {\n const lines = [`# ${title}`, \"\"];\n\n if (timestamp) {\n lines.push(`Generated: ${timestamp}`, \"\");\n }\n\n lines.push(\"```text\", content.trimEnd(), \"```\", \"\");\n\n return lines.join(\"\\n\");\n}\n\nexport function exportToFile(\n content: string,\n options: { prefix: string; format: ExportFormat; title?: string; dir?: string }\n): string {\n const { prefix, format, title, dir = process.cwd() } = options;\n const filePath = buildTimestampedPath(prefix, format, dir);\n\n let finalContent = content;\n if (format === \"md\" && title) {\n finalContent = formatAsMarkdown(content, title, getDisplayTimestamp());\n }\n\n writeFileSync(filePath, finalContent, \"utf-8\");\n\n return filePath;\n}\n\nexport function parseExportCliArgs(args: string[]): { exportFormat: ExportFormat | null; exportArgs: string[] } {\n let exportFormat: ExportFormat | null = null;\n const exportArgs: string[] = [];\n\n for (const arg of args) {\n if (arg === \"--export\") {\n exportFormat = \"txt\";\n exportArgs.push(arg);\n continue;\n }\n\n if (!arg.startsWith(\"--export=\")) {\n continue;\n }\n\n const value = arg.slice(\"--export=\".length).trim().toLowerCase();\n if (!value || !VALID_EXPORT_FORMATS.includes(value as ExportFormat)) {\n throw new Error(`Invalid value for --export: ${value || \"(empty)\"}. Valid values: txt, md`);\n }\n\n exportFormat = value as ExportFormat;\n exportArgs.push(arg);\n }\n\n return { exportFormat, exportArgs };\n}\n\nexport function handleExportOrDisplay(content: string, config: OutputOptions): string | null {\n const { exportFormat, prefix, title } = config;\n\n if (!exportFormat) {\n console.log(content);\n\n return null;\n }\n\n const outputPath = exportToFile(content, {\n prefix,\n format: exportFormat,\n title,\n });\n\n console.log(`Output exported to: ${outputPath}`);\n\n return outputPath;\n}\n","type SchemaEntry = {\n values?: string[];\n default?: string;\n exclusive?: boolean;\n prefix?: string;\n allowedValues?: string[];\n};\n\nexport function validateCliArgs(\n args: string[],\n schema: Record<string, SchemaEntry>\n): { parsed: Record<string, string | undefined>; unknownArgs: string[] } {\n const parsed: Record<string, string | undefined> = {};\n const unknownArgs: string[] = [];\n\n for (const [key, config] of Object.entries(schema)) {\n if (config.default !== undefined) {\n parsed[key] = config.default;\n }\n }\n\n for (const arg of args) {\n let matched = false;\n\n for (const [key, config] of Object.entries(schema)) {\n if (config.values?.includes(arg)) {\n if (config.exclusive && parsed[key] !== undefined && parsed[key] !== config.default) {\n throw new Error(`Multiple values provided for ${key}: ${parsed[key]} and ${arg}`);\n }\n\n parsed[key] = arg;\n matched = true;\n break;\n }\n\n if (config.prefix && arg.startsWith(config.prefix)) {\n const value = arg.slice(config.prefix.length).trim().toLowerCase();\n\n if (!value) {\n parsed[key] = \"true\";\n matched = true;\n break;\n }\n\n if (config.allowedValues && !config.allowedValues.includes(value)) {\n throw new Error(\n `Invalid value for ${config.prefix}: ${value}. Valid values: ${config.allowedValues.join(\", \")}`\n );\n }\n\n parsed[key] = value;\n matched = true;\n break;\n }\n }\n\n if (!matched && arg.startsWith(\"--\")) {\n unknownArgs.push(arg);\n }\n }\n\n return { parsed, unknownArgs };\n}\n\nexport function displayHelp(\n title: string,\n content: { description?: string; usage?: string[]; options?: string[]; examples?: string[] }\n): never {\n console.log(`\\n${title}\\n`);\n\n if (content.description) {\n console.log(`${content.description}\\n`);\n }\n\n if (content.usage?.length) {\n console.log(\"Usage:\");\n content.usage.forEach((line) => console.log(` ${line}`));\n console.log(\"\");\n }\n\n if (content.options?.length) {\n console.log(\"Options:\");\n content.options.forEach((line) => console.log(` ${line}`));\n console.log(\"\");\n }\n\n if (content.examples?.length) {\n console.log(\"Examples:\");\n content.examples.forEach((line) => console.log(` ${line}`));\n console.log(\"\");\n }\n\n process.exit(0);\n}\n\nexport function exitWithError(message: string, code = 1): never {\n console.error(`❌ ${message}`);\n process.exit(code);\n}\n\nexport function logWarning(message: string): void {\n console.warn(`⚠️ ${message}`);\n}\n\nexport function logInfo(message: string): void {\n console.log(`ℹ️ ${message}`);\n}\n\nexport function logSuccess(message: string): void {\n console.log(`✅ ${message}`);\n}\n","import { getDisplayTimestamp } from \"./export\";\n\ntype Spinner = {\n start: () => Spinner;\n stop: () => Spinner;\n succeed: (message?: string) => Spinner;\n warn: (message?: string) => Spinner;\n fail: (message?: string) => Spinner;\n};\n\ntype ProgressBar = {\n update: (value: number, payload?: Record<string, string>) => void;\n stop: () => void;\n};\n\nconst NOOP_PROGRESS_BAR: ProgressBar = {\n update: () => {},\n stop: () => {},\n};\n\nlet hasWarnedSpinnerFallback = false;\nlet hasWarnedProgressFallback = false;\n\nexport function shouldShowUI(exportMode: string | null, noBanner = false): boolean {\n return !exportMode && !noBanner && Boolean(process.stdout.isTTY);\n}\n\nexport function displayBanner(config: {\n text: string;\n subtitle?: string;\n info?: Record<string, string>;\n colors?: string[];\n font?: string;\n}): void {\n const { text, subtitle, info = {}, colors = [\"cyan\"], font = \"block\" } = config;\n const bannerText = [text, subtitle].filter(Boolean).join(\" \").trim();\n\n // Lazy load to avoid breaking non-interactive execution.\n const cfonts = require(\"cfonts\") as {\n render: (message: string, options: Record<string, unknown>) => { string: string };\n };\n const boxenModule = require(\"boxen\") as\n | ((text: string, options: Record<string, unknown>) => string)\n | { default: (text: string, options: Record<string, unknown>) => string };\n const boxen = typeof boxenModule === \"function\" ? boxenModule : boxenModule.default;\n\n const renderedBanner = cfonts.render(bannerText, {\n font,\n colors,\n align: \"left\",\n background: \"transparent\",\n letterSpacing: 1,\n lineHeight: 1,\n space: false,\n maxLength: \"0\",\n env: \"node\",\n });\n\n const infoLine = Object.entries(info)\n .map(([key, value]) => `${key}: ${value}`)\n .join(\" | \");\n\n const contentLines = [renderedBanner.string.trimEnd()];\n if (infoLine) {\n contentLines.push(\"\", ` ${infoLine}`);\n }\n contentLines.push(` Date: ${getDisplayTimestamp()}`);\n\n const boxed = boxen(contentLines.join(\"\\n\"), {\n padding: {\n top: 0,\n right: 1,\n bottom: 0,\n left: 1,\n },\n margin: {\n top: 0,\n right: 0,\n bottom: 1,\n left: 0,\n },\n borderStyle: \"round\",\n borderColor: colors[0] ?? \"cyan\",\n });\n\n console.log(boxed);\n}\n\nexport function createSpinner(text: string, color: string = \"cyan\"): Spinner {\n try {\n const ora = require(\"ora\") as (config: Record<string, unknown>) => Spinner;\n\n return ora({ text, color, spinner: \"dots\" });\n } catch {\n if (!hasWarnedSpinnerFallback) {\n hasWarnedSpinnerFallback = true;\n console.warn(\"Warning: spinner UI unavailable, continuing without spinner.\");\n }\n\n return {\n start: () => NOOP_SPINNER,\n stop: () => NOOP_SPINNER,\n succeed: () => NOOP_SPINNER,\n warn: () => NOOP_SPINNER,\n fail: () => NOOP_SPINNER,\n } as Spinner;\n }\n}\n\nconst NOOP_SPINNER: Spinner = {\n start: () => NOOP_SPINNER,\n stop: () => NOOP_SPINNER,\n succeed: () => NOOP_SPINNER,\n warn: () => NOOP_SPINNER,\n fail: () => NOOP_SPINNER,\n};\n\nexport function createProgressBar(total = 100, task = \"Progress\"): ProgressBar {\n if (!hasWarnedProgressFallback) {\n hasWarnedProgressFallback = true;\n console.warn(\n `Warning: progress bar UI is no longer used. Ignoring createProgressBar(${total}, ${JSON.stringify(task)}).`\n );\n }\n\n return NOOP_PROGRESS_BAR;\n}\n","import {\n buildJestArgsForMode,\n displayBanner,\n exitWithError,\n extractConsoleType,\n handleExportOrDisplay,\n JEST_PATTERNS,\n parseExportCliArgs,\n runJest,\n shouldShowUI,\n stripAnsi,\n validateCliArgs,\n VALID_MODES,\n createSpinner,\n displayHelp,\n logWarning,\n} from \"../core\";\n\ntype FailureBlock = {\n file: string;\n tests: string[];\n};\n\nexport function extractFailures(raw: string): FailureBlock[] {\n const lines = raw.split(\"\\n\");\n const temp: FailureBlock[] = [];\n let current: FailureBlock | null = null;\n\n for (const line of lines) {\n if (JEST_PATTERNS.FAIL_LINE.test(line)) {\n if (current) {\n temp.push(current);\n }\n current = {\n file: line.replace(\"FAIL \", \"\").trim(),\n tests: [],\n };\n continue;\n }\n\n if (JEST_PATTERNS.BULLET_POINT.test(line.trim())) {\n current?.tests.push(line.trim().slice(1).trim());\n }\n }\n\n if (current) {\n temp.push(current);\n }\n\n const merged: Record<string, FailureBlock> = {};\n for (const item of temp) {\n if (!merged[item.file]) {\n merged[item.file] = {\n file: item.file,\n tests: [],\n };\n }\n merged[item.file].tests.push(...item.tests);\n }\n\n for (const value of Object.values(merged)) {\n value.tests = Array.from(new Set(value.tests));\n }\n\n return Object.values(merged);\n}\n\nexport async function runTestContext(argv = process.argv.slice(2)): Promise<void> {\n if (argv.includes(\"-h\") || argv.includes(\"--help\")) {\n displayHelp(\"Test Context Script\", {\n description: \"Run Jest and print failures in LLM-friendly format.\",\n usage: [\n \"test-context -- --all\",\n \"test-context -- --related\",\n \"test-context -- --tests\",\n ],\n options: [\n \"--all Run all tests (default)\",\n \"--related Run tests related to staged files\",\n \"--tests Run only staged test files\",\n \"--export Export output as txt\",\n \"--export=txt|md Export output in selected format\",\n \"--no-banner Disable fancy terminal UI\",\n \"-h, --help Show this help\",\n ],\n examples: [\"test-context -- --related --export=md\"],\n });\n }\n\n const noBanner = argv.includes(\"--no-banner\");\n const args = argv.filter((arg) => arg !== \"--no-banner\");\n\n let exportFormat: \"txt\" | \"md\" | null;\n let exportArgs: string[];\n let parsed: Record<string, string | undefined>;\n let unknownArgs: string[];\n\n try {\n ({ exportFormat, exportArgs } = parseExportCliArgs(args));\n ({ parsed, unknownArgs } = validateCliArgs(args, {\n mode: {\n values: [...VALID_MODES],\n default: \"--all\",\n exclusive: true,\n },\n }));\n } catch (error) {\n exitWithError((error as Error).message);\n }\n\n const exportArgSet = new Set(exportArgs);\n const filteredUnknownArgs = unknownArgs.filter((arg) => !exportArgSet.has(arg));\n if (filteredUnknownArgs.length > 0) {\n logWarning(`Unknown arguments ignored: ${filteredUnknownArgs.join(\", \")}`);\n }\n\n const modeArg = parsed.mode ?? \"--all\";\n const mode = modeArg === \"--related\" ? \"related\" : modeArg === \"--tests\" ? \"tests\" : \"all\";\n\n const showUI = shouldShowUI(exportFormat, noBanner);\n if (showUI) {\n displayBanner({\n text: \"JEST\",\n subtitle: \"TEST\",\n info: {\n Mode: mode,\n },\n colors: [\"cyan\", \"blue\"],\n });\n }\n\n let jestArgs: string[] = [];\n try {\n jestArgs = await buildJestArgsForMode(mode);\n } catch (error) {\n exitWithError((error as Error).message);\n }\n\n const spinner = showUI ? createSpinner(\"Running Jest tests...\") : null;\n spinner?.start();\n\n const result = await runJest(jestArgs, {\n verbose: true,\n ignoreErrors: true,\n });\n\n const output = stripAnsi(result.output);\n const hadFailures = output.includes(\"FAIL\") || output.includes(\"●\");\n\n if (spinner) {\n if (hadFailures) {\n spinner.warn(\"Tests completed with failures\");\n } else {\n spinner.succeed(\"All tests passed!\");\n }\n }\n\n if (!hadFailures) {\n const passMessage = \"All tests passed!\";\n handleExportOrDisplay(passMessage, {\n exportFormat,\n prefix: \"export-test-context\",\n title: \"Test Context\",\n });\n\n return;\n }\n\n const failures = extractFailures(output);\n const lines = [\"=== LLM TEST CONTEXT BEGIN ===\", \"\"];\n\n if (failures.length === 0) {\n lines.push(\"No test failures could be parsed from Jest output.\");\n lines.push(\"This may happen if Jest failed before running tests.\", \"\");\n }\n\n for (const fail of failures) {\n lines.push(`File: ${fail.file}`);\n lines.push(\"Failures:\");\n for (const test of fail.tests) {\n lines.push(`- ${test}`);\n }\n lines.push(\"\");\n }\n\n lines.push(\"=== LLM TEST CONTEXT END ===\");\n\n handleExportOrDisplay(lines.join(\"\\n\"), {\n exportFormat,\n prefix: \"export-test-context\",\n title: \"Test Context\",\n });\n}\n","#!/usr/bin/env node\n\nimport { runTestContext } from \"../commands/test-context\";\n\nrunTestContext().catch((error) => {\n console.error(`❌ ${(error as Error).message}`);\n process.exit(1);\n});\n"],"mappings":"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","names":["import_node_child_process","path","import_node_fs","import_node_path","path"]}
1
+ {"version":3,"sources":["../../src/core/constants.ts","../../src/core/platform.ts","../../src/core/exec.ts","../../src/core/git.ts","../../src/core/jest.ts","../../src/core/parsing.ts","../../src/core/export.ts","../../src/core/cli.ts","../../src/core/ui.ts","../../src/commands/test-context.ts","../../src/bin/test-context.ts"],"sourcesContent":["export const VALID_MODES = [\"--all\", \"--related\", \"--tests\"] as const;\n\nexport const VALID_EXPORT_FORMATS = [\"txt\", \"md\"] as const;\n\nexport const VALID_TEST_EXTENSIONS = /\\.(test|spec)\\.(ts|tsx|js|jsx)$/;\n\nexport const CONSOLE_LOG_TYPES = {\n ERROR: \"console.error\",\n WARN: \"console.warn\",\n LOG: \"console.log\",\n DEBUG: \"console.debug\",\n} as const;\n\nexport const JEST_PATTERNS = {\n FAIL_LINE: /^FAIL\\s+/,\n PASS_LINE: /^PASS\\s+/,\n TEST_FILE: /^(PASS|FAIL)\\s+(.+\\.(test|spec)\\.tsx?)/,\n COVERAGE_LINE:\n /^(.+?)\\s+\\|\\s+([\\d.]+)\\s+\\|\\s+([\\d.]+)\\s+\\|\\s+([\\d.]+)\\s+\\|\\s+([\\d.]+)(?:\\s+\\|\\s+(.+))?$/,\n BULLET_POINT: /^●\\s+/,\n CODE_LINE: /^>?\\s*\\d*\\s*\\|/,\n STACK_TRACE: /^\\s+at\\s+/,\n};\n","export function getPlatform(): NodeJS.Platform {\n return process.platform;\n}\n\nexport function isWindows(): boolean {\n return process.platform === \"win32\";\n}\n\nexport function isMac(): boolean {\n return process.platform === \"darwin\";\n}\n\nexport function isLinux(): boolean {\n return process.platform === \"linux\";\n}\n\nexport function resolveCommand(cmd: string): string {\n if (!isWindows()) return cmd;\n\n const windowsCommands: Record<string, string> = {\n git: \"git.exe\",\n node: \"node.exe\",\n npm: \"npm.cmd\",\n npx: \"npx.cmd\",\n yarn: \"yarn.cmd\",\n pnpm: \"pnpm.cmd\",\n };\n\n return windowsCommands[cmd] ?? cmd;\n}\n","import { spawn } from \"node:child_process\";\n\nimport { resolveCommand } from \"./platform\";\nimport type { ExecResult } from \"../types\";\n\nexport async function execCommand(\n cmd: string,\n args: string[] = [],\n options: { shell?: boolean; ignoreErrors?: boolean } = {}\n): Promise<ExecResult> {\n return new Promise((resolve, reject) => {\n const resolvedCmd = resolveCommand(cmd);\n const child = spawn(resolvedCmd, args, {\n shell: options.shell ?? false,\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n child.stdout?.on(\"data\", (d) => {\n stdout += d.toString();\n });\n\n child.stderr?.on(\"data\", (d) => {\n stderr += d.toString();\n });\n\n child.on(\"close\", (code) => {\n const result: ExecResult = {\n stdout,\n stderr,\n output: `${stdout}\\n${stderr}`,\n code,\n };\n\n if (code !== 0 && !options.ignoreErrors) {\n reject(new Error(`Command failed with code ${code}: ${cmd} ${args.join(\" \")}`));\n return;\n }\n\n resolve(result);\n });\n\n child.on(\"error\", (error) => {\n reject(new Error(`Failed to execute command: ${error.message}`));\n });\n });\n}\n","import { execCommand } from \"./exec\";\nimport { VALID_TEST_EXTENSIONS } from \"./constants\";\n\nlet cachedGitAvailability: boolean | null = null;\nlet cachedStagedFiles: string[] | null = null;\nlet cachedStagedFilesAt = 0;\nconst STAGED_FILES_CACHE_TTL_MS = 1000;\n\nexport async function hasGit(): Promise<boolean> {\n if (cachedGitAvailability !== null) {\n return cachedGitAvailability;\n }\n\n try {\n const result = await execCommand(\"git\", [\"--version\"], { ignoreErrors: true });\n cachedGitAvailability = result.code === 0;\n\n return cachedGitAvailability;\n } catch {\n cachedGitAvailability = false;\n\n return false;\n }\n}\n\nexport async function getStagedFiles(): Promise<string[]> {\n const now = Date.now();\n if (cachedStagedFiles && now - cachedStagedFilesAt <= STAGED_FILES_CACHE_TTL_MS) {\n return cachedStagedFiles;\n }\n\n const gitAvailable = await hasGit();\n if (!gitAvailable) {\n throw new Error(\"Git is not installed or not available in PATH\");\n }\n\n const result = await execCommand(\"git\", [\"diff\", \"--name-only\", \"--cached\"], {\n ignoreErrors: true,\n });\n\n const files = result.stdout\n .split(\"\\n\")\n .map((f) => f.trim())\n .filter(Boolean);\n\n cachedStagedFiles = files;\n cachedStagedFilesAt = now;\n\n return files;\n}\n\nexport function filterTestFiles(files: string[]): string[] {\n return files.filter((file) => VALID_TEST_EXTENSIONS.test(file));\n}\n","import { spawn } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\nimport { isWindows } from \"./platform\";\nimport { filterTestFiles, getStagedFiles } from \"./git\";\nimport type { ExecutionMode, ExecResult, RunJestOptions } from \"../types\";\n\ntype ResolvedJestRunner = {\n command: string;\n argsPrefix: string[];\n};\n\nfunction resolveJestRunner(): ResolvedJestRunner {\n const cwd = process.cwd();\n const attempts: string[] = [];\n\n try {\n const jestPackageJsonPath = require.resolve(\"jest/package.json\", { paths: [cwd] });\n attempts.push(`Resolved jest package: ${jestPackageJsonPath}`);\n\n const jestPackageDir = path.dirname(jestPackageJsonPath);\n const jestPackage = JSON.parse(readFileSync(jestPackageJsonPath, \"utf-8\")) as {\n bin?: string | Record<string, string>;\n };\n\n const binField = jestPackage.bin;\n let binEntry: string | undefined;\n if (typeof binField === \"string\") {\n binEntry = binField;\n } else if (binField && typeof binField === \"object\") {\n binEntry = binField.jest ?? Object.values(binField)[0];\n }\n\n if (binEntry) {\n const binPath = path.resolve(jestPackageDir, binEntry);\n if (existsSync(binPath)) {\n return {\n command: process.execPath,\n argsPrefix: [binPath],\n };\n }\n attempts.push(`Jest bin from package.json not found: ${binPath}`);\n } else {\n attempts.push(\"Jest package.json has no usable bin field.\");\n }\n } catch {\n attempts.push(\"Could not resolve jest/package.json from current cwd.\");\n }\n\n try {\n const legacyBinPath = require.resolve(\"jest/bin/jest.js\", { paths: [cwd] });\n attempts.push(`Resolved legacy jest bin: ${legacyBinPath}`);\n return {\n command: process.execPath,\n argsPrefix: [legacyBinPath],\n };\n } catch {\n attempts.push(\"Could not resolve legacy path jest/bin/jest.js.\");\n }\n\n const localBinPath = path.resolve(cwd, \"node_modules\", \".bin\", isWindows() ? \"jest.cmd\" : \"jest\");\n if (existsSync(localBinPath)) {\n attempts.push(`Resolved local .bin executable: ${localBinPath}`);\n return {\n command: localBinPath,\n argsPrefix: [],\n };\n }\n attempts.push(`Local .bin executable not found: ${localBinPath}`);\n\n throw new Error(\n [\n \"Could not resolve Jest from the current project.\",\n \"Install `jest@^29` in the package where you run this command.\",\n \"Examples: `npm i -D jest@^29`, `pnpm add -D jest@^29`, `yarn add -D jest@^29`.\",\n `cwd: ${cwd}`,\n ...attempts,\n ].join(\"\\n\")\n );\n}\n\nexport async function runJest(args: string[] = [], options: RunJestOptions = {}): Promise<ExecResult> {\n const {\n verbose = false,\n coverage = false,\n ignoreErrors = true,\n disableVerbose = false,\n } = options;\n\n const runner = resolveJestRunner();\n const command = runner.command;\n const jestArgs = [...runner.argsPrefix];\n\n if (verbose && !disableVerbose) {\n jestArgs.push(\"--verbose\");\n }\n\n if (coverage) {\n jestArgs.push(\"--coverage\");\n\n if (options.coverageReporters) {\n for (const reporter of options.coverageReporters) {\n jestArgs.push(`--coverageReporters=${reporter}`);\n }\n }\n }\n\n if (isWindows()) {\n jestArgs.push(\"--no-watchman\");\n }\n\n jestArgs.push(...args);\n\n return new Promise((resolve, reject) => {\n const child = spawn(command, jestArgs, {\n shell: false,\n });\n\n let stdout = \"\";\n let stderr = \"\";\n\n child.stdout.on(\"data\", (d) => {\n stdout += d.toString();\n });\n\n child.stderr.on(\"data\", (d) => {\n stderr += d.toString();\n });\n\n child.on(\"close\", (code) => {\n const result: ExecResult = {\n stdout,\n stderr,\n output: `${stdout}\\n${stderr}`,\n code,\n };\n\n if (code !== 0 && !ignoreErrors) {\n reject(new Error(`Jest failed with code ${code}`));\n return;\n }\n\n resolve(result);\n });\n\n child.on(\"error\", reject);\n });\n}\n\nexport async function buildJestArgsForMode(mode: ExecutionMode): Promise<string[]> {\n if (mode === \"all\") {\n return [];\n }\n\n const staged = await getStagedFiles();\n if (staged.length === 0) {\n throw new Error(`No staged files found for mode: ${mode}`);\n }\n\n if (mode === \"tests\") {\n const testFiles = filterTestFiles(staged);\n if (testFiles.length === 0) {\n throw new Error(\"No test files found in staged files\");\n }\n\n return testFiles;\n }\n\n return [\"--findRelatedTests\", ...staged];\n}\n","import { CONSOLE_LOG_TYPES, JEST_PATTERNS } from \"./constants\";\n\nexport function stripAnsi(text: string): string {\n return text.replace(/\\x1b\\[[0-9;]*m/g, \"\");\n}\n\nexport function isCodeSnippetLine(line: string): boolean {\n return JEST_PATTERNS.CODE_LINE.test(stripAnsi(line).trim());\n}\n\nexport function isStackTraceLine(line: string): boolean {\n return JEST_PATTERNS.STACK_TRACE.test(stripAnsi(line));\n}\n\nexport function isConsoleTypeLine(line: string): boolean {\n const clean = stripAnsi(line).trim();\n return Object.values(CONSOLE_LOG_TYPES).includes(clean as (typeof CONSOLE_LOG_TYPES)[keyof typeof CONSOLE_LOG_TYPES]);\n}\n\nexport function extractConsoleType(line: string): string | null {\n const clean = stripAnsi(line).trim();\n return Object.values(CONSOLE_LOG_TYPES).find((type) => type === clean) ?? null;\n}\n","import { writeFileSync } from \"node:fs\";\nimport path from \"node:path\";\n\nimport { VALID_EXPORT_FORMATS } from \"./constants\";\nimport type { ExportFormat, OutputOptions } from \"../types\";\n\nexport function getDisplayTimestamp(locale = \"en-US\"): string {\n return new Date().toLocaleString(locale, {\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: false,\n });\n}\n\nexport function getFilenameTimestamp(): string {\n const now = new Date();\n const pad = (value: number) => String(value).padStart(2, \"0\");\n\n return (\n [now.getFullYear(), pad(now.getMonth() + 1), pad(now.getDate())].join(\"-\") +\n \"_\" +\n [pad(now.getHours()), pad(now.getMinutes()), pad(now.getSeconds())].join(\"-\")\n );\n}\n\nexport function buildTimestampedPath(prefix: string, extension: string, dir = process.cwd()): string {\n const timestamp = getFilenameTimestamp();\n const filename = `${prefix}-${timestamp}.${extension}`;\n\n return path.resolve(dir, filename);\n}\n\nexport function formatAsMarkdown(content: string, title: string, timestamp: string | null = null): string {\n const lines = [`# ${title}`, \"\"];\n\n if (timestamp) {\n lines.push(`Generated: ${timestamp}`, \"\");\n }\n\n lines.push(\"```text\", content.trimEnd(), \"```\", \"\");\n\n return lines.join(\"\\n\");\n}\n\nexport function exportToFile(\n content: string,\n options: { prefix: string; format: ExportFormat; title?: string; dir?: string }\n): string {\n const { prefix, format, title, dir = process.cwd() } = options;\n const filePath = buildTimestampedPath(prefix, format, dir);\n\n let finalContent = content;\n if (format === \"md\" && title) {\n finalContent = formatAsMarkdown(content, title, getDisplayTimestamp());\n }\n\n writeFileSync(filePath, finalContent, \"utf-8\");\n\n return filePath;\n}\n\nexport function parseExportCliArgs(args: string[]): { exportFormat: ExportFormat | null; exportArgs: string[] } {\n let exportFormat: ExportFormat | null = null;\n const exportArgs: string[] = [];\n\n for (const arg of args) {\n if (arg === \"--export\") {\n exportFormat = \"txt\";\n exportArgs.push(arg);\n continue;\n }\n\n if (!arg.startsWith(\"--export=\")) {\n continue;\n }\n\n const value = arg.slice(\"--export=\".length).trim().toLowerCase();\n if (!value || !VALID_EXPORT_FORMATS.includes(value as ExportFormat)) {\n throw new Error(`Invalid value for --export: ${value || \"(empty)\"}. Valid values: txt, md`);\n }\n\n exportFormat = value as ExportFormat;\n exportArgs.push(arg);\n }\n\n return { exportFormat, exportArgs };\n}\n\nexport function handleExportOrDisplay(content: string, config: OutputOptions): string | null {\n const { exportFormat, prefix, title } = config;\n\n if (!exportFormat) {\n console.log(content);\n\n return null;\n }\n\n const outputPath = exportToFile(content, {\n prefix,\n format: exportFormat,\n title,\n });\n\n console.log(`Output exported to: ${outputPath}`);\n\n return outputPath;\n}\n","type SchemaEntry = {\n values?: string[];\n default?: string;\n exclusive?: boolean;\n prefix?: string;\n allowedValues?: string[];\n};\n\nexport function validateCliArgs(\n args: string[],\n schema: Record<string, SchemaEntry>\n): { parsed: Record<string, string | undefined>; unknownArgs: string[] } {\n const parsed: Record<string, string | undefined> = {};\n const unknownArgs: string[] = [];\n\n for (const [key, config] of Object.entries(schema)) {\n if (config.default !== undefined) {\n parsed[key] = config.default;\n }\n }\n\n for (const arg of args) {\n let matched = false;\n\n for (const [key, config] of Object.entries(schema)) {\n if (config.values?.includes(arg)) {\n if (config.exclusive && parsed[key] !== undefined && parsed[key] !== config.default) {\n throw new Error(`Multiple values provided for ${key}: ${parsed[key]} and ${arg}`);\n }\n\n parsed[key] = arg;\n matched = true;\n break;\n }\n\n if (config.prefix && arg.startsWith(config.prefix)) {\n const value = arg.slice(config.prefix.length).trim().toLowerCase();\n\n if (!value) {\n parsed[key] = \"true\";\n matched = true;\n break;\n }\n\n if (config.allowedValues && !config.allowedValues.includes(value)) {\n throw new Error(\n `Invalid value for ${config.prefix}: ${value}. Valid values: ${config.allowedValues.join(\", \")}`\n );\n }\n\n parsed[key] = value;\n matched = true;\n break;\n }\n }\n\n if (!matched && arg.startsWith(\"--\")) {\n unknownArgs.push(arg);\n }\n }\n\n return { parsed, unknownArgs };\n}\n\nexport function displayHelp(\n title: string,\n content: { description?: string; usage?: string[]; options?: string[]; examples?: string[] }\n): never {\n console.log(`\\n${title}\\n`);\n\n if (content.description) {\n console.log(`${content.description}\\n`);\n }\n\n if (content.usage?.length) {\n console.log(\"Usage:\");\n content.usage.forEach((line) => console.log(` ${line}`));\n console.log(\"\");\n }\n\n if (content.options?.length) {\n console.log(\"Options:\");\n content.options.forEach((line) => console.log(` ${line}`));\n console.log(\"\");\n }\n\n if (content.examples?.length) {\n console.log(\"Examples:\");\n content.examples.forEach((line) => console.log(` ${line}`));\n console.log(\"\");\n }\n\n process.exit(0);\n}\n\nexport function exitWithError(message: string, code = 1): never {\n console.error(`❌ ${message}`);\n process.exit(code);\n}\n\nexport function logWarning(message: string): void {\n console.warn(`⚠️ ${message}`);\n}\n\nexport function logInfo(message: string): void {\n console.log(`ℹ️ ${message}`);\n}\n\nexport function logSuccess(message: string): void {\n console.log(`✅ ${message}`);\n}\n","import { getDisplayTimestamp } from \"./export\";\n\ntype Spinner = {\n start: () => Spinner;\n stop: () => Spinner;\n succeed: (message?: string) => Spinner;\n warn: (message?: string) => Spinner;\n fail: (message?: string) => Spinner;\n};\n\ntype ProgressBar = {\n update: (value: number, payload?: Record<string, string>) => void;\n stop: () => void;\n};\n\nconst NOOP_PROGRESS_BAR: ProgressBar = {\n update: () => {},\n stop: () => {},\n};\n\nlet hasWarnedSpinnerFallback = false;\nlet hasWarnedProgressFallback = false;\n\nexport function shouldShowUI(exportMode: string | null, noBanner = false): boolean {\n return !noBanner;\n}\n\nexport function displayBanner(config: {\n text: string;\n subtitle?: string;\n info?: Record<string, string>;\n colors?: string[];\n font?: string;\n}): void {\n const { text, subtitle, info = {}, colors = [\"cyan\"], font = \"block\" } = config;\n\n // Lazy load to avoid breaking non-interactive execution.\n const cfonts = require(\"cfonts\") as {\n render: (message: string, options: Record<string, unknown>) => { string: string };\n };\n const boxenModule = require(\"boxen\") as\n | ((text: string, options: Record<string, unknown>) => string)\n | { default: (text: string, options: Record<string, unknown>) => string };\n const boxen = typeof boxenModule === \"function\" ? boxenModule : boxenModule.default;\n\n const renderedTitle = cfonts.render(text, {\n font,\n colors: [colors[0] ?? \"cyan\"],\n align: \"left\",\n background: \"transparent\",\n letterSpacing: 1,\n lineHeight: 1,\n space: false,\n maxLength: \"0\",\n env: \"node\",\n });\n\n const renderedSubtitle = subtitle\n ? cfonts.render(subtitle, {\n font,\n colors: [colors[1] ?? colors[0] ?? \"cyan\"],\n align: \"left\",\n background: \"transparent\",\n letterSpacing: 1,\n lineHeight: 1,\n space: false,\n maxLength: \"0\",\n env: \"node\",\n })\n : null;\n\n const stripAnsi = (value: string): string => value.replace(/\\x1b\\[[0-9;]*m/g, \"\");\n const centerLines = (lines: string[], width: number): string[] => {\n return lines.map((line) => {\n const visibleLength = stripAnsi(line).length;\n const leftPad = Math.max(0, Math.floor((width - visibleLength) / 2));\n\n return `${\" \".repeat(leftPad)}${line}`;\n });\n };\n\n const titleLines = renderedTitle.string.trimEnd().split(\"\\n\");\n const subtitleLines = renderedSubtitle ? renderedSubtitle.string.trimEnd().split(\"\\n\") : [];\n const centeredWidth = Math.max(\n ...titleLines.map((line) => stripAnsi(line).length),\n ...(subtitleLines.length > 0 ? subtitleLines : [\"\"]).map((line) => stripAnsi(line).length)\n );\n\n const infoLine = Object.entries(info)\n .map(([key, value]) => `${key}: ${value}`)\n .join(\" | \");\n\n const contentLines = [...centerLines(titleLines, centeredWidth)];\n if (subtitleLines.length > 0) {\n contentLines.push(\"\", ...centerLines(subtitleLines, centeredWidth));\n }\n\n contentLines.push(\"\");\n if (infoLine) {\n contentLines.push(` ${infoLine}`);\n }\n contentLines.push(` Date: ${getDisplayTimestamp()}`);\n\n const boxed = boxen(contentLines.join(\"\\n\"), {\n padding: {\n top: 0,\n right: 1,\n bottom: 0,\n left: 1,\n },\n margin: {\n top: 0,\n right: 0,\n bottom: 1,\n left: 0,\n },\n borderStyle: \"round\",\n borderColor: colors[0] ?? \"cyan\",\n });\n\n console.log(boxed);\n}\n\nexport function createSpinner(text: string, color: string = \"cyan\"): Spinner {\n try {\n const ora = require(\"ora\") as (config: Record<string, unknown>) => Spinner;\n\n return ora({ text, color, spinner: \"dots\" });\n } catch {\n if (!hasWarnedSpinnerFallback) {\n hasWarnedSpinnerFallback = true;\n console.warn(\"Warning: spinner UI unavailable, continuing without spinner.\");\n }\n\n return {\n start: () => NOOP_SPINNER,\n stop: () => NOOP_SPINNER,\n succeed: () => NOOP_SPINNER,\n warn: () => NOOP_SPINNER,\n fail: () => NOOP_SPINNER,\n } as Spinner;\n }\n}\n\nconst NOOP_SPINNER: Spinner = {\n start: () => NOOP_SPINNER,\n stop: () => NOOP_SPINNER,\n succeed: () => NOOP_SPINNER,\n warn: () => NOOP_SPINNER,\n fail: () => NOOP_SPINNER,\n};\n\nexport function createProgressBar(total = 100, task = \"Progress\"): ProgressBar {\n if (!hasWarnedProgressFallback) {\n hasWarnedProgressFallback = true;\n console.warn(\n `Warning: progress bar UI is no longer used. Ignoring createProgressBar(${total}, ${JSON.stringify(task)}).`\n );\n }\n\n return NOOP_PROGRESS_BAR;\n}\n","import {\n buildJestArgsForMode,\n displayBanner,\n exitWithError,\n extractConsoleType,\n handleExportOrDisplay,\n JEST_PATTERNS,\n parseExportCliArgs,\n runJest,\n shouldShowUI,\n stripAnsi,\n validateCliArgs,\n VALID_MODES,\n createSpinner,\n displayHelp,\n logWarning,\n} from \"../core\";\n\ntype FailureBlock = {\n file: string;\n tests: string[];\n};\n\nfunction outputTestContext(content: string, options: { exportFormat: \"txt\" | \"md\" | null }): void {\n const { exportFormat } = options;\n\n if (!exportFormat) {\n handleExportOrDisplay(content, {\n exportFormat,\n prefix: \"export-test-context\",\n title: \"Test Context\",\n });\n\n return;\n }\n\n const exportSpinner = createSpinner(\"Exporting test context...\", \"cyan\");\n exportSpinner.start();\n\n handleExportOrDisplay(content, {\n exportFormat,\n prefix: \"export-test-context\",\n title: \"Test Context\",\n });\n\n exportSpinner.succeed(\"Test context exported\");\n}\n\nexport function extractFailures(raw: string): FailureBlock[] {\n const lines = raw.split(\"\\n\");\n const temp: FailureBlock[] = [];\n let current: FailureBlock | null = null;\n\n for (const line of lines) {\n if (JEST_PATTERNS.FAIL_LINE.test(line)) {\n if (current) {\n temp.push(current);\n }\n current = {\n file: line.replace(\"FAIL \", \"\").trim(),\n tests: [],\n };\n continue;\n }\n\n if (JEST_PATTERNS.BULLET_POINT.test(line.trim())) {\n current?.tests.push(line.trim().slice(1).trim());\n }\n }\n\n if (current) {\n temp.push(current);\n }\n\n const merged: Record<string, FailureBlock> = {};\n for (const item of temp) {\n if (!merged[item.file]) {\n merged[item.file] = {\n file: item.file,\n tests: [],\n };\n }\n merged[item.file].tests.push(...item.tests);\n }\n\n for (const value of Object.values(merged)) {\n value.tests = Array.from(new Set(value.tests));\n }\n\n return Object.values(merged);\n}\n\nexport async function runTestContext(argv = process.argv.slice(2)): Promise<void> {\n if (argv.includes(\"-h\") || argv.includes(\"--help\")) {\n displayHelp(\"Test Context Script\", {\n description: \"Run Jest and print failures in LLM-friendly format.\",\n usage: [\n \"test-context -- --all\",\n \"test-context -- --related\",\n \"test-context -- --tests\",\n ],\n options: [\n \"--all Run all tests (default)\",\n \"--related Run tests related to staged files\",\n \"--tests Run only staged test files\",\n \"--export Export output as txt\",\n \"--export=txt|md Export output in selected format\",\n \"--no-banner Disable fancy terminal UI\",\n \"-h, --help Show this help\",\n ],\n examples: [\"test-context -- --related --export=md\"],\n });\n }\n\n const noBanner = argv.includes(\"--no-banner\");\n const args = argv.filter((arg) => arg !== \"--no-banner\");\n\n let exportFormat: \"txt\" | \"md\" | null;\n let exportArgs: string[];\n let parsed: Record<string, string | undefined>;\n let unknownArgs: string[];\n\n try {\n ({ exportFormat, exportArgs } = parseExportCliArgs(args));\n ({ parsed, unknownArgs } = validateCliArgs(args, {\n mode: {\n values: [...VALID_MODES],\n default: \"--all\",\n exclusive: true,\n },\n }));\n } catch (error) {\n exitWithError((error as Error).message);\n }\n\n const exportArgSet = new Set(exportArgs);\n const filteredUnknownArgs = unknownArgs.filter((arg) => !exportArgSet.has(arg));\n if (filteredUnknownArgs.length > 0) {\n logWarning(`Unknown arguments ignored: ${filteredUnknownArgs.join(\", \")}`);\n }\n\n const modeArg = parsed.mode ?? \"--all\";\n const mode = modeArg === \"--related\" ? \"related\" : modeArg === \"--tests\" ? \"tests\" : \"all\";\n\n const showBanner = shouldShowUI(exportFormat, noBanner);\n if (showBanner) {\n displayBanner({\n text: \"JEST\",\n subtitle: \"TEST\",\n info: {\n Mode: mode,\n },\n colors: [\"cyan\", \"blue\"],\n });\n }\n\n let jestArgs: string[] = [];\n try {\n jestArgs = await buildJestArgsForMode(mode);\n } catch (error) {\n exitWithError((error as Error).message);\n }\n\n const spinner = createSpinner(\"Running Jest tests...\");\n spinner.start();\n\n const result = await runJest(jestArgs, {\n verbose: true,\n ignoreErrors: true,\n });\n\n const output = stripAnsi(result.output);\n const hadFailures = output.includes(\"FAIL\") || output.includes(\"●\");\n\n if (hadFailures) {\n spinner.warn(\"Tests completed with failures\");\n } else {\n spinner.succeed(\"All tests passed!\");\n }\n\n if (!hadFailures) {\n const passMessage = \"All tests passed!\";\n outputTestContext(passMessage, { exportFormat });\n\n return;\n }\n\n const failures = extractFailures(output);\n const lines = [\"=== LLM TEST CONTEXT BEGIN ===\", \"\"];\n\n if (failures.length === 0) {\n lines.push(\"No test failures could be parsed from Jest output.\");\n lines.push(\"This may happen if Jest failed before running tests.\", \"\");\n }\n\n for (const fail of failures) {\n lines.push(`File: ${fail.file}`);\n lines.push(\"Failures:\");\n for (const test of fail.tests) {\n lines.push(`- ${test}`);\n }\n lines.push(\"\");\n }\n\n lines.push(\"=== LLM TEST CONTEXT END ===\");\n\n outputTestContext(lines.join(\"\\n\"), { exportFormat });\n}\n","#!/usr/bin/env node\n\nimport { runTestContext } from \"../commands/test-context\";\n\nrunTestContext().catch((error) => {\n console.error(`❌ ${(error as Error).message}`);\n process.exit(1);\n});\n"],"mappings":"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","names":["import_node_child_process","path","import_node_fs","import_node_path","path","stripAnsi"]}
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runTestContext
4
- } from "../chunk-B3JGCTH3.mjs";
5
- import "../chunk-44SYPQVJ.mjs";
4
+ } from "../chunk-UHFZOKGL.mjs";
5
+ import "../chunk-2B6NO7WQ.mjs";
6
6
 
7
7
  // src/bin/test-context.ts
8
8
  runTestContext().catch((error) => {