apisurf
Version:
Analyze API surface changes between npm package versions to catch breaking changes
140 lines (139 loc) • 5.45 kB
JavaScript
import chalk from 'chalk';
/**
* Formats inspect results for console output with colors and structure.
*/
export function formatInspectConsoleOutput(result, verbose = false) {
const lines = [];
// Header
lines.push(chalk.bold.blue(`📦 ${result.packageName}@${result.version}`));
if (result.repositoryUrl) {
lines.push(chalk.gray(` Repository: ${result.repositoryUrl}`));
}
lines.push('');
// Summary
if (result.success) {
lines.push(chalk.green(`✓ ${result.summary}`));
}
else {
lines.push(chalk.red(`✗ ${result.summary}`));
}
// Errors
if (result.errors && result.errors.length > 0) {
lines.push('');
lines.push(chalk.red('Errors:'));
result.errors.forEach(error => {
lines.push(chalk.red(` - ${error}`));
});
}
if (!result.success) {
return lines.join('\n');
}
// API Surfaces
for (const [entryPoint, surface] of result.apiSurfaces) {
lines.push('');
lines.push(chalk.bold.cyan(entryPoint === 'main' ? '📄 Main Export' : `📄 Export: ${entryPoint}`));
lines.push(chalk.gray('─'.repeat(50)));
// Default export
if (surface.defaultExport) {
lines.push('');
lines.push(chalk.yellow('Default Export:'));
lines.push(' ✓ Has default export');
}
// Named exports
if (surface.namedExports.size > 0) {
lines.push('');
lines.push(chalk.yellow(`Named Exports (${surface.namedExports.size}):`));
const exports = Array.from(surface.namedExports).sort();
exports.forEach(name => {
const typeDef = surface.typeDefinitions?.get(name);
if (typeDef) {
lines.push(` ${chalk.green('●')} ${chalk.cyan(name)} ${chalk.gray(`(${typeDef.kind})`)}`);
if (verbose) {
lines.push(formatTypeDefinition(typeDef, ' '));
}
}
else {
lines.push(` ${chalk.green('●')} ${chalk.cyan(name)}`);
}
});
}
// Type-only exports
if (surface.typeOnlyExports.size > 0) {
lines.push('');
lines.push(chalk.yellow(`Type Exports (${surface.typeOnlyExports.size}):`));
const typeExports = Array.from(surface.typeOnlyExports).sort();
typeExports.forEach(name => {
const typeDef = surface.typeDefinitions?.get(name);
if (typeDef) {
lines.push(` ${chalk.blue('○')} ${chalk.cyan(name)} ${chalk.gray(`(${typeDef.kind})`)}`);
if (verbose) {
lines.push(formatTypeDefinition(typeDef, ' '));
}
}
else {
lines.push(` ${chalk.blue('○')} ${chalk.cyan(name)}`);
}
});
}
// Star exports
if (surface.starExports.length > 0) {
lines.push('');
lines.push(chalk.yellow(`Re-exports (${surface.starExports.length}):`));
surface.starExports.forEach(module => {
lines.push(` ${chalk.magenta('*')} ${chalk.gray(`from "${module}"`)}`);
});
}
}
return lines.join('\n');
}
/**
* Formats a type definition for console output.
*/
function formatTypeDefinition(def, indent) {
const lines = [];
if (def.signature) {
// For simple signatures, show them inline
if (def.signature.length < 80 && !def.signature.includes('\n')) {
lines.push(`${indent}${chalk.gray(def.signature)}`);
}
else if (def.kind === 'function') {
// Format function signature
lines.push(`${indent}${chalk.gray(formatFunctionSignature(def))}`);
}
else {
// For complex types, show a summary
if (def.properties && def.properties.size > 0) {
lines.push(`${indent}${chalk.gray('Properties:')}`);
const props = Array.from(def.properties.entries()).slice(0, 5);
props.forEach(([name, type]) => {
const truncatedType = type.length > 50 ? type.substring(0, 47) + '...' : type;
lines.push(`${indent} - ${name}: ${chalk.gray(truncatedType)}`);
});
if (def.properties.size > 5) {
lines.push(`${indent} ${chalk.gray(`... and ${def.properties.size - 5} more`)}`);
}
}
if (def.members && def.members.length > 0) {
lines.push(`${indent}${chalk.gray('Members:')}`);
const members = def.members.slice(0, 5);
members.forEach(member => {
lines.push(`${indent} - ${member}`);
});
if (def.members.length > 5) {
lines.push(`${indent} ${chalk.gray(`... and ${def.members.length - 5} more`)}`);
}
}
}
}
return lines.join('\n');
}
/**
* Formats a function signature for display.
*/
function formatFunctionSignature(def) {
if (def.parameters && def.returnType) {
const params = def.parameters.join(', ');
return `(${params}) => ${def.returnType}`;
}
return def.signature || 'function';
}