UNPKG

apisurf

Version:

Analyze API surface changes between npm package versions to catch breaking changes

67 lines (66 loc) 3.32 kB
import { Command } from 'commander'; import chalk from 'chalk'; import { formatOutput } from '../utilities/formatOutput.js'; import { analyzeDiff } from '../analyzers/analyzeDiff.js'; export const diffCommand = new Command('diff') .description('Check for breaking changes by comparing package API surface between git branches or npm package versions') .argument('[packagename]', 'NPM package name to compare versions') .argument('[fromversion]', 'Base version to compare from') .argument('[toversion]', 'Target version to compare to') .option('--base <branch>', 'Base branch to compare against (for git mode)', 'main') .option('--head <branch>', 'Head branch to compare (for git mode, defaults to current branch)') .option('--packages <pattern>', 'Glob pattern for packages to check (for monorepos in git mode)') .option('--registry <url>', 'NPM registry URL (defaults to public npm, respects .npmrc)') .option('--format <format>', 'Output format: console, json, md, html, report', 'report') .option('--logfile <filename>', 'JSON file to log full API surfaces for both versions') .option('--verbose', 'Enable verbose output including npm notices') .action(async (packagename, fromversion, toversion, options) => { try { // Convert commander options to DiffOptions const diffOptions = { base: options.base, head: options.head, packages: options.packages, format: options.format, npmPackage: packagename, fromVersion: fromversion, toVersion: toversion, registry: options.registry, logfile: options.logfile, verbose: options.verbose }; // Validate options if (diffOptions.npmPackage) { if (!diffOptions.fromVersion || !diffOptions.toVersion) { console.error('Error: NPM mode requires all three arguments: <packagename> <fromversion> <toversion>'); process.exit(1); } if (diffOptions.format === 'console' || diffOptions.format === 'html' || diffOptions.format === 'report') { console.log(`Analyzing ${chalk.cyan(diffOptions.npmPackage)} api surface changes: ${chalk.yellow(diffOptions.fromVersion)} to ${chalk.green(diffOptions.toVersion)}`); console.log(); } } else { if (diffOptions.format === 'console' || diffOptions.format === 'html' || diffOptions.format === 'report') { console.log('Analyzing api surface changes...'); console.log(); } } const result = await analyzeDiff(diffOptions); const output = formatOutput(result, diffOptions.format, diffOptions.verbose); // For markdown and json formats, output directly without any additional formatting if (diffOptions.format === 'md' || diffOptions.format === 'json') { process.stdout.write(output + '\n'); } else { console.log(output); } if (result.hasBreakingChanges) { process.exit(1); } } catch (error) { console.error('Error during diff analysis:', error instanceof Error ? error.message : String(error)); process.exit(1); } });