@bernierllc/package-analyzer
v0.3.2
Published
Pure package analysis utilities for monorepo management
Readme
@bernierllc/package-analyzer
Pure package analysis utilities for monorepo management.
Features
- Package Discovery: Find all packages in a monorepo (supports nested subdirectories)
- Git Integration: Analyze recent changes, modifications, and publish needs
- Status Analysis: Get detailed package status including version comparison
- Smart Suggestions: Intelligent package prioritization for publishing
- Pure Functions: Stateless, testable, and composable utilities
Installation
npm install @bernierllc/package-analyzerQuick Start
import { analyzePackages, getAllPackages, getPackageJson } from '@bernierllc/package-analyzer';
// Get all packages in the monorepo
const packages = getAllPackages();
console.log(packages); // ['core/package1', 'service/package2', ...]
// Get complete analysis
const analysis = await analyzePackages();
console.log(analysis);
// {
// allPackages: ['core/package1', 'service/package2'],
// recentPackages: ['core/package1'],
// modifiedPackages: ['service/package2'],
// packagesNeedingPublish: [],
// smartSuggestion: 'core/package1'
// }
// Get package.json for a specific package
const pkgJson = getPackageJson('core/package1');
console.log(pkgJson.name); // '@bernierllc/package1'API Reference
Core Functions
getAllPackages(config?)
Get all packages in the monorepo.
const packages = getAllPackages();
// Returns: ['core/package1', 'service/package2', ...]getPackageJson(packageName, config?)
Get package.json for a specific package.
const pkgJson = getPackageJson('core/package1');
// Returns: { name: '@bernierllc/package1', version: '1.0.0', ... }analyzePackageStatus(packageName, config?)
Get detailed status of a package including publish state.
const status = await analyzePackageStatus('core/package1');
// Returns: {
// packageName: 'core/package1',
// fullPackageName: '@bernierllc/package1',
// isPublished: true,
// publishedVersion: '0.9.0',
// localVersion: '1.0.0',
// isPrivate: true,
// needsPublishing: true,
// isFirstTimePublish: false
// }Git Analysis Functions
getRecentPackages(config?)
Get packages modified in the last N days.
const recent = await getRecentPackages();
// Returns: ['core/package1', 'service/package2']getModifiedPackages(config?)
Get packages with uncommitted changes.
const modified = await getModifiedPackages();
// Returns: ['core/package1', 'service/package2']getPackagesNeedingPublish(config?)
Get packages that need publishing (have commits but not published).
const needsPublish = await getPackagesNeedingPublish();
// Returns: ['core/package1', 'service/package2']Utility Functions
sortPackagesByPriority(packages, recentPackages, modifiedPackages, packagesNeedingPublish)
Sort packages by priority: needs publish > recent > modified > alphabetical.
const sorted = sortPackagesByPriority(
['core/package1', 'service/package2'],
['service/package2'],
['core/package1'],
[]
);
// Returns: ['core/package1', 'service/package2']getSmartSuggestion(packagesNeedingPublish, recentPackages, modifiedPackages)
Get the best package suggestion for publishing.
const suggestion = getSmartSuggestion(
['core/package1'],
['service/package2'],
['util/package3']
);
// Returns: 'core/package1'analyzePackages(config?)
Complete package analysis.
const analysis = await analyzePackages();
// Returns: AnalyzerResult with all package informationConfiguration
All functions accept an optional configuration object:
interface AnalyzerConfig {
packagesDir: string; // Default: 'packages'
recentDays: number; // Default: 7
timeoutMs: number; // Default: 30000
maxRecentPackages: number; // Default: 20
}Example:
const config = {
packagesDir: '/custom/packages',
recentDays: 14,
timeoutMs: 60000
};
const packages = getAllPackages(config);Utility Functions
isValidPackageName(packageName)
Validate package name format (category/package-name).
isValidPackageName('core/package1'); // true
isValidPackageName('package1'); // falsegetPackageCategory(packageName)
Extract category from package name.
getPackageCategory('core/package1'); // 'core'getPackageNameOnly(packageName)
Extract package name without category.
getPackageNameOnly('core/package1'); // 'package1'Directory Structure Support
This package supports both flat and nested package structures:
packages/
├── core/
│ ├── package1/
│ └── package2/
├── service/
│ ├── package3/
│ └── package4/
└── util/
└── package5/Package names are returned in the format category/package-name.
Error Handling
All functions handle errors gracefully:
- File System Errors: Return empty arrays or throw descriptive errors
- Git Command Errors: Return empty arrays with console warnings
- NPM Command Errors: Return appropriate defaults for unpublished packages
Testing
npm testThe package includes comprehensive tests with mocked file system and git operations.
Performance
- Pure Functions: No side effects, easily cacheable
- Lazy Evaluation: Git commands only run when needed
- Configurable Timeouts: Prevent hanging on slow operations
- Efficient Filtering: Early returns for empty results
Use Cases
Publishing Workflow
const analysis = await analyzePackages();
if (analysis.packagesNeedingPublish.length > 0) {
const nextPackage = analysis.smartSuggestion;
console.log(`Next package to publish: ${nextPackage}`);
}Development Checks
const modified = await getModifiedPackages();
if (modified.length > 0) {
console.log('Packages with uncommitted changes:', modified);
}Package Discovery
const allPackages = getAllPackages();
const corePackages = allPackages.filter(pkg => pkg.startsWith('core/'));
console.log('Core packages:', corePackages);Contributing
This package follows the BernierLLC development standards:
- TypeScript: Strict type checking enabled
- Tests: Comprehensive test coverage
- Documentation: JSDoc comments on all public functions
- Error Handling: Graceful error handling with descriptive messages
License
UNLICENSED - Bernier LLC internal use only.
