tryscript 0.1.1 → 0.1.2

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/dist/bin.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
 
4
- import { a as createExecutionContext, c as parseTestFile, d as mergeConfig, f as resolveCoverageConfig, i as cleanupExecutionContext, n as matchOutput, o as runAfterHook, s as runBlock, t as VERSION, u as loadConfig } from "./src-CndHSuTT.mjs";
4
+ import { a as createExecutionContext, c as parseTestFile, d as mergeConfig, f as resolveCoverageConfig, i as cleanupExecutionContext, n as matchOutput, o as runAfterHook, s as runBlock, t as VERSION, u as loadConfig } from "./src-DKrim0QL.mjs";
5
5
  import { fileURLToPath } from "node:url";
6
6
  import { existsSync, readFileSync } from "node:fs";
7
7
  import { dirname, join, resolve } from "node:path";
@@ -21,10 +21,8 @@ import { writeFile } from "atomically";
21
21
  const colors = {
22
22
  success: (s) => pc.green(s),
23
23
  error: (s) => pc.red(s),
24
- info: (s) => pc.cyan(s),
25
24
  warn: (s) => pc.yellow(s),
26
- muted: (s) => pc.gray(s),
27
- bold: (s) => pc.bold(s)
25
+ info: (s) => pc.cyan(s)
28
26
  };
29
27
  /**
30
28
  * Status indicators with emoji.
@@ -181,7 +179,7 @@ function buildUpdatedBlock(block, result) {
181
179
  * Find the c8 executable path.
182
180
  * Checks local node_modules/.bin first, then falls back to npx.
183
181
  */
