@andy2639/jest-context 1.0.4 → 1.0.5

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.5
4
+
5
+ - Improve Jest runner resolution across project layouts by resolving `jest/package.json` first
6
+ - Add robust fallbacks for legacy Jest paths and local `.bin` executables
7
+ - Improve missing-Jest diagnostics with cwd and resolution attempts
8
+
3
9
  ## 1.0.4
4
10
 
5
11
  - Strengthen package metadata to clearly require `jest@>=29` as a non-optional peer dependency
@@ -24,7 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  ));
25
25
 
26
26
  // src/commands/console-context.ts
27
- var import_node_path2 = __toESM(require("path"));
27
+ var import_node_path3 = __toESM(require("path"));
28
28
 
29
29
  // src/core/constants.ts
30
30
  var VALID_MODES = ["--all", "--related", "--tests"];
@@ -140,14 +140,66 @@ function filterTestFiles(files) {
140
140
 
141
141
  // src/core/jest.ts
142
142
  var import_node_child_process2 = require("child_process");
143
- function resolveJestBinPath() {
143
+ var import_node_fs = require("fs");
144
+ var import_node_path = __toESM(require("path"));
145
+ function resolveJestRunner() {
146
+ const cwd = process.cwd();
147
+ const attempts = [];
144
148
  try {
145
- return require.resolve("jest/bin/jest.js", { paths: [process.cwd()] });
149
+ const jestPackageJsonPath = require.resolve("jest/package.json", { paths: [cwd] });
150
+ attempts.push(`Resolved jest package: ${jestPackageJsonPath}`);
151
+ const jestPackageDir = import_node_path.default.dirname(jestPackageJsonPath);
152
+ const jestPackage = JSON.parse((0, import_node_fs.readFileSync)(jestPackageJsonPath, "utf-8"));
153
+ const binField = jestPackage.bin;
154
+ let binEntry;
155
+ if (typeof binField === "string") {
156
+ binEntry = binField;
157
+ } else if (binField && typeof binField === "object") {
158
+ binEntry = binField.jest ?? Object.values(binField)[0];
159
+ }
160
+ if (binEntry) {
161
+ const binPath = import_node_path.default.resolve(jestPackageDir, binEntry);
162
+ if ((0, import_node_fs.existsSync)(binPath)) {
163
+ return {
164
+ command: process.execPath,
165
+ argsPrefix: [binPath]
166
+ };
167
+ }
168
+ attempts.push(`Jest bin from package.json not found: ${binPath}`);
169
+ } else {
170
+ attempts.push("Jest package.json has no usable bin field.");
171
+ }
146
172
  } catch {
147
- throw new Error(
148
- "Could not resolve Jest from the current project. Install `jest@^29` in this project (for example: `npm i -D jest@^29`, `pnpm add -D jest@^29`, or `yarn add -D jest@^29`)."
149
- );
173
+ attempts.push("Could not resolve jest/package.json from current cwd.");
150
174
  }
175
+ try {
176
+ const legacyBinPath = require.resolve("jest/bin/jest.js", { paths: [cwd] });
177
+ attempts.push(`Resolved legacy jest bin: ${legacyBinPath}`);
178
+ return {
179
+ command: process.execPath,
180
+ argsPrefix: [legacyBinPath]
181
+ };
182
+ } catch {
183
+ attempts.push("Could not resolve legacy path jest/bin/jest.js.");
184
+ }
185
+ const localBinPath = import_node_path.default.resolve(cwd, "node_modules", ".bin", isWindows() ? "jest.cmd" : "jest");
186
+ if ((0, import_node_fs.existsSync)(localBinPath)) {
187
+ attempts.push(`Resolved local .bin executable: ${localBinPath}`);
188
+ return {
189
+ command: localBinPath,
190
+ argsPrefix: []
191
+ };
192
+ }
193
+ attempts.push(`Local .bin executable not found: ${localBinPath}`);
194
+ throw new Error(
195
+ [
196
+ "Could not resolve Jest from the current project.",
197
+ "Install `jest@^29` in the package where you run this command.",
198
+ "Examples: `npm i -D jest@^29`, `pnpm add -D jest@^29`, `yarn add -D jest@^29`.",
199
+ `cwd: ${cwd}`,
200
+ ...attempts
201
+ ].join("\n")
202
+ );
151
203
  }
152
204
  async function runJest(args = [], options = {}) {
153
205
  const {
@@ -156,9 +208,9 @@ async function runJest(args = [], options = {}) {
156
208
  ignoreErrors = true,
157
209
  disableVerbose = false
158
210
  } = options;
159
- const jestBinPath = resolveJestBinPath();
160
- const command = process.execPath;
161
- const jestArgs = [jestBinPath];
211
+ const runner = resolveJestRunner();
212
+ const command = runner.command;
213
+ const jestArgs = [...runner.argsPrefix];
162
214
  if (verbose && !disableVerbose) {
163
215
  jestArgs.push("--verbose");
164
216
  }
@@ -241,8 +293,8 @@ function extractConsoleType(line) {
241
293
  }
242
294
 
243
295
  // src/core/export.ts
244
- var import_node_fs = require("fs");
245
- var import_node_path = __toESM(require("path"));
296
+ var import_node_fs2 = require("fs");
297
+ var import_node_path2 = __toESM(require("path"));
246
298
  function getDisplayTimestamp(locale = "en-US") {
247
299
  return (/* @__PURE__ */ new Date()).toLocaleString(locale, {
248
300
  year: "numeric",
@@ -262,7 +314,7 @@ function getFilenameTimestamp() {
262
314
  function buildTimestampedPath(prefix, extension, dir = process.cwd()) {
263
315
  const timestamp = getFilenameTimestamp();
264
316
  const filename = `${prefix}-${timestamp}.${extension}`;
265
- return import_node_path.default.resolve(dir, filename);
317
+ return import_node_path2.default.resolve(dir, filename);
266
318
  }
267
319
  function formatAsMarkdown(content, title, timestamp = null) {
268
320
  const lines = [`# ${title}`, ""];
@@ -279,7 +331,7 @@ function exportToFile(content, options) {
279
331
  if (format === "md" && title) {
280
332
  finalContent = formatAsMarkdown(content, title, getDisplayTimestamp());
281
333
  }
282
- (0, import_node_fs.writeFileSync)(filePath, finalContent, "utf-8");
334
+ (0, import_node_fs2.writeFileSync)(filePath, finalContent, "utf-8");
283
335
  return filePath;
284
336
  }
285
337
  function parseExportCliArgs(args) {
@@ -489,7 +541,7 @@ function parseConsoleWarnings(rawOutput) {
489
541
  if (JEST_PATTERNS.TEST_FILE.test(trimmed)) {
490
542
  const match = trimmed.match(JEST_PATTERNS.TEST_FILE);
491
543
  if (match) {
492
- state.currentTestFile = import_node_path2.default.basename(match[2]);
544
+ state.currentTestFile = import_node_path3.default.basename(match[2]);
493
545
  for (const warning of state.pendingWarnings) {
494
546
  if (warning.testFile === "unknown") warning.testFile = state.currentTestFile;
495
547
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/commands/console-context.ts","../../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/bin/console-context.ts"],"sourcesContent":["import path from \"node:path\";\n\nimport {\n buildJestArgsForMode,\n CONSOLE_LOG_TYPES,\n createSpinner,\n displayBanner,\n displayHelp,\n exitWithError,\n extractConsoleType,\n getDisplayTimestamp,\n handleExportOrDisplay,\n isCodeSnippetLine,\n isConsoleTypeLine,\n isStackTraceLine,\n JEST_PATTERNS,\n logWarning,\n parseExportCliArgs,\n runJest,\n shouldShowUI,\n stripAnsi,\n validateCliArgs,\n VALID_MODES,\n} from \"../core\";\n\ntype ParsedWarning = {\n type: string;\n testFile: string;\n messages: string[];\n};\n\nfunction parseConsoleWarnings(rawOutput: string): ParsedWarning[] {\n const lines = rawOutput.split(\"\\n\");\n const warnings: ParsedWarning[] = [];\n\n const state: {\n currentTestFile: string | null;\n currentWarning: ParsedWarning | null;\n pendingWarnings: ParsedWarning[];\n } = {\n currentTestFile: null,\n currentWarning: null,\n pendingWarnings: [],\n };\n\n const flushCurrentWarning = () => {\n if (!state.currentWarning) return;\n\n if (state.currentWarning.testFile === \"unknown\" && state.currentTestFile) {\n state.currentWarning.testFile = state.currentTestFile;\n }\n\n warnings.push(state.currentWarning);\n state.pendingWarnings.push(state.currentWarning);\n state.currentWarning = null;\n };\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n if (JEST_PATTERNS.TEST_FILE.test(trimmed)) {\n const match = trimmed.match(JEST_PATTERNS.TEST_FILE);\n if (match) {\n state.currentTestFile = path.basename(match[2]);\n for (const warning of state.pendingWarnings) {\n if (warning.testFile === \"unknown\") warning.testFile = state.currentTestFile;\n }\n }\n flushCurrentWarning();\n continue;\n }\n\n if (trimmed === \"● Console\") {\n continue;\n }\n\n if (isConsoleTypeLine(line)) {\n flushCurrentWarning();\n state.currentWarning = {\n type: extractConsoleType(line) ?? \"console.warn\",\n testFile: state.currentTestFile ?? \"unknown\",\n messages: [],\n };\n continue;\n }\n\n if (!state.currentWarning) continue;\n if (isCodeSnippetLine(line)) continue;\n if (isStackTraceLine(line)) continue;\n\n const cleanMessage = stripAnsi(line).trim();\n if (cleanMessage.length > 0) {\n state.currentWarning.messages.push(cleanMessage);\n }\n }\n\n flushCurrentWarning();\n\n return warnings;\n}\n\nfunction filterWarningsByType(warnings: ParsedWarning[], filter: \"errors\" | \"warns\" | null): ParsedWarning[] {\n if (filter === \"errors\") {\n return warnings.filter((w) => w.type === CONSOLE_LOG_TYPES.ERROR);\n }\n if (filter === \"warns\") {\n return warnings.filter((w) => w.type === CONSOLE_LOG_TYPES.WARN);\n }\n\n return warnings;\n}\n\nfunction groupByTestFile(warnings: ParsedWarning[]): Record<string, ParsedWarning[]> {\n const grouped: Record<string, ParsedWarning[]> = {};\n\n for (const warning of warnings) {\n const file = warning.testFile;\n if (!grouped[file]) grouped[file] = [];\n grouped[file].push(warning);\n }\n\n return grouped;\n}\n\nfunction sortFilesByWarningCount(grouped: Record<string, ParsedWarning[]>): Array<[string, ParsedWarning[]]> {\n const entries = Object.entries(grouped);\n entries.sort((a, b) => b[1].length - a[1].length);\n\n return entries;\n}\n\nfunction formatWarningsOutput(\n grouped: Record<string, ParsedWarning[]>,\n timestamp: string,\n stats: { total: number; byType: Record<string, number> }\n): string {\n const lines: string[] = [];\n lines.push(\"=== CONSOLE WARNINGS CONTEXT BEGIN ===\", \"\", `📅 Run Date: ${timestamp}`, \"\");\n\n const sortedEntries = sortFilesByWarningCount(grouped);\n const totalFiles = sortedEntries.length;\n\n if (totalFiles === 0) {\n lines.push(\"✅ No console warnings found!\");\n } else {\n lines.push(\n `⚠️ Found ${stats.total} warning(s) in ${totalFiles} test file(s)`,\n \"\",\n \"📊 Summary by Type:\",\n ` - console.error: ${stats.byType[CONSOLE_LOG_TYPES.ERROR] ?? 0} occurrence(s)`,\n ` - console.warn: ${stats.byType[CONSOLE_LOG_TYPES.WARN] ?? 0} occurrence(s)`,\n \"\",\n \"=\".repeat(60),\n \"\"\n );\n\n for (const [file, warnings] of sortedEntries) {\n lines.push(`📄 File: ${file}`, ` Total Warnings: ${warnings.length}`, \"\");\n\n warnings.forEach((warning, idx) => {\n lines.push(` ${idx + 1}. ${warning.type}`, \"\");\n\n if (warning.messages.length > 0) {\n lines.push(\" 📝 Message:\");\n warning.messages.forEach((msg) => lines.push(` ${msg}`));\n lines.push(\"\");\n }\n\n if (idx < warnings.length - 1) {\n lines.push(\" \" + \"-\".repeat(50), \"\");\n }\n });\n\n lines.push(\"=\".repeat(60), \"\");\n }\n }\n\n lines.push(\"=== CONSOLE WARNINGS CONTEXT END ===\");\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction calculateStatistics(warnings: ParsedWarning[]) {\n const stats = {\n total: warnings.length,\n byType: {\n [CONSOLE_LOG_TYPES.ERROR]: 0,\n [CONSOLE_LOG_TYPES.WARN]: 0,\n },\n };\n\n for (const warning of warnings) {\n if (warning.type === CONSOLE_LOG_TYPES.ERROR) {\n stats.byType[CONSOLE_LOG_TYPES.ERROR]++;\n } else if (warning.type === CONSOLE_LOG_TYPES.WARN) {\n stats.byType[CONSOLE_LOG_TYPES.WARN]++;\n }\n }\n\n return stats;\n}\n\nexport async function runConsoleContext(argv = process.argv.slice(2)): Promise<void> {\n if (argv.includes(\"-h\") || argv.includes(\"--help\")) {\n displayHelp(\"Console Context Script\", {\n description: \"Capture and format console warnings/errors from Jest output.\",\n usage: [\n \"console-context -- --all\",\n \"console-context -- --related\",\n \"console-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 \"--only-errors Show only console.error warnings\",\n \"--only-warns Show only console.warn warnings\",\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: [\n \"console-context -- --related --only-errors\",\n \"console-context -- --all --export=md\",\n ],\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 mode: {\n values: [...VALID_MODES],\n default: \"--all\",\n exclusive: true,\n },\n filter: {\n values: [\"--only-errors\", \"--only-warns\"],\n exclusive: true,\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 mode = parsed.mode ?? \"--all\";\n const filter = parsed.filter === \"--only-errors\" ? \"errors\" : parsed.filter === \"--only-warns\" ? \"warns\" : null;\n\n const showUI = shouldShowUI(exportFormat, noBanner);\n if (showUI) {\n displayBanner({\n text: \"JEST\",\n subtitle: \"CONSOLE\",\n info: {\n Mode: mode,\n Filter: filter ?? \"none\",\n },\n colors: [\"yellow\", \"red\"],\n });\n }\n\n const modeKey = mode.replace(\"--\", \"\") as \"all\" | \"related\" | \"tests\";\n\n let jestArgs: string[] = [];\n try {\n jestArgs = await buildJestArgsForMode(modeKey);\n } catch (error) {\n exitWithError((error as Error).message);\n }\n\n const spinner = showUI ? createSpinner(\"Capturing console warnings...\", \"yellow\") : null;\n spinner?.start();\n\n const result = await runJest(jestArgs, {\n disableVerbose: true,\n ignoreErrors: true,\n });\n\n let warnings = parseConsoleWarnings(result.output);\n warnings = filterWarningsByType(warnings, filter);\n\n if (spinner) {\n if (warnings.length > 0) {\n spinner.warn(`Found ${warnings.length} warning(s)`);\n } else {\n spinner.succeed(\"No console warnings found\");\n }\n }\n\n const grouped = groupByTestFile(warnings);\n const stats = calculateStatistics(warnings);\n const timestamp = getDisplayTimestamp();\n const formatted = formatWarningsOutput(grouped, timestamp, stats);\n\n handleExportOrDisplay(formatted, {\n exportFormat,\n prefix: \"export-console-context\",\n title: \"Console Warnings 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 { 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\";\n\nimport { isWindows } from \"./platform\";\nimport { filterTestFiles, getStagedFiles } from \"./git\";\nimport type { ExecutionMode, ExecResult, RunJestOptions } from \"../types\";\n\nfunction resolveJestBinPath(): string {\n try {\n return require.resolve(\"jest/bin/jest.js\", { paths: [process.cwd()] });\n } catch {\n throw new Error(\n \"Could not resolve Jest from the current project. Install `jest@^29` in this project (for example: `npm i -D jest@^29`, `pnpm add -D jest@^29`, or `yarn add -D jest@^29`).\"\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 jestBinPath = resolveJestBinPath();\n const command = process.execPath;\n const jestArgs = [jestBinPath];\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","#!/usr/bin/env node\n\nimport { runConsoleContext } from \"../commands/console-context\";\n\nrunConsoleContext().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","path"]}
1
+ {"version":3,"sources":["../../src/commands/console-context.ts","../../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/bin/console-context.ts"],"sourcesContent":["import path from \"node:path\";\n\nimport {\n buildJestArgsForMode,\n CONSOLE_LOG_TYPES,\n createSpinner,\n displayBanner,\n displayHelp,\n exitWithError,\n extractConsoleType,\n getDisplayTimestamp,\n handleExportOrDisplay,\n isCodeSnippetLine,\n isConsoleTypeLine,\n isStackTraceLine,\n JEST_PATTERNS,\n logWarning,\n parseExportCliArgs,\n runJest,\n shouldShowUI,\n stripAnsi,\n validateCliArgs,\n VALID_MODES,\n} from \"../core\";\n\ntype ParsedWarning = {\n type: string;\n testFile: string;\n messages: string[];\n};\n\nfunction parseConsoleWarnings(rawOutput: string): ParsedWarning[] {\n const lines = rawOutput.split(\"\\n\");\n const warnings: ParsedWarning[] = [];\n\n const state: {\n currentTestFile: string | null;\n currentWarning: ParsedWarning | null;\n pendingWarnings: ParsedWarning[];\n } = {\n currentTestFile: null,\n currentWarning: null,\n pendingWarnings: [],\n };\n\n const flushCurrentWarning = () => {\n if (!state.currentWarning) return;\n\n if (state.currentWarning.testFile === \"unknown\" && state.currentTestFile) {\n state.currentWarning.testFile = state.currentTestFile;\n }\n\n warnings.push(state.currentWarning);\n state.pendingWarnings.push(state.currentWarning);\n state.currentWarning = null;\n };\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n if (JEST_PATTERNS.TEST_FILE.test(trimmed)) {\n const match = trimmed.match(JEST_PATTERNS.TEST_FILE);\n if (match) {\n state.currentTestFile = path.basename(match[2]);\n for (const warning of state.pendingWarnings) {\n if (warning.testFile === \"unknown\") warning.testFile = state.currentTestFile;\n }\n }\n flushCurrentWarning();\n continue;\n }\n\n if (trimmed === \"● Console\") {\n continue;\n }\n\n if (isConsoleTypeLine(line)) {\n flushCurrentWarning();\n state.currentWarning = {\n type: extractConsoleType(line) ?? \"console.warn\",\n testFile: state.currentTestFile ?? \"unknown\",\n messages: [],\n };\n continue;\n }\n\n if (!state.currentWarning) continue;\n if (isCodeSnippetLine(line)) continue;\n if (isStackTraceLine(line)) continue;\n\n const cleanMessage = stripAnsi(line).trim();\n if (cleanMessage.length > 0) {\n state.currentWarning.messages.push(cleanMessage);\n }\n }\n\n flushCurrentWarning();\n\n return warnings;\n}\n\nfunction filterWarningsByType(warnings: ParsedWarning[], filter: \"errors\" | \"warns\" | null): ParsedWarning[] {\n if (filter === \"errors\") {\n return warnings.filter((w) => w.type === CONSOLE_LOG_TYPES.ERROR);\n }\n if (filter === \"warns\") {\n return warnings.filter((w) => w.type === CONSOLE_LOG_TYPES.WARN);\n }\n\n return warnings;\n}\n\nfunction groupByTestFile(warnings: ParsedWarning[]): Record<string, ParsedWarning[]> {\n const grouped: Record<string, ParsedWarning[]> = {};\n\n for (const warning of warnings) {\n const file = warning.testFile;\n if (!grouped[file]) grouped[file] = [];\n grouped[file].push(warning);\n }\n\n return grouped;\n}\n\nfunction sortFilesByWarningCount(grouped: Record<string, ParsedWarning[]>): Array<[string, ParsedWarning[]]> {\n const entries = Object.entries(grouped);\n entries.sort((a, b) => b[1].length - a[1].length);\n\n return entries;\n}\n\nfunction formatWarningsOutput(\n grouped: Record<string, ParsedWarning[]>,\n timestamp: string,\n stats: { total: number; byType: Record<string, number> }\n): string {\n const lines: string[] = [];\n lines.push(\"=== CONSOLE WARNINGS CONTEXT BEGIN ===\", \"\", `📅 Run Date: ${timestamp}`, \"\");\n\n const sortedEntries = sortFilesByWarningCount(grouped);\n const totalFiles = sortedEntries.length;\n\n if (totalFiles === 0) {\n lines.push(\"✅ No console warnings found!\");\n } else {\n lines.push(\n `⚠️ Found ${stats.total} warning(s) in ${totalFiles} test file(s)`,\n \"\",\n \"📊 Summary by Type:\",\n ` - console.error: ${stats.byType[CONSOLE_LOG_TYPES.ERROR] ?? 0} occurrence(s)`,\n ` - console.warn: ${stats.byType[CONSOLE_LOG_TYPES.WARN] ?? 0} occurrence(s)`,\n \"\",\n \"=\".repeat(60),\n \"\"\n );\n\n for (const [file, warnings] of sortedEntries) {\n lines.push(`📄 File: ${file}`, ` Total Warnings: ${warnings.length}`, \"\");\n\n warnings.forEach((warning, idx) => {\n lines.push(` ${idx + 1}. ${warning.type}`, \"\");\n\n if (warning.messages.length > 0) {\n lines.push(\" 📝 Message:\");\n warning.messages.forEach((msg) => lines.push(` ${msg}`));\n lines.push(\"\");\n }\n\n if (idx < warnings.length - 1) {\n lines.push(\" \" + \"-\".repeat(50), \"\");\n }\n });\n\n lines.push(\"=\".repeat(60), \"\");\n }\n }\n\n lines.push(\"=== CONSOLE WARNINGS CONTEXT END ===\");\n\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nfunction calculateStatistics(warnings: ParsedWarning[]) {\n const stats = {\n total: warnings.length,\n byType: {\n [CONSOLE_LOG_TYPES.ERROR]: 0,\n [CONSOLE_LOG_TYPES.WARN]: 0,\n },\n };\n\n for (const warning of warnings) {\n if (warning.type === CONSOLE_LOG_TYPES.ERROR) {\n stats.byType[CONSOLE_LOG_TYPES.ERROR]++;\n } else if (warning.type === CONSOLE_LOG_TYPES.WARN) {\n stats.byType[CONSOLE_LOG_TYPES.WARN]++;\n }\n }\n\n return stats;\n}\n\nexport async function runConsoleContext(argv = process.argv.slice(2)): Promise<void> {\n if (argv.includes(\"-h\") || argv.includes(\"--help\")) {\n displayHelp(\"Console Context Script\", {\n description: \"Capture and format console warnings/errors from Jest output.\",\n usage: [\n \"console-context -- --all\",\n \"console-context -- --related\",\n \"console-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 \"--only-errors Show only console.error warnings\",\n \"--only-warns Show only console.warn warnings\",\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: [\n \"console-context -- --related --only-errors\",\n \"console-context -- --all --export=md\",\n ],\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 mode: {\n values: [...VALID_MODES],\n default: \"--all\",\n exclusive: true,\n },\n filter: {\n values: [\"--only-errors\", \"--only-warns\"],\n exclusive: true,\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 mode = parsed.mode ?? \"--all\";\n const filter = parsed.filter === \"--only-errors\" ? \"errors\" : parsed.filter === \"--only-warns\" ? \"warns\" : null;\n\n const showUI = shouldShowUI(exportFormat, noBanner);\n if (showUI) {\n displayBanner({\n text: \"JEST\",\n subtitle: \"CONSOLE\",\n info: {\n Mode: mode,\n Filter: filter ?? \"none\",\n },\n colors: [\"yellow\", \"red\"],\n });\n }\n\n const modeKey = mode.replace(\"--\", \"\") as \"all\" | \"related\" | \"tests\";\n\n let jestArgs: string[] = [];\n try {\n jestArgs = await buildJestArgsForMode(modeKey);\n } catch (error) {\n exitWithError((error as Error).message);\n }\n\n const spinner = showUI ? createSpinner(\"Capturing console warnings...\", \"yellow\") : null;\n spinner?.start();\n\n const result = await runJest(jestArgs, {\n disableVerbose: true,\n ignoreErrors: true,\n });\n\n let warnings = parseConsoleWarnings(result.output);\n warnings = filterWarningsByType(warnings, filter);\n\n if (spinner) {\n if (warnings.length > 0) {\n spinner.warn(`Found ${warnings.length} warning(s)`);\n } else {\n spinner.succeed(\"No console warnings found\");\n }\n }\n\n const grouped = groupByTestFile(warnings);\n const stats = calculateStatistics(warnings);\n const timestamp = getDisplayTimestamp();\n const formatted = formatWarningsOutput(grouped, timestamp, stats);\n\n handleExportOrDisplay(formatted, {\n exportFormat,\n prefix: \"export-console-context\",\n title: \"Console Warnings 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 { 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","#!/usr/bin/env node\n\nimport { runConsoleContext } from \"../commands/console-context\";\n\nrunConsoleContext().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
  runConsoleContext
4
- } from "../chunk-YIYGGZAF.mjs";
5
- import "../chunk-PUB2BNCX.mjs";
4
+ } from "../chunk-DFRTVPXC.mjs";
5
+ import "../chunk-44SYPQVJ.mjs";
6
6
 
7
7
  // src/bin/console-context.ts
8
8
  runConsoleContext().catch((error) => {
@@ -24,7 +24,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  ));
25
25
 
26
26
  // src/commands/coverage-context.ts
27
- var import_node_path2 = __toESM(require("path"));
27
+ var import_node_path3 = __toESM(require("path"));
28
28
 
29
29
  // src/core/constants.ts
30
30
  var VALID_EXPORT_FORMATS = ["txt", "md"];
@@ -48,14 +48,66 @@ var import_node_child_process = require("child_process");
48
48
 
49
49
  // src/core/jest.ts
50
50
  var import_node_child_process2 = require("child_process");
51
- function resolveJestBinPath() {
51
+ var import_node_fs = require("fs");
52
+ var import_node_path = __toESM(require("path"));
53
+ function resolveJestRunner() {
54
+ const cwd = process.cwd();
55
+ const attempts = [];
56
+ try {
57
+ const jestPackageJsonPath = require.resolve("jest/package.json", { paths: [cwd] });
58
+ attempts.push(`Resolved jest package: ${jestPackageJsonPath}`);
59
+ const jestPackageDir = import_node_path.default.dirname(jestPackageJsonPath);
60
+ const jestPackage = JSON.parse((0, import_node_fs.readFileSync)(jestPackageJsonPath, "utf-8"));
61
+ const binField = jestPackage.bin;
62
+ let binEntry;
63
+ if (typeof binField === "string") {
64
+ binEntry = binField;
65
+ } else if (binField && typeof binField === "object") {
66
+ binEntry = binField.jest ?? Object.values(binField)[0];
67
+ }
68
+ if (binEntry) {
69
+ const binPath = import_node_path.default.resolve(jestPackageDir, binEntry);
70
+ if ((0, import_node_fs.existsSync)(binPath)) {
71
+ return {
72
+ command: process.execPath,
73
+ argsPrefix: [binPath]
74
+ };
75
+ }
76
+ attempts.push(`Jest bin from package.json not found: ${binPath}`);
77
+ } else {
78
+ attempts.push("Jest package.json has no usable bin field.");
79
+ }
80
+ } catch {
81
+ attempts.push("Could not resolve jest/package.json from current cwd.");
82
+ }
52
83
  try {
53
- return require.resolve("jest/bin/jest.js", { paths: [process.cwd()] });
84
+ const legacyBinPath = require.resolve("jest/bin/jest.js", { paths: [cwd] });
85
+ attempts.push(`Resolved legacy jest bin: ${legacyBinPath}`);
86
+ return {
87
+ command: process.execPath,
88
+ argsPrefix: [legacyBinPath]
89
+ };
54
90
  } catch {
55
- throw new Error(
56
- "Could not resolve Jest from the current project. Install `jest@^29` in this project (for example: `npm i -D jest@^29`, `pnpm add -D jest@^29`, or `yarn add -D jest@^29`)."
57
- );
91
+ attempts.push("Could not resolve legacy path jest/bin/jest.js.");
92
+ }
93
+ const localBinPath = import_node_path.default.resolve(cwd, "node_modules", ".bin", isWindows() ? "jest.cmd" : "jest");
94
+ if ((0, import_node_fs.existsSync)(localBinPath)) {
95
+ attempts.push(`Resolved local .bin executable: ${localBinPath}`);
96
+ return {
97
+ command: localBinPath,
98
+ argsPrefix: []
99
+ };
58
100
  }
101
+ attempts.push(`Local .bin executable not found: ${localBinPath}`);
102
+ throw new Error(
103
+ [
104
+ "Could not resolve Jest from the current project.",
105
+ "Install `jest@^29` in the package where you run this command.",
106
+ "Examples: `npm i -D jest@^29`, `pnpm add -D jest@^29`, `yarn add -D jest@^29`.",
107
+ `cwd: ${cwd}`,
108
+ ...attempts
109
+ ].join("\n")
110
+ );
59
111
  }
60
112
  async function runJest(args = [], options = {}) {
61
113
  const {
@@ -64,9 +116,9 @@ async function runJest(args = [], options = {}) {
64
116
  ignoreErrors = true,
65
117
  disableVerbose = false
66
118
  } = options;
67
- const jestBinPath = resolveJestBinPath();
68
- const command = process.execPath;
69
- const jestArgs = [jestBinPath];
119
+ const runner = resolveJestRunner();
120
+ const command = runner.command;
121
+ const jestArgs = [...runner.argsPrefix];
70
122
  if (verbose && !disableVerbose) {
71
123
  jestArgs.push("--verbose");
72
124
  }
@@ -113,8 +165,8 @@ ${stderr}`,
113
165
  }
114
166
 
115
167
  // src/core/export.ts
116
- var import_node_fs = require("fs");
117
- var import_node_path = __toESM(require("path"));
168
+ var import_node_fs2 = require("fs");
169
+ var import_node_path2 = __toESM(require("path"));
118
170
  function getDisplayTimestamp(locale = "en-US") {
119
171
  return (/* @__PURE__ */ new Date()).toLocaleString(locale, {
120
172
  year: "numeric",
@@ -134,7 +186,7 @@ function getFilenameTimestamp() {
134
186
  function buildTimestampedPath(prefix, extension, dir = process.cwd()) {
135
187
  const timestamp = getFilenameTimestamp();
136
188
  const filename = `${prefix}-${timestamp}.${extension}`;
137
- return import_node_path.default.resolve(dir, filename);
189
+ return import_node_path2.default.resolve(dir, filename);
138
190
  }
139
191
  function formatAsMarkdown(content, title, timestamp = null) {
140
192
  const lines = [`# ${title}`, ""];
@@ -151,7 +203,7 @@ function exportToFile(content, options) {
151
203
  if (format === "md" && title) {
152
204
  finalContent = formatAsMarkdown(content, title, getDisplayTimestamp());
153
205
  }
154
- (0, import_node_fs.writeFileSync)(filePath, finalContent, "utf-8");
206
+ (0, import_node_fs2.writeFileSync)(filePath, finalContent, "utf-8");
155
207
  return filePath;
156
208
  }
157
209
  function parseExportCliArgs(args) {
@@ -351,10 +403,10 @@ function parseCoverage(text) {
351
403
  continue;
352
404
  }
353
405
  if (/index\.(ts|tsx)$/.test(normalized)) continue;
354
- if (!currentFolder) currentFolder = import_node_path2.default.dirname(normalized);
406
+ if (!currentFolder) currentFolder = import_node_path3.default.dirname(normalized);
355
407
  rows.push({
356
408
  folder: currentFolder,
357
- file: import_node_path2.default.basename(normalized),
409
+ file: import_node_path3.default.basename(normalized),
358
410
  stmts: Number(stmts),
359
411
  branch: Number(branch),
360
412
  funcs: Number(funcs),