184
- function findC8Path() {
182
+ function findC8Path$1() {
185
183
  const localPaths = [resolve(process.cwd(), "node_modules", ".bin", "c8"), resolve(process.cwd(), "..", "..", "node_modules", ".bin", "c8")];
186
184
  for (const localPath of localPaths) if (existsSync(localPath)) return localPath;
187
185
  return "npx c8";
@@ -190,7 +188,7 @@ function findC8Path() {
190
188
  * Check if c8 is available in the current environment.
191
189
  */
192
190
  async function isC8Available() {
193
- const c8Path = findC8Path();
191
+ const c8Path = findC8Path$1();
194
192
  return new Promise((resolve$1) => {
195
193
  const isNpx = c8Path === "npx c8";
196
194
  const proc = spawn(isNpx ? "npx" : c8Path, isNpx ? ["c8", "--version"] : ["--version"], {
@@ -227,7 +225,7 @@ function getCoverageEnv(ctx) {
227
225
  */
228
226
  async function generateCoverageReport(ctx) {
229
227
  const { options, tempDir } = ctx;
230
- const c8Path = findC8Path();
228
+ const c8Path = findC8Path$1();
231
229
  const reportArgs = [
232
230
  "report",
233
231
  "--temp-directory",
@@ -238,6 +236,12 @@ async function generateCoverageReport(ctx) {
238
236
  options.src,
239
237
  "--all",
240
238
  ...options.include.flatMap((pattern) => ["--include", pattern]),
239
+ ...options.exclude.flatMap((pattern) => ["--exclude", pattern]),
240
+ ...options.excludeNodeModules ? ["--exclude-node-modules"] : ["--no-exclude-node-modules"],
241
+ ...options.excludeAfterRemap ? ["--exclude-after-remap"] : [],
242
+ ...options.skipFull ? ["--skip-full"] : [],
243
+ ...options.allowExternal ? ["--allowExternal"] : [],
244
+ ...options.monocart ? ["--experimental-monocart"] : [],
241
245
  ...options.reporters.flatMap((reporter) => ["--reporter", reporter])
242
246
  ];
243
247
  const isNpx = c8Path === "npx c8";
@@ -276,9 +280,9 @@ async function cleanupCoverageContext(ctx) {
276
280
  * Register the run command.
277
281
  */
278
282
  function registerRunCommand(program) {
279
- program.command("run").description("Run golden tests").argument("[files...]", "Test files to run (default: **/*.tryscript.md)").option("--update", "Update golden files with actual output").option("--diff", "Show diff on failure (default: true)").option("--no-diff", "Hide diff on failure").option("--fail-fast", "Stop on first failure").option("--filter <pattern>", "Filter tests by name pattern").option("--verbose", "Show detailed output including passing test output").option("--quiet", "Suppress non-essential output (only show failures)").option("--coverage", "Enable code coverage collection (requires c8)").option("--coverage-dir <dir>", "Coverage output directory (default: coverage-tryscript)").option("--coverage-reporter <reporter...>", "Coverage reporters (default: text, html). Can be specified multiple times.").action(runCommand);
283
+ program.command("run").description("Run golden tests").argument("[files...]", "Test files to run (default: **/*.tryscript.md)").option("--update", "Update golden files with actual output").option("--diff", "Show diff on failure (default: true)").option("--no-diff", "Hide diff on failure").option("--fail-fast", "Stop on first failure").option("--filter <pattern>", "Filter tests by name pattern").option("--verbose", "Show detailed output including passing test output").option("--quiet", "Suppress non-essential output (only show failures)").option("--coverage", "Enable code coverage collection (requires c8)").option("--coverage-dir <dir>", "Coverage output directory (default: coverage-tryscript)").option("--coverage-reporter <reporter...>", "Coverage reporters (default: text, html). Can be specified multiple times.").option("--coverage-exclude <pattern...>", "Patterns to exclude from coverage (c8 --exclude). Can be specified multiple times.").option("--coverage-exclude-node-modules", "Exclude node_modules from coverage (c8 --exclude-node-modules, default: true)").option("--no-coverage-exclude-node-modules", "Include node_modules in coverage (c8 --no-exclude-node-modules)").option("--coverage-exclude-after-remap", "Apply exclude logic after sourcemap remapping (c8 --exclude-after-remap)").option("--coverage-skip-full", "Hide files with 100% coverage (c8 --skip-full)").option("--coverage-allow-external", "Allow files from outside cwd (c8 --allowExternal)").option("--coverage-monocart", "Use monocart for accurate line counts, better for merging with vitest (c8 --experimental-monocart)").action(runCommand$1);
280
284
  }
281
- async function runCommand(files, options) {
285
+ async function runCommand$1(files, options) {
282
286
  const startTime = Date.now();
283
287
  const opts = {
284
288
  diff: options.diff !== false,
@@ -308,7 +312,13 @@ async function runCommand(files, options) {
308
312
  coverageCtx = await createCoverageContext({
309
313
  ...globalConfig.coverage,
310
314
  reportsDir: options.coverageDir ?? globalConfig.coverage?.reportsDir,
311
- reporters: options.coverageReporter ?? globalConfig.coverage?.reporters
315
+ reporters: options.coverageReporter ?? globalConfig.coverage?.reporters,
316
+ exclude: options.coverageExclude ?? globalConfig.coverage?.exclude,
317
+ excludeNodeModules: options.coverageExcludeNodeModules ?? globalConfig.coverage?.excludeNodeModules,
318
+ excludeAfterRemap: options.coverageExcludeAfterRemap ?? globalConfig.coverage?.excludeAfterRemap,
319
+ skipFull: options.coverageSkipFull ?? globalConfig.coverage?.skipFull,
320
+ allowExternal: options.coverageAllowExternal ?? globalConfig.coverage?.allowExternal,
321
+ monocart: options.coverageMonocart ?? globalConfig.coverage?.monocart
312
322
  });
313
323
  coverageEnv = getCoverageEnv(coverageCtx);
314
324
  }
@@ -392,6 +402,147 @@ async function runCommand(files, options) {
392
402
  process.exit(summary.totalFailed > 0 ? 1 : 0);
393
403
  }
394
404
 
405
+ //#endregion
406
+ //#region src/cli/commands/coverage.ts
407
+ /**
408
+ * Register the coverage command.
409
+ */
410
+ function registerCoverageCommand(program) {
411
+ program.command("coverage").description("Run commands with merged V8 coverage").argument("<commands...>", "Commands to run (each will inherit coverage environment)").option("--reports-dir <dir>", "Coverage output directory (default: coverage)").option("--reporters <reporters>", "Comma-separated coverage reporters (default: text,json,json-summary,lcov,html)").option("--include <patterns>", "Comma-separated patterns to include in coverage").option("--exclude <patterns>", "Comma-separated patterns to exclude from coverage").option("--exclude-node-modules", "Exclude node_modules from coverage (default: true)", true).option("--no-exclude-node-modules", "Include node_modules in coverage").option("--exclude-after-remap", "Apply exclude logic after sourcemap remapping").option("--skip-full", "Hide files with 100% coverage").option("--allow-external", "Allow files from outside cwd").option("--monocart", "Use monocart for accurate line counts (recommended for merging)").option("--src <dir>", "Source directory for sourcemap remapping (default: src)").action(coverageCommand);
412
+ }
413
+ /**
414
+ * Run a command with inherited coverage environment.
415
+ */
416
+ async function runCommand(command, env) {
417
+ return new Promise((resolve$1) => {
418
+ const proc = spawn(command, [], {
419
+ stdio: "inherit",
420
+ env: {
421
+ ...process.env,
422
+ ...env
423
+ },
424
+ shell: true
425
+ });
426
+ proc.on("close", (code) => {
427
+ resolve$1({
428
+ success: code === 0,
429
+ code: code ?? 1
430
+ });
431
+ });
432
+ proc.on("error", (err) => {
433
+ logError(`Failed to run command: ${err.message}`);
434
+ resolve$1({
435
+ success: false,
436
+ code: 1
437
+ });
438
+ });
439
+ });
440
+ }
441
+ /**
442
+ * Find the c8 executable path.
443
+ * Can be overridden via TRYSCRIPT_C8_COMMAND env var for testing.
444
+ */
445
+ function findC8Path() {
446
+ const override = process.env.TRYSCRIPT_C8_COMMAND;
447
+ if (override) return override;
448
+ const localPaths = [resolve(process.cwd(), "node_modules", ".bin", "c8"), resolve(process.cwd(), "..", "..", "node_modules", ".bin", "c8")];
449
+ for (const localPath of localPaths) if (existsSync(localPath)) return localPath;
450
+ return null;
451
+ }
452
+ /**
453
+ * Generate c8 coverage report.
454
+ */
455
+ async function generateReport(tempDir, options) {
456
+ const c8Path = findC8Path();
457
+ if (!c8Path) {
458
+ logError("c8 not found. Install with: npm install -D c8");
459
+ return false;
460
+ }
461
+ const reporters = options.reporters ?? [
462
+ "text",
463
+ "json",
464
+ "json-summary",
465
+ "lcov",
466
+ "html"
467
+ ];
468
+ const include = options.include ?? ["dist/**"];
469
+ const exclude = options.exclude ?? [];
470
+ const reportArgs = [
471
+ "report",
472
+ "--temp-directory",
473
+ tempDir,
474
+ "--reports-dir",
475
+ options.reportsDir ?? "coverage",
476
+ "--src",
477
+ options.src ?? "src",
478
+ "--all",
479
+ ...include.flatMap((pattern) => ["--include", pattern]),
480
+ ...exclude.flatMap((pattern) => ["--exclude", pattern]),
481
+ ...options.excludeNodeModules !== false ? ["--exclude-node-modules"] : ["--no-exclude-node-modules"],
482
+ ...options.excludeAfterRemap ? ["--exclude-after-remap"] : [],
483
+ ...options.skipFull ? ["--skip-full"] : [],
484
+ ...options.allowExternal ? ["--allowExternal"] : [],
485
+ ...options.monocart ? ["--experimental-monocart"] : [],
486
+ ...reporters.flatMap((reporter) => ["--reporter", reporter])
487
+ ];
488
+ return new Promise((resolve$1) => {
489
+ const proc = spawn(c8Path, reportArgs, {
490
+ stdio: "inherit",
491
+ shell: false
492
+ });
493
+ proc.on("close", (code) => {
494
+ resolve$1(code === 0);
495
+ });
496
+ proc.on("error", (err) => {
497
+ logError(`Failed to generate coverage report: ${err.message}`);
498
+ resolve$1(false);
499
+ });
500
+ });
501
+ }
502
+ async function coverageCommand(commands, options) {
503
+ if (commands.length === 0) {
504
+ logError("No commands specified. Usage: tryscript coverage \"cmd1\" \"cmd2\"");
505
+ process.exit(1);
506
+ }
507
+ if (!findC8Path()) {
508
+ logError("Coverage requires c8. Install with: npm install -D c8");
509
+ process.exit(1);
510
+ }
511
+ const coverageTemp = await mkdtemp(join(tmpdir(), "tryscript-coverage-"));
512
+ const coverageEnv = { NODE_V8_COVERAGE: coverageTemp };
513
+ console.error(colors.info(`Collecting V8 coverage to ${coverageTemp}`));
514
+ let hasFailures = false;
515
+ try {
516
+ for (let i = 0; i < commands.length; i++) {
517
+ const command = commands[i];
518
+ console.error(colors.info(`\n=== Running command ${i + 1}/${commands.length}: ${command} ===`));
519
+ const result = await runCommand(command, coverageEnv);
520
+ if (!result.success) {
521
+ logWarn(`Command exited with code ${result.code}: ${command}`);
522
+ hasFailures = true;
523
+ }
524
+ }
525
+ console.error(colors.info("\n=== Generating merged coverage report ==="));
526
+ const parsedOptions = {
527
+ ...options,
528
+ reporters: options.reporters ? typeof options.reporters === "string" ? options.reporters.split(",") : options.reporters : void 0,
529
+ include: options.include ? typeof options.include === "string" ? options.include.split(",") : options.include : void 0,
530
+ exclude: options.exclude ? typeof options.exclude === "string" ? options.exclude.split(",") : options.exclude : void 0
531
+ };
532
+ if (!await generateReport(coverageTemp, parsedOptions)) {
533
+ logError("Failed to generate coverage report");
534
+ process.exit(1);
535
+ }
536
+ console.error(colors.success(`\nCoverage report written to ${parsedOptions.reportsDir ?? "coverage"}/`));
537
+ } finally {
538
+ await rm(coverageTemp, {
539
+ recursive: true,
540
+ force: true
541
+ });
542
+ }
543
+ if (hasFailures) process.exit(1);
544
+ }
545
+
395
546
  //#endregion
396
547
  //#region src/cli/commands/readme.ts
397
548
  /**
@@ -471,7 +622,7 @@ function isInteractive$1() {
471
622
  */
472
623
  function showReadme(options) {
473
624
  try {
474
- const formatted = formatMarkdown$1(loadReadme(), !options?.raw && isInteractive$1());
625
+ const formatted = formatMarkdown$1(loadReadme(), options?.color ?? (!options?.raw && isInteractive$1()));
475
626
  console.log(formatted);
476
627
  } catch (error) {
477
628
  const message = error instanceof Error ? error.message : String(error);
@@ -483,7 +634,7 @@ function showReadme(options) {
483
634
  * Register the readme command.
484
635
  */
485
636
  function registerReadmeCommand(program) {
486
- program.command("readme").description("Display README documentation").option("--raw", "Output raw markdown without formatting").action(showReadme);
637
+ program.command("readme").description("Display README documentation").option("--raw", "Output raw markdown without formatting").option("--color", "Force colorized output (for testing)").action(showReadme);
487
638
  }
488
639
 
489
640
  //#endregion
@@ -563,9 +714,9 @@ function isInteractive() {
563
714
  * Register the docs command.
564
715
  */
565
716
  function registerDocsCommand(program) {
566
- program.command("docs").description("Display concise syntax reference").option("--raw", "Output raw markdown without formatting").action((options) => {
717
+ program.command("docs").description("Display concise syntax reference").option("--raw", "Output raw markdown without formatting").option("--color", "Force colorized output (for testing)").action((options) => {
567
718
  try {
568
- const formatted = formatMarkdown(loadDocs(), !options.raw && isInteractive());
719
+ const formatted = formatMarkdown(loadDocs(), options.color ?? (!options.raw && isInteractive()));
569
720
  console.log(formatted);
570
721
  } catch (error) {
571
722
  const message = error instanceof Error ? error.message : String(error);
@@ -585,6 +736,7 @@ function registerDocsCommand(program) {
585
736
  function run(argv) {
586
737
  const program = withColoredHelp(new Command().name("tryscript").version(VERSION, "--version", "Show version number").description("Golden testing for CLI applications").showHelpAfterError("(use --help for usage)"));
587
738
  registerRunCommand(program);
739
+ registerCoverageCommand(program);
588
740
  registerReadmeCommand(program);
589
741
  registerDocsCommand(program);
590
742
  program.action(() => {
package/dist/bin.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bin.mjs","names":["status","parts: string[]","changes: string[]","lines: string[]","coverageCtx: CoverageContext | undefined","coverageEnv: Record<string, string>","fileResults: TestFileResult[]","results: TestBlockResult[]","fileResult: TestFileResult","statusIndicators","summary: TestRunSummary","formatMarkdown","formatted: string[]","isInteractive","formatted: string[]"],"sources":["../src/cli/lib/shared.ts","../src/lib/reporter.ts","../src/lib/updater.ts","../src/lib/coverage.ts","../src/cli/commands/run.ts","../src/cli/commands/readme.ts","../src/cli/commands/docs.ts","../src/cli/cli.ts","../src/bin.ts"],"sourcesContent":["/**\n * Shared CLI utilities for consistent output formatting and color usage.\n *\n * This module provides:\n * - Color utilities via picocolors\n * - Commander.js help text styling\n * - Logging helpers for consistent output\n */\n\nimport type { Command } from 'commander';\nimport pc from 'picocolors';\n\n/**\n * Shared color utilities for consistent terminal output.\n */\nexport const colors = {\n success: (s: string) => pc.green(s),\n error: (s: string) => pc.red(s),\n info: (s: string) => pc.cyan(s),\n warn: (s: string) => pc.yellow(s),\n muted: (s: string) => pc.gray(s),\n bold: (s: string) => pc.bold(s),\n};\n\n/**\n * Status indicators with emoji.\n */\nexport const status = {\n pass: pc.green('✓'),\n fail: pc.red('✗'),\n skip: pc.yellow('○'),\n update: pc.yellow('↻'),\n};\n\n/**\n * Configure Commander.js with colored help text.\n * Applies consistent styling: cyan titles, green commands, yellow options.\n */\nexport function withColoredHelp<T extends Command>(cmd: T): T {\n cmd.configureHelp({\n styleTitle: (str) => pc.bold(pc.cyan(str)),\n styleCommandText: (str) => pc.green(str),\n styleOptionText: (str) => pc.yellow(str),\n showGlobalOptions: true,\n });\n return cmd;\n}\n\n/**\n * Format a duration in milliseconds for display.\n */\nexport function formatDuration(ms: number): string {\n if (ms < 1000) {\n return `${ms}ms`;\n }\n return `${(ms / 1000).toFixed(2)}s`;\n}\n\n/**\n * Log an informational message to stderr.\n */\nexport function logInfo(message: string): void {\n console.error(colors.info(message));\n}\n\n/**\n * Log a success message to stderr.\n */\nexport function logSuccess(message: string): void {\n console.error(colors.success(message));\n}\n\n/**\n * Log a warning message to stderr.\n */\nexport function logWarn(message: string): void {\n console.error(colors.warn(message));\n}\n\n/**\n * Log an error message to stderr.\n */\nexport function logError(message: string): void {\n console.error(colors.error(message));\n}\n\n/**\n * Log timing information with emoji.\n */\nexport function logTiming(label: string, durationMs: number): void {\n console.error(colors.info(`⏰ ${label}: ${formatDuration(durationMs)}`));\n}\n","/**\n * Test result reporting utilities.\n *\n * Handles output formatting for test results, diffs, and summaries.\n */\n\nimport pc from 'picocolors';\nimport { createPatch } from 'diff';\nimport type { TestFileResult, TestRunSummary } from './types.js';\n\nexport interface ReporterOptions {\n diff: boolean;\n verbose: boolean;\n quiet: boolean;\n}\n\n// Status indicators for consistent output\nconst statusIcon = {\n pass: pc.green('✓'),\n fail: pc.red('✗'),\n};\n\n/**\n * Format a duration in milliseconds for display.\n */\nfunction formatDuration(ms: number): string {\n if (ms < 1000) {\n return `${ms}ms`;\n }\n return `${(ms / 1000).toFixed(2)}s`;\n}\n\n/**\n * Create a unified diff between expected and actual output.\n */\nexport function createDiff(expected: string, actual: string, filename: string): string {\n const patch = createPatch(filename, expected, actual, 'expected', 'actual');\n // Remove the header lines (first 4 lines)\n const lines = patch.split('\\n').slice(4);\n return lines\n .map((line) => {\n if (line.startsWith('+')) {\n return pc.green(line);\n }\n if (line.startsWith('-')) {\n return pc.red(line);\n }\n if (line.startsWith('@')) {\n return pc.cyan(line);\n }\n return line;\n })\n .join('\\n');\n}\n\n/**\n * Report results for a single file.\n */\nexport function reportFile(result: TestFileResult, options: ReporterOptions): void {\n const filename = result.file.path;\n const status = result.passed ? pc.green(pc.bold('PASS')) : pc.red(pc.bold('FAIL'));\n\n if (options.quiet && result.passed) {\n return;\n }\n\n // File header\n console.error(`${status} ${filename}`);\n\n // Individual block results\n for (const blockResult of result.results) {\n const name = blockResult.block.name ?? `Line ${blockResult.block.lineNumber}`;\n\n if (blockResult.passed) {\n if (!options.quiet) {\n console.error(` ${statusIcon.pass} ${name}`);\n }\n } else {\n console.error(` ${statusIcon.fail} ${name}`);\n\n // Show error details\n if (blockResult.error) {\n console.error(` ${pc.red(blockResult.error)}`);\n } else {\n // Exit code mismatch\n if (blockResult.actualExitCode !== blockResult.block.expectedExitCode) {\n console.error(\n ` Expected exit code ${blockResult.block.expectedExitCode}, got ${blockResult.actualExitCode}`,\n );\n }\n\n // Output mismatch with diff\n if (options.diff && blockResult.diff) {\n console.error('');\n console.error(blockResult.diff);\n }\n }\n }\n }\n\n console.error('');\n}\n\n/**\n * Report final summary.\n */\nexport function reportSummary(summary: TestRunSummary, _options: ReporterOptions): void {\n const parts: string[] = [];\n\n if (summary.totalPassed > 0) {\n parts.push(pc.green(`${summary.totalPassed} passed`));\n }\n if (summary.totalFailed > 0) {\n parts.push(pc.red(`${summary.totalFailed} failed`));\n }\n\n const duration = formatDuration(summary.duration);\n const line = `${parts.join(', ')} (${duration})`;\n\n // Summary goes to stdout (can be piped/parsed)\n console.log(line);\n}\n","import { writeFile } from 'atomically';\nimport type { TestFile, TestBlock, TestBlockResult } from './types.js';\n\n/**\n * Update a test file with actual output from test results.\n */\nexport async function updateTestFile(\n file: TestFile,\n results: TestBlockResult[],\n): Promise<{ updated: boolean; changes: string[] }> {\n let content = file.rawContent;\n const changes: string[] = [];\n\n // Process blocks in reverse order to maintain correct offsets\n const blocksWithResults = file.blocks\n .map((block, i) => ({ block, result: results[i] }))\n .reverse();\n\n for (const { block, result } of blocksWithResults) {\n if (!result) {\n continue;\n }\n\n if (result.passed) {\n continue; // Don't touch passing tests\n }\n\n if (result.error) {\n // Execution error, can't update\n continue;\n }\n\n // Build the new block content\n const newBlockContent = buildUpdatedBlock(block, result);\n\n // Find and replace the block in the file\n const blockStart = content.indexOf(block.rawContent);\n if (blockStart !== -1) {\n content =\n content.slice(0, blockStart) +\n newBlockContent +\n content.slice(blockStart + block.rawContent.length);\n\n changes.push(block.name ?? `Line ${block.lineNumber}`);\n }\n }\n\n if (changes.length > 0) {\n await writeFile(file.path, content);\n }\n\n return { updated: changes.length > 0, changes };\n}\n\n/**\n * Build an updated console block with new expected output.\n */\nfunction buildUpdatedBlock(block: TestBlock, result: TestBlockResult): string {\n // Reconstruct the command line(s)\n const commandLines = block.command.split('\\n').map((line, i) => {\n return i === 0 ? `$ ${line}` : `> ${line}`;\n });\n\n // Build the block\n const lines: string[] = ['```console', ...commandLines];\n\n // Add output if present\n const trimmedOutput = result.actualOutput.trimEnd();\n if (trimmedOutput) {\n lines.push(trimmedOutput);\n }\n\n // Add exit code\n lines.push(`? ${result.actualExitCode}`, '```');\n\n return lines.join('\\n');\n}\n","/**\n * Coverage collection for CLI subprocess testing.\n *\n * Uses c8 and NODE_V8_COVERAGE to collect coverage from spawned processes.\n */\n\nimport { spawn } from 'node:child_process';\nimport { mkdtemp, rm, access } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join, resolve } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport type { CoverageContext, CoverageConfig } from './types.js';\nimport { resolveCoverageConfig } from './config.js';\n\n/**\n * Find the c8 executable path.\n * Checks local node_modules/.bin first, then falls back to npx.\n */\nfunction findC8Path(): string {\n // Check common locations for local c8\n const localPaths = [\n resolve(process.cwd(), 'node_modules', '.bin', 'c8'),\n resolve(process.cwd(), '..', '..', 'node_modules', '.bin', 'c8'), // monorepo root\n ];\n\n for (const localPath of localPaths) {\n if (existsSync(localPath)) {\n return localPath;\n }\n }\n\n // Fall back to npx which will find c8 in node_modules\n return 'npx c8';\n}\n\n/**\n * Check if c8 is available in the current environment.\n */\nexport async function isC8Available(): Promise<boolean> {\n const c8Path = findC8Path();\n\n return new Promise((resolve) => {\n // Use npx to run c8 if we fell back to npx\n const isNpx = c8Path === 'npx c8';\n const command = isNpx ? 'npx' : c8Path;\n const args = isNpx ? ['c8', '--version'] : ['--version'];\n\n const proc = spawn(command, args, {\n shell: false,\n stdio: 'ignore',\n });\n proc.on('close', (code) => {\n resolve(code === 0);\n });\n proc.on('error', () => {\n resolve(false);\n });\n });\n}\n\n/**\n * Create a coverage context for collecting V8 coverage data.\n */\nexport async function createCoverageContext(config?: CoverageConfig): Promise<CoverageContext> {\n const options = resolveCoverageConfig(config);\n const tempDir = await mkdtemp(join(tmpdir(), 'tryscript-coverage-'));\n\n return {\n tempDir,\n options,\n };\n}\n\n/**\n * Get environment variables for enabling V8 coverage in spawned processes.\n */\nexport function getCoverageEnv(ctx: CoverageContext): Record<string, string> {\n return {\n NODE_V8_COVERAGE: ctx.tempDir,\n };\n}\n\n/**\n * Generate coverage report from collected V8 coverage data using c8.\n * Throws an error if coverage report generation fails.\n */\nexport async function generateCoverageReport(ctx: CoverageContext): Promise<void> {\n const { options, tempDir } = ctx;\n const c8Path = findC8Path();\n\n // Base args for c8 report\n const reportArgs = [\n 'report',\n '--temp-directory',\n tempDir,\n '--reports-dir',\n options.reportsDir,\n '--src',\n options.src,\n '--all',\n ...options.include.flatMap((pattern) => ['--include', pattern]),\n ...options.reporters.flatMap((reporter) => ['--reporter', reporter]),\n ];\n\n // Handle 'npx c8' vs direct c8 path\n // Use shell: false to prevent glob expansion of patterns like dist/**\n const isNpx = c8Path === 'npx c8';\n const command = isNpx ? 'npx' : c8Path;\n const args = isNpx ? ['c8', ...reportArgs] : reportArgs;\n\n await new Promise<void>((resolvePromise, reject) => {\n const proc = spawn(command, args, {\n shell: false,\n stdio: 'inherit',\n });\n\n proc.on('close', (code) => {\n if (code === 0) {\n resolvePromise();\n } else {\n reject(new Error(`c8 report exited with code ${code}`));\n }\n });\n\n proc.on('error', (err) => {\n reject(new Error(`Failed to run c8 report: ${err.message}`));\n });\n });\n}\n\n/**\n * Clean up coverage context by removing the temporary directory.\n */\nexport async function cleanupCoverageContext(ctx: CoverageContext): Promise<void> {\n try {\n await access(ctx.tempDir);\n await rm(ctx.tempDir, { recursive: true, force: true });\n } catch {\n // Directory doesn't exist, nothing to clean up\n }\n}\n","/**\n * Run command - executes golden tests against CLI applications.\n *\n * Supports filtering, update mode, and detailed diff output for failures.\n */\n\nimport type { Command } from 'commander';\n\nimport { readFile } from 'node:fs/promises';\nimport fg from 'fast-glob';\nimport { loadConfig, mergeConfig } from '../../lib/config.js';\nimport { logWarn, logError, colors, status as statusIndicators } from '../lib/shared.js';\nimport { parseTestFile } from '../../lib/parser.js';\nimport {\n runBlock,\n createExecutionContext,\n cleanupExecutionContext,\n runAfterHook,\n} from '../../lib/runner.js';\nimport { matchOutput } from '../../lib/matcher.js';\nimport { createDiff, reportFile, reportSummary } from '../../lib/reporter.js';\nimport { updateTestFile } from '../../lib/updater.js';\nimport {\n isC8Available,\n createCoverageContext,\n getCoverageEnv,\n generateCoverageReport,\n cleanupCoverageContext,\n} from '../../lib/coverage.js';\nimport type {\n TestBlockResult,\n TestFileResult,\n TestRunSummary,\n CoverageContext,\n} from '../../lib/types.js';\n\ninterface RunOptions {\n update?: boolean;\n diff?: boolean;\n failFast?: boolean;\n filter?: string;\n verbose?: boolean;\n quiet?: boolean;\n coverage?: boolean;\n coverageDir?: string;\n coverageReporter?: string[];\n}\n\n/**\n * Register the run command.\n */\nexport function registerRunCommand(program: Command): void {\n program\n .command('run')\n .description('Run golden tests')\n .argument('[files...]', 'Test files to run (default: **/*.tryscript.md)')\n .option('--update', 'Update golden files with actual output')\n .option('--diff', 'Show diff on failure (default: true)')\n .option('--no-diff', 'Hide diff on failure')\n .option('--fail-fast', 'Stop on first failure')\n .option('--filter <pattern>', 'Filter tests by name pattern')\n .option('--verbose', 'Show detailed output including passing test output')\n .option('--quiet', 'Suppress non-essential output (only show failures)')\n .option('--coverage', 'Enable code coverage collection (requires c8)')\n .option('--coverage-dir <dir>', 'Coverage output directory (default: coverage-tryscript)')\n .option(\n '--coverage-reporter <reporter...>',\n 'Coverage reporters (default: text, html). Can be specified multiple times.',\n )\n .action(runCommand);\n}\n\nasync function runCommand(files: string[], options: RunOptions): Promise<void> {\n const startTime = Date.now();\n\n // Default options\n const opts = {\n diff: options.diff !== false,\n verbose: options.verbose ?? false,\n quiet: options.quiet ?? false,\n update: options.update ?? false,\n failFast: options.failFast ?? false,\n filter: options.filter,\n };\n\n // Find test files (fast-glob respects .gitignore by default)\n const patterns = files.length > 0 ? files : ['**/*.tryscript.md'];\n const testFiles = await fg(patterns, {\n ignore: ['**/node_modules/**', '**/dist/**'],\n absolute: true,\n dot: false,\n });\n\n if (testFiles.length === 0) {\n logWarn('No test files found');\n process.exit(1);\n }\n\n // Load global config\n const globalConfig = await loadConfig(process.cwd());\n\n // Setup coverage if enabled\n let coverageCtx: CoverageContext | undefined;\n let coverageEnv: Record<string, string> = {};\n\n if (options.coverage) {\n // Check if c8 is available\n const c8Available = await isC8Available();\n if (!c8Available) {\n logError('Coverage requires c8. Install with: npm install -D c8');\n process.exit(1);\n }\n\n // Create coverage context with CLI options overriding config\n coverageCtx = await createCoverageContext({\n ...globalConfig.coverage,\n reportsDir: options.coverageDir ?? globalConfig.coverage?.reportsDir,\n reporters: options.coverageReporter ?? globalConfig.coverage?.reporters,\n });\n coverageEnv = getCoverageEnv(coverageCtx);\n }\n\n // Run tests\n const fileResults: TestFileResult[] = [];\n let shouldStop = false;\n\n for (const filePath of testFiles) {\n if (shouldStop) {\n break;\n }\n\n const content = await readFile(filePath, 'utf-8');\n const testFile = parseTestFile(content, filePath);\n const config = mergeConfig(globalConfig, testFile.config);\n\n // Filter blocks by name if specified\n let blocksToRun = testFile.blocks;\n if (opts.filter) {\n const filterPattern = new RegExp(opts.filter, 'i');\n blocksToRun = blocksToRun.filter((b) => (b.name ? filterPattern.test(b.name) : true));\n }\n\n // Handle \"only\" mode - if any block has only=true, run only those\n const onlyBlocks = blocksToRun.filter((b) => b.only);\n if (onlyBlocks.length > 0) {\n blocksToRun = onlyBlocks;\n }\n\n if (blocksToRun.length === 0) {\n continue;\n }\n\n const ctx = await createExecutionContext(config, filePath, coverageEnv);\n const results: TestBlockResult[] = [];\n\n try {\n for (const block of blocksToRun) {\n const result = await runBlock(block, ctx);\n\n // Skip checking for skipped tests\n if (result.skipped) {\n results.push(result);\n continue;\n }\n\n // Check if output matches expected\n // [ROOT] = test file directory, [CWD] = command working directory\n // If expectedStderr is set, compare stdout only (not combined output)\n const outputToCheck = block.expectedStderr\n ? (result.actualStdout ?? '')\n : result.actualOutput;\n const outputMatches = matchOutput(\n outputToCheck,\n block.expectedOutput,\n { root: ctx.testDir, cwd: ctx.cwd },\n config.patterns ?? {},\n );\n\n // Check stderr if expected (using actualStderr if available)\n let stderrMatches = true;\n if (block.expectedStderr) {\n stderrMatches = matchOutput(\n result.actualStderr ?? '',\n block.expectedStderr,\n { root: ctx.testDir, cwd: ctx.cwd },\n config.patterns ?? {},\n );\n }\n\n const exitCodeMatches = result.actualExitCode === block.expectedExitCode;\n result.passed = outputMatches && stderrMatches && exitCodeMatches && !result.error;\n\n if (!result.passed && opts.diff) {\n result.diff = createDiff(\n block.expectedOutput,\n result.actualOutput,\n `${filePath}:${block.lineNumber}`,\n );\n }\n\n results.push(result);\n\n if (!result.passed && opts.failFast) {\n shouldStop = true;\n break;\n }\n }\n\n // Run after hook if configured\n await runAfterHook(ctx);\n } finally {\n await cleanupExecutionContext(ctx);\n }\n\n const fileResult: TestFileResult = {\n file: testFile,\n results,\n passed: results.every((r) => r.passed),\n duration: results.reduce((sum, r) => sum + r.duration, 0),\n };\n\n fileResults.push(fileResult);\n reportFile(fileResult, opts);\n\n // Update mode\n if (opts.update && !fileResult.passed) {\n const { updated, changes } = await updateTestFile(testFile, results);\n if (updated) {\n console.error(colors.warn(` ${statusIndicators.update} Updated: ${changes.join(', ')}`));\n }\n }\n }\n\n // Summary\n const summary: TestRunSummary = {\n files: fileResults,\n totalPassed: fileResults.reduce((sum, f) => sum + f.results.filter((r) => r.passed).length, 0),\n totalFailed: fileResults.reduce((sum, f) => sum + f.results.filter((r) => !r.passed).length, 0),\n totalBlocks: fileResults.reduce((sum, f) => sum + f.results.length, 0),\n duration: Date.now() - startTime,\n };\n\n reportSummary(summary, opts);\n\n // Generate coverage report if enabled\n if (coverageCtx) {\n console.error('\\nGenerating coverage report...');\n try {\n await generateCoverageReport(coverageCtx);\n console.error(\n colors.success(`Coverage report written to ${coverageCtx.options.reportsDir}/`),\n );\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logError(`Failed to generate coverage report: ${message}`);\n } finally {\n await cleanupCoverageContext(coverageCtx);\n }\n }\n\n // Exit code\n process.exit(summary.totalFailed > 0 ? 1 : 0);\n}\n","/**\n * Readme command - Display the README documentation.\n *\n * Shows the package README.md, formatted for the terminal when interactive,\n * or as plain text when piped.\n */\n\nimport type { Command } from 'commander';\n\nimport { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport pc from 'picocolors';\n\n/**\n * Get the path to the README.md file.\n * Works both during development and when installed as a package.\n */\nfunction getReadmePath(): string {\n const thisDir = dirname(fileURLToPath(import.meta.url));\n const dirName = thisDir.split(/[/\\\\]/).pop();\n\n if (dirName === 'dist') {\n // Bundled: dist -> package root -> README.md\n return join(dirname(thisDir), 'README.md');\n }\n\n // Development: src/cli/commands -> src/cli -> src -> package root -> README.md\n return join(dirname(dirname(dirname(thisDir))), 'README.md');\n}\n\n/**\n * Load the README content.\n */\nfunction loadReadme(): string {\n const readmePath = getReadmePath();\n try {\n return readFileSync(readmePath, 'utf-8');\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to load README from ${readmePath}: ${message}`);\n }\n}\n\n/**\n * Apply basic terminal formatting to markdown content.\n * Colorizes headers, code blocks, and other elements for better readability.\n */\nfunction formatMarkdown(content: string, useColors: boolean): string {\n if (!useColors) {\n return content;\n }\n\n const lines = content.split('\\n');\n const formatted: string[] = [];\n let inCodeBlock = false;\n\n for (const line of lines) {\n // Track code blocks\n if (line.startsWith('```')) {\n inCodeBlock = !inCodeBlock;\n formatted.push(pc.dim(line));\n continue;\n }\n\n if (inCodeBlock) {\n formatted.push(pc.dim(line));\n continue;\n }\n\n // Headers\n if (line.startsWith('# ')) {\n formatted.push(pc.bold(pc.cyan(line)));\n continue;\n }\n if (line.startsWith('## ')) {\n formatted.push(pc.bold(pc.blue(line)));\n continue;\n }\n if (line.startsWith('### ')) {\n formatted.push(pc.bold(line));\n continue;\n }\n\n // Inline code (backticks)\n let formattedLine = line.replace(/`([^`]+)`/g, (_match, code: string) => {\n return pc.yellow(code);\n });\n\n // Bold text\n formattedLine = formattedLine.replace(/\\*\\*([^*]+)\\*\\*/g, (_match, text: string) => {\n return pc.bold(text);\n });\n\n // Links - show text in cyan, URL dimmed\n formattedLine = formattedLine.replace(\n /\\[([^\\]]+)\\]\\(([^)]+)\\)/g,\n (_match, text: string, url: string) => {\n return `${pc.cyan(text)} ${pc.dim(`(${url})`)}`;\n },\n );\n\n formatted.push(formattedLine);\n }\n\n return formatted.join('\\n');\n}\n\n/**\n * Check if stdout is an interactive terminal.\n */\nfunction isInteractive(): boolean {\n return process.stdout.isTTY === true;\n}\n\n/**\n * Display the README content.\n * Exported for use as the default command.\n */\nexport function showReadme(options?: { raw?: boolean }): void {\n try {\n const readme = loadReadme();\n\n // Determine if we should colorize\n const shouldColorize = !options?.raw && isInteractive();\n\n const formatted = formatMarkdown(readme, shouldColorize);\n console.log(formatted);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(pc.red(`Error: ${message}`));\n process.exit(1);\n }\n}\n\n/**\n * Register the readme command.\n */\nexport function registerReadmeCommand(program: Command): void {\n program\n .command('readme')\n .description('Display README documentation')\n .option('--raw', 'Output raw markdown without formatting')\n .action(showReadme);\n}\n","/**\n * Docs command - Display the tryscript quick reference.\n *\n * Shows the tryscript-reference.md file, formatted for the terminal when interactive,\n * or as plain text when piped.\n */\n\nimport type { Command } from 'commander';\n\nimport { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport pc from 'picocolors';\n\n/**\n * Get the path to the tryscript-reference.md file.\n * Works both during development and when installed as a package.\n */\nfunction getDocsPath(): string {\n const thisDir = dirname(fileURLToPath(import.meta.url));\n const dirName = thisDir.split(/[/\\\\]/).pop();\n\n if (dirName === 'dist') {\n // Bundled: dist -> package root -> docs/tryscript-reference.md\n return join(dirname(thisDir), 'docs', 'tryscript-reference.md');\n }\n\n // Development: src/cli/commands -> src/cli -> src -> package root -> docs/tryscript-reference.md\n return join(dirname(dirname(dirname(thisDir))), 'docs', 'tryscript-reference.md');\n}\n\n/**\n * Load the docs content.\n */\nfunction loadDocs(): string {\n const docsPath = getDocsPath();\n try {\n return readFileSync(docsPath, 'utf-8');\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to load reference docs from ${docsPath}: ${message}`);\n }\n}\n\n/**\n * Apply basic terminal formatting to markdown content.\n * Colorizes headers, code blocks, and other elements for better readability.\n */\nfunction formatMarkdown(content: string, useColors: boolean): string {\n if (!useColors) {\n return content;\n }\n\n const lines = content.split('\\n');\n const formatted: string[] = [];\n let inCodeBlock = false;\n\n for (const line of lines) {\n // Track code blocks\n if (line.startsWith('```')) {\n inCodeBlock = !inCodeBlock;\n formatted.push(pc.dim(line));\n continue;\n }\n\n if (inCodeBlock) {\n formatted.push(pc.dim(line));\n continue;\n }\n\n // Headers\n if (line.startsWith('# ')) {\n formatted.push(pc.bold(pc.cyan(line)));\n continue;\n }\n if (line.startsWith('## ')) {\n formatted.push(pc.bold(pc.blue(line)));\n continue;\n }\n if (line.startsWith('### ')) {\n formatted.push(pc.bold(line));\n continue;\n }\n\n // Inline code (backticks)\n let formattedLine = line.replace(/`([^`]+)`/g, (_match, code: string) => {\n return pc.yellow(code);\n });\n\n // Bold text\n formattedLine = formattedLine.replace(/\\*\\*([^*]+)\\*\\*/g, (_match, text: string) => {\n return pc.bold(text);\n });\n\n // Links - show text in cyan, URL dimmed\n formattedLine = formattedLine.replace(\n /\\[([^\\]]+)\\]\\(([^)]+)\\)/g,\n (_match, text: string, url: string) => {\n return `${pc.cyan(text)} ${pc.dim(`(${url})`)}`;\n },\n );\n\n formatted.push(formattedLine);\n }\n\n return formatted.join('\\n');\n}\n\n/**\n * Check if stdout is an interactive terminal.\n */\nfunction isInteractive(): boolean {\n return process.stdout.isTTY === true;\n}\n\n/**\n * Register the docs command.\n */\nexport function registerDocsCommand(program: Command): void {\n program\n .command('docs')\n .description('Display concise syntax reference')\n .option('--raw', 'Output raw markdown without formatting')\n .action((options: { raw?: boolean }) => {\n try {\n const docs = loadDocs();\n\n // Determine if we should colorize\n const shouldColorize = !options.raw && isInteractive();\n\n const formatted = formatMarkdown(docs, shouldColorize);\n console.log(formatted);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(pc.red(`Error: ${message}`));\n process.exit(1);\n }\n });\n}\n","/**\n * CLI entry point for tryscript.\n *\n * Configures Commander.js with colored help and registers all subcommands.\n */\n\nimport { Command } from 'commander';\nimport { VERSION } from '../index.js';\nimport { registerRunCommand } from './commands/run.js';\nimport { registerReadmeCommand } from './commands/readme.js';\nimport { registerDocsCommand } from './commands/docs.js';\nimport { withColoredHelp, logError } from './lib/shared.js';\n\nexport function run(argv: string[]): void {\n const program = withColoredHelp(\n new Command()\n .name('tryscript')\n .version(VERSION, '--version', 'Show version number')\n .description('Golden testing for CLI applications')\n .showHelpAfterError('(use --help for usage)'),\n );\n\n // Register subcommands\n registerRunCommand(program);\n registerReadmeCommand(program);\n registerDocsCommand(program);\n\n // Default action: show help when no command given\n program.action(() => {\n program.help();\n });\n\n program.parseAsync(argv).catch((err: Error) => {\n logError(`Error: ${err.message}`);\n process.exit(2);\n });\n}\n","#!/usr/bin/env node\nimport { run } from './cli/cli.js';\n\nrun(process.argv);\n"],"mappings":"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"}
1
+ {"version":3,"file":"bin.mjs","names":["status","parts: string[]","changes: string[]","lines: string[]","findC8Path","runCommand","coverageCtx: CoverageContext | undefined","coverageEnv: Record<string, string>","fileResults: TestFileResult[]","results: TestBlockResult[]","fileResult: TestFileResult","statusIndicators","summary: TestRunSummary","parsedOptions: CoverageOptions","formatMarkdown","formatted: string[]","isInteractive","formatted: string[]"],"sources":["../src/cli/lib/shared.ts","../src/lib/reporter.ts","../src/lib/updater.ts","../src/lib/coverage.ts","../src/cli/commands/run.ts","../src/cli/commands/coverage.ts","../src/cli/commands/readme.ts","../src/cli/commands/docs.ts","../src/cli/cli.ts","../src/bin.ts"],"sourcesContent":["/**\n * Shared CLI utilities for consistent output formatting and color usage.\n *\n * This module provides:\n * - Color utilities via picocolors\n * - Commander.js help text styling\n * - Logging helpers for consistent output\n */\n\nimport type { Command } from 'commander';\nimport pc from 'picocolors';\n\n/**\n * Shared color utilities for consistent terminal output.\n */\nexport const colors = {\n success: (s: string) => pc.green(s),\n error: (s: string) => pc.red(s),\n warn: (s: string) => pc.yellow(s),\n info: (s: string) => pc.cyan(s),\n};\n\n/**\n * Status indicators with emoji.\n */\nexport const status = {\n pass: pc.green('✓'),\n fail: pc.red('✗'),\n skip: pc.yellow('○'),\n update: pc.yellow('↻'),\n};\n\n/**\n * Configure Commander.js with colored help text.\n * Applies consistent styling: cyan titles, green commands, yellow options.\n */\nexport function withColoredHelp<T extends Command>(cmd: T): T {\n cmd.configureHelp({\n styleTitle: (str) => pc.bold(pc.cyan(str)),\n styleCommandText: (str) => pc.green(str),\n styleOptionText: (str) => pc.yellow(str),\n showGlobalOptions: true,\n });\n return cmd;\n}\n\n/**\n * Format a duration in milliseconds for display.\n */\nexport function formatDuration(ms: number): string {\n if (ms < 1000) {\n return `${ms}ms`;\n }\n return `${(ms / 1000).toFixed(2)}s`;\n}\n\n/**\n * Log a warning message to stderr.\n */\nexport function logWarn(message: string): void {\n console.error(colors.warn(message));\n}\n\n/**\n * Log an error message to stderr.\n */\nexport function logError(message: string): void {\n console.error(colors.error(message));\n}\n","/**\n * Test result reporting utilities.\n *\n * Handles output formatting for test results, diffs, and summaries.\n */\n\nimport pc from 'picocolors';\nimport { createPatch } from 'diff';\nimport type { TestFileResult, TestRunSummary } from './types.js';\n\nexport interface ReporterOptions {\n diff: boolean;\n verbose: boolean;\n quiet: boolean;\n}\n\n// Status indicators for consistent output\nconst statusIcon = {\n pass: pc.green('✓'),\n fail: pc.red('✗'),\n};\n\n/**\n * Format a duration in milliseconds for display.\n */\nfunction formatDuration(ms: number): string {\n if (ms < 1000) {\n return `${ms}ms`;\n }\n return `${(ms / 1000).toFixed(2)}s`;\n}\n\n/**\n * Create a unified diff between expected and actual output.\n */\nexport function createDiff(expected: string, actual: string, filename: string): string {\n const patch = createPatch(filename, expected, actual, 'expected', 'actual');\n // Remove the header lines (first 4 lines)\n const lines = patch.split('\\n').slice(4);\n return lines\n .map((line) => {\n if (line.startsWith('+')) {\n return pc.green(line);\n }\n if (line.startsWith('-')) {\n return pc.red(line);\n }\n if (line.startsWith('@')) {\n return pc.cyan(line);\n }\n return line;\n })\n .join('\\n');\n}\n\n/**\n * Report results for a single file.\n */\nexport function reportFile(result: TestFileResult, options: ReporterOptions): void {\n const filename = result.file.path;\n const status = result.passed ? pc.green(pc.bold('PASS')) : pc.red(pc.bold('FAIL'));\n\n if (options.quiet && result.passed) {\n return;\n }\n\n // File header\n console.error(`${status} ${filename}`);\n\n // Individual block results\n for (const blockResult of result.results) {\n const name = blockResult.block.name ?? `Line ${blockResult.block.lineNumber}`;\n\n if (blockResult.passed) {\n if (!options.quiet) {\n console.error(` ${statusIcon.pass} ${name}`);\n }\n } else {\n console.error(` ${statusIcon.fail} ${name}`);\n\n // Show error details\n if (blockResult.error) {\n console.error(` ${pc.red(blockResult.error)}`);\n } else {\n // Exit code mismatch\n if (blockResult.actualExitCode !== blockResult.block.expectedExitCode) {\n console.error(\n ` Expected exit code ${blockResult.block.expectedExitCode}, got ${blockResult.actualExitCode}`,\n );\n }\n\n // Output mismatch with diff\n if (options.diff && blockResult.diff) {\n console.error('');\n console.error(blockResult.diff);\n }\n }\n }\n }\n\n console.error('');\n}\n\n/**\n * Report final summary.\n */\nexport function reportSummary(summary: TestRunSummary, _options: ReporterOptions): void {\n const parts: string[] = [];\n\n if (summary.totalPassed > 0) {\n parts.push(pc.green(`${summary.totalPassed} passed`));\n }\n if (summary.totalFailed > 0) {\n parts.push(pc.red(`${summary.totalFailed} failed`));\n }\n\n const duration = formatDuration(summary.duration);\n const line = `${parts.join(', ')} (${duration})`;\n\n // Summary goes to stdout (can be piped/parsed)\n console.log(line);\n}\n","import { writeFile } from 'atomically';\nimport type { TestFile, TestBlock, TestBlockResult } from './types.js';\n\n/**\n * Update a test file with actual output from test results.\n */\nexport async function updateTestFile(\n file: TestFile,\n results: TestBlockResult[],\n): Promise<{ updated: boolean; changes: string[] }> {\n let content = file.rawContent;\n const changes: string[] = [];\n\n // Process blocks in reverse order to maintain correct offsets\n const blocksWithResults = file.blocks\n .map((block, i) => ({ block, result: results[i] }))\n .reverse();\n\n for (const { block, result } of blocksWithResults) {\n if (!result) {\n continue;\n }\n\n if (result.passed) {\n continue; // Don't touch passing tests\n }\n\n if (result.error) {\n // Execution error, can't update\n continue;\n }\n\n // Build the new block content\n const newBlockContent = buildUpdatedBlock(block, result);\n\n // Find and replace the block in the file\n const blockStart = content.indexOf(block.rawContent);\n if (blockStart !== -1) {\n content =\n content.slice(0, blockStart) +\n newBlockContent +\n content.slice(blockStart + block.rawContent.length);\n\n changes.push(block.name ?? `Line ${block.lineNumber}`);\n }\n }\n\n if (changes.length > 0) {\n await writeFile(file.path, content);\n }\n\n return { updated: changes.length > 0, changes };\n}\n\n/**\n * Build an updated console block with new expected output.\n */\nfunction buildUpdatedBlock(block: TestBlock, result: TestBlockResult): string {\n // Reconstruct the command line(s)\n const commandLines = block.command.split('\\n').map((line, i) => {\n return i === 0 ? `$ ${line}` : `> ${line}`;\n });\n\n // Build the block\n const lines: string[] = ['```console', ...commandLines];\n\n // Add output if present\n const trimmedOutput = result.actualOutput.trimEnd();\n if (trimmedOutput) {\n lines.push(trimmedOutput);\n }\n\n // Add exit code\n lines.push(`? ${result.actualExitCode}`, '```');\n\n return lines.join('\\n');\n}\n","/**\n * Coverage collection for CLI subprocess testing.\n *\n * Uses c8 and NODE_V8_COVERAGE to collect coverage from spawned processes.\n */\n\nimport { spawn } from 'node:child_process';\nimport { mkdtemp, rm, access } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join, resolve } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport type { CoverageContext, CoverageConfig } from './types.js';\nimport { resolveCoverageConfig } from './config.js';\n\n/**\n * Find the c8 executable path.\n * Checks local node_modules/.bin first, then falls back to npx.\n */\nfunction findC8Path(): string {\n // Check common locations for local c8\n const localPaths = [\n resolve(process.cwd(), 'node_modules', '.bin', 'c8'),\n resolve(process.cwd(), '..', '..', 'node_modules', '.bin', 'c8'), // monorepo root\n ];\n\n for (const localPath of localPaths) {\n if (existsSync(localPath)) {\n return localPath;\n }\n }\n\n // Fall back to npx which will find c8 in node_modules\n return 'npx c8';\n}\n\n/**\n * Check if c8 is available in the current environment.\n */\nexport async function isC8Available(): Promise<boolean> {\n const c8Path = findC8Path();\n\n return new Promise((resolve) => {\n // Use npx to run c8 if we fell back to npx\n const isNpx = c8Path === 'npx c8';\n const command = isNpx ? 'npx' : c8Path;\n const args = isNpx ? ['c8', '--version'] : ['--version'];\n\n const proc = spawn(command, args, {\n shell: false,\n stdio: 'ignore',\n });\n proc.on('close', (code) => {\n resolve(code === 0);\n });\n proc.on('error', () => {\n resolve(false);\n });\n });\n}\n\n/**\n * Create a coverage context for collecting V8 coverage data.\n */\nexport async function createCoverageContext(config?: CoverageConfig): Promise<CoverageContext> {\n const options = resolveCoverageConfig(config);\n const tempDir = await mkdtemp(join(tmpdir(), 'tryscript-coverage-'));\n\n return {\n tempDir,\n options,\n };\n}\n\n/**\n * Get environment variables for enabling V8 coverage in spawned processes.\n */\nexport function getCoverageEnv(ctx: CoverageContext): Record<string, string> {\n return {\n NODE_V8_COVERAGE: ctx.tempDir,\n };\n}\n\n/**\n * Generate coverage report from collected V8 coverage data using c8.\n * Throws an error if coverage report generation fails.\n */\nexport async function generateCoverageReport(ctx: CoverageContext): Promise<void> {\n const { options, tempDir } = ctx;\n const c8Path = findC8Path();\n\n // Base args for c8 report\n const reportArgs = [\n 'report',\n '--temp-directory',\n tempDir,\n '--reports-dir',\n options.reportsDir,\n '--src',\n options.src,\n '--all',\n // Include patterns\n ...options.include.flatMap((pattern) => ['--include', pattern]),\n // Exclude patterns\n ...options.exclude.flatMap((pattern) => ['--exclude', pattern]),\n // Boolean flags (only add if explicitly set)\n ...(options.excludeNodeModules ? ['--exclude-node-modules'] : ['--no-exclude-node-modules']),\n ...(options.excludeAfterRemap ? ['--exclude-after-remap'] : []),\n ...(options.skipFull ? ['--skip-full'] : []),\n ...(options.allowExternal ? ['--allowExternal'] : []),\n ...(options.monocart ? ['--experimental-monocart'] : []),\n // Reporters\n ...options.reporters.flatMap((reporter) => ['--reporter', reporter]),\n ];\n\n // Handle 'npx c8' vs direct c8 path\n // Use shell: false to prevent glob expansion of patterns like dist/**\n const isNpx = c8Path === 'npx c8';\n const command = isNpx ? 'npx' : c8Path;\n const args = isNpx ? ['c8', ...reportArgs] : reportArgs;\n\n await new Promise<void>((resolvePromise, reject) => {\n const proc = spawn(command, args, {\n shell: false,\n stdio: 'inherit',\n });\n\n proc.on('close', (code) => {\n if (code === 0) {\n resolvePromise();\n } else {\n reject(new Error(`c8 report exited with code ${code}`));\n }\n });\n\n proc.on('error', (err) => {\n reject(new Error(`Failed to run c8 report: ${err.message}`));\n });\n });\n}\n\n/**\n * Clean up coverage context by removing the temporary directory.\n */\nexport async function cleanupCoverageContext(ctx: CoverageContext): Promise<void> {\n try {\n await access(ctx.tempDir);\n await rm(ctx.tempDir, { recursive: true, force: true });\n } catch {\n // Directory doesn't exist, nothing to clean up\n }\n}\n","/**\n * Run command - executes golden tests against CLI applications.\n *\n * Supports filtering, update mode, and detailed diff output for failures.\n */\n\nimport type { Command } from 'commander';\n\nimport { readFile } from 'node:fs/promises';\nimport fg from 'fast-glob';\nimport { loadConfig, mergeConfig } from '../../lib/config.js';\nimport { logWarn, logError, colors, status as statusIndicators } from '../lib/shared.js';\nimport { parseTestFile } from '../../lib/parser.js';\nimport {\n runBlock,\n createExecutionContext,\n cleanupExecutionContext,\n runAfterHook,\n} from '../../lib/runner.js';\nimport { matchOutput } from '../../lib/matcher.js';\nimport { createDiff, reportFile, reportSummary } from '../../lib/reporter.js';\nimport { updateTestFile } from '../../lib/updater.js';\nimport {\n isC8Available,\n createCoverageContext,\n getCoverageEnv,\n generateCoverageReport,\n cleanupCoverageContext,\n} from '../../lib/coverage.js';\nimport type {\n TestBlockResult,\n TestFileResult,\n TestRunSummary,\n CoverageContext,\n} from '../../lib/types.js';\n\ninterface RunOptions {\n update?: boolean;\n diff?: boolean;\n failFast?: boolean;\n filter?: string;\n verbose?: boolean;\n quiet?: boolean;\n coverage?: boolean;\n coverageDir?: string;\n coverageReporter?: string[];\n coverageExclude?: string[];\n coverageExcludeNodeModules?: boolean;\n coverageExcludeAfterRemap?: boolean;\n coverageSkipFull?: boolean;\n coverageAllowExternal?: boolean;\n coverageMonocart?: boolean;\n}\n\n/**\n * Register the run command.\n */\nexport function registerRunCommand(program: Command): void {\n program\n .command('run')\n .description('Run golden tests')\n .argument('[files...]', 'Test files to run (default: **/*.tryscript.md)')\n .option('--update', 'Update golden files with actual output')\n .option('--diff', 'Show diff on failure (default: true)')\n .option('--no-diff', 'Hide diff on failure')\n .option('--fail-fast', 'Stop on first failure')\n .option('--filter <pattern>', 'Filter tests by name pattern')\n .option('--verbose', 'Show detailed output including passing test output')\n .option('--quiet', 'Suppress non-essential output (only show failures)')\n .option('--coverage', 'Enable code coverage collection (requires c8)')\n .option('--coverage-dir <dir>', 'Coverage output directory (default: coverage-tryscript)')\n .option(\n '--coverage-reporter <reporter...>',\n 'Coverage reporters (default: text, html). Can be specified multiple times.',\n )\n .option(\n '--coverage-exclude <pattern...>',\n 'Patterns to exclude from coverage (c8 --exclude). Can be specified multiple times.',\n )\n .option(\n '--coverage-exclude-node-modules',\n 'Exclude node_modules from coverage (c8 --exclude-node-modules, default: true)',\n )\n .option(\n '--no-coverage-exclude-node-modules',\n 'Include node_modules in coverage (c8 --no-exclude-node-modules)',\n )\n .option(\n '--coverage-exclude-after-remap',\n 'Apply exclude logic after sourcemap remapping (c8 --exclude-after-remap)',\n )\n .option('--coverage-skip-full', 'Hide files with 100% coverage (c8 --skip-full)')\n .option('--coverage-allow-external', 'Allow files from outside cwd (c8 --allowExternal)')\n .option(\n '--coverage-monocart',\n 'Use monocart for accurate line counts, better for merging with vitest (c8 --experimental-monocart)',\n )\n .action(runCommand);\n}\n\nasync function runCommand(files: string[], options: RunOptions): Promise<void> {\n const startTime = Date.now();\n\n // Default options\n const opts = {\n diff: options.diff !== false,\n verbose: options.verbose ?? false,\n quiet: options.quiet ?? false,\n update: options.update ?? false,\n failFast: options.failFast ?? false,\n filter: options.filter,\n };\n\n // Find test files (fast-glob respects .gitignore by default)\n const patterns = files.length > 0 ? files : ['**/*.tryscript.md'];\n const testFiles = await fg(patterns, {\n ignore: ['**/node_modules/**', '**/dist/**'],\n absolute: true,\n dot: false,\n });\n\n if (testFiles.length === 0) {\n logWarn('No test files found');\n process.exit(1);\n }\n\n // Load global config\n const globalConfig = await loadConfig(process.cwd());\n\n // Setup coverage if enabled\n let coverageCtx: CoverageContext | undefined;\n let coverageEnv: Record<string, string> = {};\n\n if (options.coverage) {\n // Check if c8 is available\n const c8Available = await isC8Available();\n if (!c8Available) {\n logError('Coverage requires c8. Install with: npm install -D c8');\n process.exit(1);\n }\n\n // Create coverage context with CLI options overriding config\n coverageCtx = await createCoverageContext({\n ...globalConfig.coverage,\n reportsDir: options.coverageDir ?? globalConfig.coverage?.reportsDir,\n reporters: options.coverageReporter ?? globalConfig.coverage?.reporters,\n exclude: options.coverageExclude ?? globalConfig.coverage?.exclude,\n excludeNodeModules:\n options.coverageExcludeNodeModules ?? globalConfig.coverage?.excludeNodeModules,\n excludeAfterRemap:\n options.coverageExcludeAfterRemap ?? globalConfig.coverage?.excludeAfterRemap,\n skipFull: options.coverageSkipFull ?? globalConfig.coverage?.skipFull,\n allowExternal: options.coverageAllowExternal ?? globalConfig.coverage?.allowExternal,\n monocart: options.coverageMonocart ?? globalConfig.coverage?.monocart,\n });\n coverageEnv = getCoverageEnv(coverageCtx);\n }\n\n // Run tests\n const fileResults: TestFileResult[] = [];\n let shouldStop = false;\n\n for (const filePath of testFiles) {\n if (shouldStop) {\n break;\n }\n\n const content = await readFile(filePath, 'utf-8');\n const testFile = parseTestFile(content, filePath);\n const config = mergeConfig(globalConfig, testFile.config);\n\n // Filter blocks by name if specified\n let blocksToRun = testFile.blocks;\n if (opts.filter) {\n const filterPattern = new RegExp(opts.filter, 'i');\n blocksToRun = blocksToRun.filter((b) => (b.name ? filterPattern.test(b.name) : true));\n }\n\n // Handle \"only\" mode - if any block has only=true, run only those\n const onlyBlocks = blocksToRun.filter((b) => b.only);\n if (onlyBlocks.length > 0) {\n blocksToRun = onlyBlocks;\n }\n\n if (blocksToRun.length === 0) {\n continue;\n }\n\n const ctx = await createExecutionContext(config, filePath, coverageEnv);\n const results: TestBlockResult[] = [];\n\n try {\n for (const block of blocksToRun) {\n const result = await runBlock(block, ctx);\n\n // Skip checking for skipped tests\n if (result.skipped) {\n results.push(result);\n continue;\n }\n\n // Check if output matches expected\n // [ROOT] = test file directory, [CWD] = command working directory\n // If expectedStderr is set, compare stdout only (not combined output)\n const outputToCheck = block.expectedStderr\n ? (result.actualStdout ?? '')\n : result.actualOutput;\n const outputMatches = matchOutput(\n outputToCheck,\n block.expectedOutput,\n { root: ctx.testDir, cwd: ctx.cwd },\n config.patterns ?? {},\n );\n\n // Check stderr if expected (using actualStderr if available)\n let stderrMatches = true;\n if (block.expectedStderr) {\n stderrMatches = matchOutput(\n result.actualStderr ?? '',\n block.expectedStderr,\n { root: ctx.testDir, cwd: ctx.cwd },\n config.patterns ?? {},\n );\n }\n\n const exitCodeMatches = result.actualExitCode === block.expectedExitCode;\n result.passed = outputMatches && stderrMatches && exitCodeMatches && !result.error;\n\n if (!result.passed && opts.diff) {\n result.diff = createDiff(\n block.expectedOutput,\n result.actualOutput,\n `${filePath}:${block.lineNumber}`,\n );\n }\n\n results.push(result);\n\n if (!result.passed && opts.failFast) {\n shouldStop = true;\n break;\n }\n }\n\n // Run after hook if configured\n await runAfterHook(ctx);\n } finally {\n await cleanupExecutionContext(ctx);\n }\n\n const fileResult: TestFileResult = {\n file: testFile,\n results,\n passed: results.every((r) => r.passed),\n duration: results.reduce((sum, r) => sum + r.duration, 0),\n };\n\n fileResults.push(fileResult);\n reportFile(fileResult, opts);\n\n // Update mode\n if (opts.update && !fileResult.passed) {\n const { updated, changes } = await updateTestFile(testFile, results);\n if (updated) {\n console.error(colors.warn(` ${statusIndicators.update} Updated: ${changes.join(', ')}`));\n }\n }\n }\n\n // Summary\n const summary: TestRunSummary = {\n files: fileResults,\n totalPassed: fileResults.reduce((sum, f) => sum + f.results.filter((r) => r.passed).length, 0),\n totalFailed: fileResults.reduce((sum, f) => sum + f.results.filter((r) => !r.passed).length, 0),\n totalBlocks: fileResults.reduce((sum, f) => sum + f.results.length, 0),\n duration: Date.now() - startTime,\n };\n\n reportSummary(summary, opts);\n\n // Generate coverage report if enabled\n if (coverageCtx) {\n console.error('\\nGenerating coverage report...');\n try {\n await generateCoverageReport(coverageCtx);\n console.error(\n colors.success(`Coverage report written to ${coverageCtx.options.reportsDir}/`),\n );\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logError(`Failed to generate coverage report: ${message}`);\n } finally {\n await cleanupCoverageContext(coverageCtx);\n }\n }\n\n // Exit code\n process.exit(summary.totalFailed > 0 ? 1 : 0);\n}\n","/**\n * Coverage command - runs multiple commands with merged V8 coverage.\n *\n * This command provides a simple way to collect coverage from multiple sources\n * (e.g., unit tests + CLI tests) and generate a merged coverage report.\n *\n * Example usage:\n * tryscript coverage \"vitest run\" \"tryscript run tests/\"\n * tryscript coverage --monocart --reporters text,html \"vitest run\" \"node dist/bin.mjs run tests/\"\n */\n\nimport type { Command } from 'commander';\nimport { spawn } from 'node:child_process';\nimport { mkdtemp, rm } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join, resolve } from 'node:path';\nimport { existsSync } from 'node:fs';\nimport { logError, logWarn, colors } from '../lib/shared.js';\n\ninterface CoverageOptions {\n reportsDir?: string;\n reporters?: string[];\n include?: string[];\n exclude?: string[];\n excludeNodeModules?: boolean;\n excludeAfterRemap?: boolean;\n skipFull?: boolean;\n allowExternal?: boolean;\n monocart?: boolean;\n src?: string;\n}\n\n/**\n * Register the coverage command.\n */\nexport function registerCoverageCommand(program: Command): void {\n program\n .command('coverage')\n .description('Run commands with merged V8 coverage')\n .argument('<commands...>', 'Commands to run (each will inherit coverage environment)')\n .option('--reports-dir <dir>', 'Coverage output directory (default: coverage)')\n .option(\n '--reporters <reporters>',\n 'Comma-separated coverage reporters (default: text,json,json-summary,lcov,html)',\n )\n .option('--include <patterns>', 'Comma-separated patterns to include in coverage')\n .option('--exclude <patterns>', 'Comma-separated patterns to exclude from coverage')\n .option('--exclude-node-modules', 'Exclude node_modules from coverage (default: true)', true)\n .option('--no-exclude-node-modules', 'Include node_modules in coverage')\n .option('--exclude-after-remap', 'Apply exclude logic after sourcemap remapping')\n .option('--skip-full', 'Hide files with 100% coverage')\n .option('--allow-external', 'Allow files from outside cwd')\n .option('--monocart', 'Use monocart for accurate line counts (recommended for merging)')\n .option('--src <dir>', 'Source directory for sourcemap remapping (default: src)')\n .action(coverageCommand);\n}\n\n/**\n * Run a command with inherited coverage environment.\n */\nasync function runCommand(\n command: string,\n env: Record<string, string>,\n): Promise<{ success: boolean; code: number }> {\n return new Promise((resolve) => {\n const proc = spawn(command, [], {\n stdio: 'inherit',\n env: { ...process.env, ...env },\n shell: true,\n });\n\n proc.on('close', (code) => {\n resolve({ success: code === 0, code: code ?? 1 });\n });\n\n proc.on('error', (err) => {\n logError(`Failed to run command: ${err.message}`);\n resolve({ success: false, code: 1 });\n });\n });\n}\n\n/**\n * Find the c8 executable path.\n * Can be overridden via TRYSCRIPT_C8_COMMAND env var for testing.\n */\nfunction findC8Path(): string | null {\n // Allow override for testing - when set, we trust it exists\n const override = process.env.TRYSCRIPT_C8_COMMAND;\n if (override) {\n return override;\n }\n\n const localPaths = [\n resolve(process.cwd(), 'node_modules', '.bin', 'c8'),\n resolve(process.cwd(), '..', '..', 'node_modules', '.bin', 'c8'),\n ];\n\n for (const localPath of localPaths) {\n if (existsSync(localPath)) {\n return localPath;\n }\n }\n\n return null;\n}\n\n/**\n * Generate c8 coverage report.\n */\nasync function generateReport(tempDir: string, options: CoverageOptions): Promise<boolean> {\n const c8Path = findC8Path();\n if (!c8Path) {\n logError('c8 not found. Install with: npm install -D c8');\n return false;\n }\n\n const reporters = options.reporters ?? ['text', 'json', 'json-summary', 'lcov', 'html'];\n const include = options.include ?? ['dist/**'];\n const exclude = options.exclude ?? [];\n\n const reportArgs = [\n 'report',\n '--temp-directory',\n tempDir,\n '--reports-dir',\n options.reportsDir ?? 'coverage',\n '--src',\n options.src ?? 'src',\n '--all',\n ...include.flatMap((pattern) => ['--include', pattern]),\n ...exclude.flatMap((pattern) => ['--exclude', pattern]),\n ...(options.excludeNodeModules !== false\n ? ['--exclude-node-modules']\n : ['--no-exclude-node-modules']),\n ...(options.excludeAfterRemap ? ['--exclude-after-remap'] : []),\n ...(options.skipFull ? ['--skip-full'] : []),\n ...(options.allowExternal ? ['--allowExternal'] : []),\n ...(options.monocart ? ['--experimental-monocart'] : []),\n ...reporters.flatMap((reporter) => ['--reporter', reporter]),\n ];\n\n return new Promise((resolve) => {\n const proc = spawn(c8Path, reportArgs, {\n stdio: 'inherit',\n shell: false,\n });\n\n proc.on('close', (code) => {\n resolve(code === 0);\n });\n\n proc.on('error', (err) => {\n logError(`Failed to generate coverage report: ${err.message}`);\n resolve(false);\n });\n });\n}\n\nasync function coverageCommand(commands: string[], options: CoverageOptions): Promise<void> {\n // Validate we have commands to run\n if (commands.length === 0) {\n logError('No commands specified. Usage: tryscript coverage \"cmd1\" \"cmd2\"');\n process.exit(1);\n }\n\n // Check for c8\n const c8Path = findC8Path();\n if (!c8Path) {\n logError('Coverage requires c8. Install with: npm install -D c8');\n process.exit(1);\n }\n\n // Create temp directory for V8 coverage data\n const coverageTemp = await mkdtemp(join(tmpdir(), 'tryscript-coverage-'));\n const coverageEnv = { NODE_V8_COVERAGE: coverageTemp };\n\n console.error(colors.info(`Collecting V8 coverage to ${coverageTemp}`));\n\n let hasFailures = false;\n\n try {\n // Run each command with shared coverage environment\n for (let i = 0; i < commands.length; i++) {\n const command = commands[i]!;\n console.error(\n colors.info(`\\n=== Running command ${i + 1}/${commands.length}: ${command} ===`),\n );\n\n const result = await runCommand(command, coverageEnv);\n if (!result.success) {\n logWarn(`Command exited with code ${result.code}: ${command}`);\n hasFailures = true;\n }\n }\n\n // Generate merged coverage report\n console.error(colors.info('\\n=== Generating merged coverage report ==='));\n\n // Parse comma-separated options\n const parsedOptions: CoverageOptions = {\n ...options,\n reporters: options.reporters\n ? typeof options.reporters === 'string'\n ? (options.reporters as string).split(',')\n : options.reporters\n : undefined,\n include: options.include\n ? typeof options.include === 'string'\n ? (options.include as string).split(',')\n : options.include\n : undefined,\n exclude: options.exclude\n ? typeof options.exclude === 'string'\n ? (options.exclude as string).split(',')\n : options.exclude\n : undefined,\n };\n\n const reportSuccess = await generateReport(coverageTemp, parsedOptions);\n if (!reportSuccess) {\n logError('Failed to generate coverage report');\n process.exit(1);\n }\n\n console.error(\n colors.success(`\\nCoverage report written to ${parsedOptions.reportsDir ?? 'coverage'}/`),\n );\n } finally {\n // Cleanup temp directory\n await rm(coverageTemp, { recursive: true, force: true });\n }\n\n // Exit with failure if any command failed\n if (hasFailures) {\n process.exit(1);\n }\n}\n","/**\n * Readme command - Display the README documentation.\n *\n * Shows the package README.md, formatted for the terminal when interactive,\n * or as plain text when piped.\n */\n\nimport type { Command } from 'commander';\n\nimport { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport pc from 'picocolors';\n\n/**\n * Get the path to the README.md file.\n * Works both during development and when installed as a package.\n */\nfunction getReadmePath(): string {\n const thisDir = dirname(fileURLToPath(import.meta.url));\n const dirName = thisDir.split(/[/\\\\]/).pop();\n\n if (dirName === 'dist') {\n // Bundled: dist -> package root -> README.md\n return join(dirname(thisDir), 'README.md');\n }\n\n // Development: src/cli/commands -> src/cli -> src -> package root -> README.md\n return join(dirname(dirname(dirname(thisDir))), 'README.md');\n}\n\n/**\n * Load the README content.\n */\nfunction loadReadme(): string {\n const readmePath = getReadmePath();\n try {\n return readFileSync(readmePath, 'utf-8');\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to load README from ${readmePath}: ${message}`);\n }\n}\n\n/**\n * Apply basic terminal formatting to markdown content.\n * Colorizes headers, code blocks, and other elements for better readability.\n */\nfunction formatMarkdown(content: string, useColors: boolean): string {\n if (!useColors) {\n return content;\n }\n\n const lines = content.split('\\n');\n const formatted: string[] = [];\n let inCodeBlock = false;\n\n for (const line of lines) {\n // Track code blocks\n if (line.startsWith('```')) {\n inCodeBlock = !inCodeBlock;\n formatted.push(pc.dim(line));\n continue;\n }\n\n if (inCodeBlock) {\n formatted.push(pc.dim(line));\n continue;\n }\n\n // Headers\n if (line.startsWith('# ')) {\n formatted.push(pc.bold(pc.cyan(line)));\n continue;\n }\n if (line.startsWith('## ')) {\n formatted.push(pc.bold(pc.blue(line)));\n continue;\n }\n if (line.startsWith('### ')) {\n formatted.push(pc.bold(line));\n continue;\n }\n\n // Inline code (backticks)\n let formattedLine = line.replace(/`([^`]+)`/g, (_match, code: string) => {\n return pc.yellow(code);\n });\n\n // Bold text\n formattedLine = formattedLine.replace(/\\*\\*([^*]+)\\*\\*/g, (_match, text: string) => {\n return pc.bold(text);\n });\n\n // Links - show text in cyan, URL dimmed\n formattedLine = formattedLine.replace(\n /\\[([^\\]]+)\\]\\(([^)]+)\\)/g,\n (_match, text: string, url: string) => {\n return `${pc.cyan(text)} ${pc.dim(`(${url})`)}`;\n },\n );\n\n formatted.push(formattedLine);\n }\n\n return formatted.join('\\n');\n}\n\n/**\n * Check if stdout is an interactive terminal.\n */\nfunction isInteractive(): boolean {\n return process.stdout.isTTY === true;\n}\n\n/**\n * Display the README content.\n * Exported for use as the default command.\n */\nexport function showReadme(options?: { raw?: boolean; color?: boolean }): void {\n try {\n const readme = loadReadme();\n\n // Determine if we should colorize\n const shouldColorize = options?.color ?? (!options?.raw && isInteractive());\n\n const formatted = formatMarkdown(readme, shouldColorize);\n console.log(formatted);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(pc.red(`Error: ${message}`));\n process.exit(1);\n }\n}\n\n/**\n * Register the readme command.\n */\nexport function registerReadmeCommand(program: Command): void {\n program\n .command('readme')\n .description('Display README documentation')\n .option('--raw', 'Output raw markdown without formatting')\n .option('--color', 'Force colorized output (for testing)')\n .action(showReadme);\n}\n","/**\n * Docs command - Display the tryscript quick reference.\n *\n * Shows the tryscript-reference.md file, formatted for the terminal when interactive,\n * or as plain text when piped.\n */\n\nimport type { Command } from 'commander';\n\nimport { readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport pc from 'picocolors';\n\n/**\n * Get the path to the tryscript-reference.md file.\n * Works both during development and when installed as a package.\n */\nfunction getDocsPath(): string {\n const thisDir = dirname(fileURLToPath(import.meta.url));\n const dirName = thisDir.split(/[/\\\\]/).pop();\n\n if (dirName === 'dist') {\n // Bundled: dist -> package root -> docs/tryscript-reference.md\n return join(dirname(thisDir), 'docs', 'tryscript-reference.md');\n }\n\n // Development: src/cli/commands -> src/cli -> src -> package root -> docs/tryscript-reference.md\n return join(dirname(dirname(dirname(thisDir))), 'docs', 'tryscript-reference.md');\n}\n\n/**\n * Load the docs content.\n */\nfunction loadDocs(): string {\n const docsPath = getDocsPath();\n try {\n return readFileSync(docsPath, 'utf-8');\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Failed to load reference docs from ${docsPath}: ${message}`);\n }\n}\n\n/**\n * Apply basic terminal formatting to markdown content.\n * Colorizes headers, code blocks, and other elements for better readability.\n */\nfunction formatMarkdown(content: string, useColors: boolean): string {\n if (!useColors) {\n return content;\n }\n\n const lines = content.split('\\n');\n const formatted: string[] = [];\n let inCodeBlock = false;\n\n for (const line of lines) {\n // Track code blocks\n if (line.startsWith('```')) {\n inCodeBlock = !inCodeBlock;\n formatted.push(pc.dim(line));\n continue;\n }\n\n if (inCodeBlock) {\n formatted.push(pc.dim(line));\n continue;\n }\n\n // Headers\n if (line.startsWith('# ')) {\n formatted.push(pc.bold(pc.cyan(line)));\n continue;\n }\n if (line.startsWith('## ')) {\n formatted.push(pc.bold(pc.blue(line)));\n continue;\n }\n if (line.startsWith('### ')) {\n formatted.push(pc.bold(line));\n continue;\n }\n\n // Inline code (backticks)\n let formattedLine = line.replace(/`([^`]+)`/g, (_match, code: string) => {\n return pc.yellow(code);\n });\n\n // Bold text\n formattedLine = formattedLine.replace(/\\*\\*([^*]+)\\*\\*/g, (_match, text: string) => {\n return pc.bold(text);\n });\n\n // Links - show text in cyan, URL dimmed\n formattedLine = formattedLine.replace(\n /\\[([^\\]]+)\\]\\(([^)]+)\\)/g,\n (_match, text: string, url: string) => {\n return `${pc.cyan(text)} ${pc.dim(`(${url})`)}`;\n },\n );\n\n formatted.push(formattedLine);\n }\n\n return formatted.join('\\n');\n}\n\n/**\n * Check if stdout is an interactive terminal.\n */\nfunction isInteractive(): boolean {\n return process.stdout.isTTY === true;\n}\n\n/**\n * Register the docs command.\n */\nexport function registerDocsCommand(program: Command): void {\n program\n .command('docs')\n .description('Display concise syntax reference')\n .option('--raw', 'Output raw markdown without formatting')\n .option('--color', 'Force colorized output (for testing)')\n .action((options: { raw?: boolean; color?: boolean }) => {\n try {\n const docs = loadDocs();\n\n // Determine if we should colorize\n const shouldColorize = options.color ?? (!options.raw && isInteractive());\n\n const formatted = formatMarkdown(docs, shouldColorize);\n console.log(formatted);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(pc.red(`Error: ${message}`));\n process.exit(1);\n }\n });\n}\n","/**\n * CLI entry point for tryscript.\n *\n * Configures Commander.js with colored help and registers all subcommands.\n */\n\nimport { Command } from 'commander';\nimport { VERSION } from '../index.js';\nimport { registerRunCommand } from './commands/run.js';\nimport { registerCoverageCommand } from './commands/coverage.js';\nimport { registerReadmeCommand } from './commands/readme.js';\nimport { registerDocsCommand } from './commands/docs.js';\nimport { withColoredHelp, logError } from './lib/shared.js';\n\nexport function run(argv: string[]): void {\n const program = withColoredHelp(\n new Command()\n .name('tryscript')\n .version(VERSION, '--version', 'Show version number')\n .description('Golden testing for CLI applications')\n .showHelpAfterError('(use --help for usage)'),\n );\n\n // Register subcommands\n registerRunCommand(program);\n registerCoverageCommand(program);\n registerReadmeCommand(program);\n registerDocsCommand(program);\n\n // Default action: show help when no command given\n program.action(() => {\n program.help();\n });\n\n program.parseAsync(argv).catch((err: Error) => {\n logError(`Error: ${err.message}`);\n process.exit(2);\n });\n}\n","#!/usr/bin/env node\nimport { run } from './cli/cli.js';\n\nrun(process.argv);\n"],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- const require_src = require('./src-CxUUK92Q.cjs');
2
+ const require_src = require('./src-BR3CZ3tc.cjs');
3
3
 
4
4
  exports.VERSION = require_src.VERSION;
5
5
  exports.cleanupExecutionContext = require_src.cleanupExecutionContext;
package/dist/index.d.cts CHANGED
@@ -132,6 +132,8 @@ interface TestRunSummary {
132
132
  }
133
133
  /**
134
134
  * Schema for coverage configuration.
135
+ * Options mirror c8's CLI flags for maximum flexibility.
136
+ * @see https://github.com/bcoe/c8 for c8 documentation
135
137
  */
136
138
  declare const CoverageConfigSchema: z.ZodObject<{
137
139
  /** Output directory for coverage reports (default: 'coverage-tryscript') */
@@ -140,18 +142,42 @@ declare const CoverageConfigSchema: z.ZodObject<{
140
142
  reporters: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
141
143
  /** File patterns to include in coverage (default: ['dist/**']) */
142
144
  include: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
145
+ /** File patterns to exclude from coverage (c8 --exclude) */
146
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
147
+ /** Exclude all node_modules folders (c8 --exclude-node-modules, default: true) */
148
+ excludeNodeModules: z.ZodOptional<z.ZodBoolean>;
149
+ /** Apply exclude logic after sourcemap remapping (c8 --exclude-after-remap) */
150
+ excludeAfterRemap: z.ZodOptional<z.ZodBoolean>;
151
+ /** Hide files with 100% coverage (c8 --skip-full) */
152
+ skipFull: z.ZodOptional<z.ZodBoolean>;
153
+ /** Allow files from outside cwd (c8 --allowExternal) */
154
+ allowExternal: z.ZodOptional<z.ZodBoolean>;
143
155
  /** Source directory for sourcemap mapping (default: 'src') */
144
156
  src: z.ZodOptional<z.ZodString>;
157
+ /** Use monocart for more accurate line counts (c8 --experimental-monocart) */
158
+ monocart: z.ZodOptional<z.ZodBoolean>;
145
159
  }, "strip", z.ZodTypeAny, {
146
160
  reportsDir?: string | undefined;
147
161
  reporters?: string[] | undefined;
148
162
  include?: string[] | undefined;
163
+ exclude?: string[] | undefined;
164
+ excludeNodeModules?: boolean | undefined;
165
+ excludeAfterRemap?: boolean | undefined;
166
+ skipFull?: boolean | undefined;
167
+ allowExternal?: boolean | undefined;
149
168
  src?: string | undefined;
169
+ monocart?: boolean | undefined;
150
170
  }, {
151
171
  reportsDir?: string | undefined;
152
172
  reporters?: string[] | undefined;
153
173
  include?: string[] | undefined;
174
+ exclude?: string[] | undefined;
175
+ excludeNodeModules?: boolean | undefined;
176
+ excludeAfterRemap?: boolean | undefined;
177
+ skipFull?: boolean | undefined;
178
+ allowExternal?: boolean | undefined;
154
179
  src?: string | undefined;
180
+ monocart?: boolean | undefined;
155
181
  }>;
156
182
  /**
157
183
  * Coverage configuration options.
package/dist/index.d.mts CHANGED
@@ -132,6 +132,8 @@ interface TestRunSummary {
132
132
  }
133
133
  /**
134
134
  * Schema for coverage configuration.
135
+ * Options mirror c8's CLI flags for maximum flexibility.
136
+ * @see https://github.com/bcoe/c8 for c8 documentation
135
137
  */
136
138
  declare const CoverageConfigSchema: z.ZodObject<{
137
139
  /** Output directory for coverage reports (default: 'coverage-tryscript') */
@@ -140,18 +142,42 @@ declare const CoverageConfigSchema: z.ZodObject<{
140
142
  reporters: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
141
143
  /** File patterns to include in coverage (default: ['dist/**']) */
142
144
  include: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
145
+ /** File patterns to exclude from coverage (c8 --exclude) */
146
+ exclude: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
147
+ /** Exclude all node_modules folders (c8 --exclude-node-modules, default: true) */
148
+ excludeNodeModules: z.ZodOptional<z.ZodBoolean>;
149
+ /** Apply exclude logic after sourcemap remapping (c8 --exclude-after-remap) */
150
+ excludeAfterRemap: z.ZodOptional<z.ZodBoolean>;
151
+ /** Hide files with 100% coverage (c8 --skip-full) */
152
+ skipFull: z.ZodOptional<z.ZodBoolean>;
153
+ /** Allow files from outside cwd (c8 --allowExternal) */
154
+ allowExternal: z.ZodOptional<z.ZodBoolean>;
143
155
  /** Source directory for sourcemap mapping (default: 'src') */
144
156
  src: z.ZodOptional<z.ZodString>;
157
+ /** Use monocart for more accurate line counts (c8 --experimental-monocart) */
158
+ monocart: z.ZodOptional<z.ZodBoolean>;
145
159
  }, "strip", z.ZodTypeAny, {
146
160
  reportsDir?: string | undefined;
147
161
  reporters?: string[] | undefined;
148
162
  include?: string[] | undefined;
163
+ exclude?: string[] | undefined;
164
+ excludeNodeModules?: boolean | undefined;
165
+ excludeAfterRemap?: boolean | undefined;
166
+ skipFull?: boolean | undefined;
167
+ allowExternal?: boolean | undefined;
149
168
  src?: string | undefined;
169
+ monocart?: boolean | undefined;
150
170
  }, {
151
171
  reportsDir?: string | undefined;
152
172
  reporters?: string[] | undefined;
153
173
  include?: string[] | undefined;
174
+ exclude?: string[] | undefined;
175
+ excludeNodeModules?: boolean | undefined;
176
+ excludeAfterRemap?: boolean | undefined;
177
+ skipFull?: boolean | undefined;
178
+ allowExternal?: boolean | undefined;
154
179
  src?: string | undefined;
180
+ monocart?: boolean | undefined;
155
181
  }>;
156
182
  /**
157
183
  * Coverage configuration options.
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
1
 
2
- import { a as createExecutionContext, c as parseTestFile, i as cleanupExecutionContext, l as defineConfig, n as matchOutput, r as normalizeOutput, s as runBlock, t as VERSION } from "./src-CndHSuTT.mjs";
2
+ import { a as createExecutionContext, c as parseTestFile, i as cleanupExecutionContext, l as defineConfig, n as matchOutput, r as normalizeOutput, s as runBlock, t as VERSION } from "./src-DKrim0QL.mjs";
3
3
 
4
4
  export { VERSION, cleanupExecutionContext, createExecutionContext, defineConfig, matchOutput, normalizeOutput, parseTestFile, runBlock };