Development
Set up PCU for development and learn how to contribute to the project. This guide covers project setup, architecture, and development workflows.
Prerequisites
Before you start developing PCU, make sure you have the required tools:
node --version # Should be >= 22.0.0
pnpm --version # Should be >= 10.0.0
Project Setup
Clone and set up the development environment:
# Clone the repository
git clone https://github.com/houko/pnpm-catalog-updates.git
cd pnpm-catalog-updates
# Install dependencies
pnpm install
# Build the project
pnpm build
# Run tests to verify setup
pnpm test
Project Architecture
PCU follows clean architecture principles with clear separation of concerns:
βββ apps/
β βββ cli/ # CLI application layer
β β βββ src/cli/ # CLI interface
β β β βββ commands/ # Command handlers
β β β βββ formatters/ # Output formatters
β β β βββ interactive/ # Interactive prompts
β β β βββ themes/ # Color themes
β β β βββ validators/ # Input validation
β β βββ bin/ # Executable binaries
β βββ docs/ # Documentation site
βββ packages/
β βββ core/ # Core business logic
β β βββ src/
β β βββ application/ # Application services
β β βββ domain/ # Domain model (DDD)
β β βββ infrastructure/# Infrastructure layer
β βββ utils/ # Shared utilities
βββ scripts/ # Build and deployment
Architecture Layers
- Name
CLI Layer- Type
- apps/cli
- Description
User interface, command parsing, output formatting
- Name
Application Layer- Type
- packages/core/application
- Description
Business logic orchestration, use cases
- Name
Domain Layer- Type
- packages/core/domain
- Description
Core business entities, value objects, repository interfaces
- Name
Infrastructure Layer- Type
- packages/core/infrastructure
- Description
External API clients, file system access, repository implementations
- Name
Utils Layer- Type
- packages/utils
- Description
Shared utilities, configuration, logging, error handling
Development Workflow
Making Changes
-
Create a feature branch:
git checkout -b feature/amazing-feature -
Make your changes following the coding standards
-
Add tests for your changes:
pnpm test:watch # Run tests in watch mode -
Ensure quality checks pass:
pnpm lint # Check code style pnpm typecheck # Type checking pnpm test # Run all tests -
Commit your changes:
git commit -m 'feat: add amazing feature'
Testing Strategy
PCU uses a comprehensive testing approach:
# Run unit tests
pnpm test
# Run with coverage
pnpm test:coverage
# Test specific package
pnpm --filter @pcu/core test
Code Quality
PCU maintains high code quality standards:
# Check code style
pnpm lint
# Fix linting issues
pnpm lint:fix
# Format code
pnpm format
# Check TypeScript types
pnpm typecheck
Adding Features
Creating New Commands
- Create command handler in
apps/cli/src/cli/commands/:
import { Command } from 'commander';
import { GlobalOptions } from '../options';
export function createNewCommand(): Command {
return new Command('new')
.description('Description of new command')
.option('-f, --format <type>', 'Output format', 'table')
.action(async (options: NewCommandOptions) => {
// Command implementation
});
}
interface NewCommandOptions extends GlobalOptions {
format: string;
}
-
Add business logic in
packages/core/src/application/services/ -
Create tests for both CLI and core logic
-
Update documentation
Adding New Output Formats
- Create formatter in
apps/cli/src/cli/formatters/:
xmlFormatter.ts
import { OutputFormatter, FormattedOutput } from './outputFormatter';
export class XmlFormatter implements OutputFormatter {
format(data: any): FormattedOutput {
// XML formatting logic
return {
content: xmlContent,
type: 'xml',
};
}
}
-
Register formatter in the main formatter registry
-
Add tests and update documentation
Contributing Guidelines
Commit Message Convention
PCU uses Conventional Commits:
feat: A new feature
fix: A bug fix
docs: Documentation only changes
style: Code style changes (formatting, etc)
refactor: Code change that neither fixes a bug nor adds a feature
test: Adding missing tests or correcting existing tests
chore: Changes to build process or auxiliary tools
Pull Request Process
- Fork the repository and create a feature branch
- Make your changes following the development workflow
- Ensure all tests pass and code quality checks succeed
- Update documentation if needed
- Submit a pull request with:
- Clear description of changes
- Link to related issues
- Screenshots for UI changes
- Breaking change notes if applicable
Code Review Checklist
- All tests pass
- Code coverage maintained (>85%)
- TypeScript types are correct
- Code style follows project standards
- Documentation updated
- Breaking changes documented
- Performance impact considered
Debugging
Development Debugging
# Debug with Node.js inspector
node --inspect-brk ./apps/cli/bin/pcu.js --help
# Debug with VS Code
# Use the launch configuration in .vscode/launch.json
Testing Debugging
# Debug specific test
npm test -- --grep "specific test name"
# Debug with Node inspector
node --inspect-brk node_modules/.bin/vitest run
Building and Publishing
Local Testing
# Build and test locally
pnpm build
pnpm --filter @pcu/cli start --help
# Test installation
npm pack apps/cli
npm install -g pcu-*.tgz
Release Process
-
Update version using changesets:
pnpm changeset pnpm changeset version -
Build and test:
pnpm build pnpm test pnpm test:e2e -
Publish (maintainers only):
pnpm publish -r
Getting Help
- π Documentation: Check this documentation for detailed guides
- π Issues: Report bugs via GitHub Issues
- π¬ Discussions: Ask questions in GitHub Discussions
- π§ Development: Join development discussions in issues and PRs
Advanced Architecture Details
Core Domain Model
Based on Domain-Driven Design (DDD) principles, PCU's core domain includes:
// packages/core/src/domain/entities/
βββ catalog.ts // Catalog aggregate root
βββ package.ts // Package entity
βββ workspace.ts // Workspace aggregate root
// Key domain concepts:
interface Catalog {
readonly id: CatalogId;
readonly name: string;
packages: PackageCollection;
addPackage(packageInfo: Package): void;
updatePackage(name: string, version: Version): void;
}
interface Package {
readonly name: string;
readonly currentVersion: Version;
readonly latestVersion: Version;
readonly updateType: UpdateType;
}
Service Layer Architecture
The application layer orchestrates business logic through services:
// packages/core/src/application/services/
βββ catalogUpdateService.ts // Main orchestration
βββ workspaceService.ts // Workspace operations
// Service responsibilities:
class CatalogUpdateService {
async checkForUpdates(options: CheckOptions): Promise<UpdateReport>;
async updateCatalog(options: UpdateOptions): Promise<UpdateResult>;
async analyzeImpact(catalog: string, package: string): Promise<ImpactAnalysis>;
}
CLI Layer Design
The CLI layer provides a clean interface to the core domain:
// apps/cli/src/cli/commands/
βββ checkCommand.ts // Check command implementation
βββ updateCommand.ts // Update command with validation
βββ analyzeCommand.ts // Impact analysis command
βββ workspaceCommand.ts # Workspace management
βββ themeCommand.ts # Theme configuration
βββ securityCommand.ts # Security scanning
βββ initCommand.ts # Workspace initialization
// Each command follows consistent patterns:
export class CheckCommand {
constructor(
private readonly catalogService: CatalogUpdateService,
private readonly validator: CommandValidator,
private readonly formatter: OutputFormatter
) {}
async execute(options: CheckCommandOptions): Promise<void> {
const validation = this.validator.validateCheckOptions(options);
if (!validation.isValid) {
throw new ValidationError(validation.errors);
}
const result = await this.catalogService.checkForUpdates(options);
const formatted = this.formatter.format(result, options.format);
console.log(formatted);
}
}
Testing Architecture
Comprehensive testing strategy across all layers:
βββ packages/core/src/**/__tests__/ # Unit tests
βββ packages/utils/src/**/__tests__/ # Utility tests
βββ apps/cli/src/**/__tests__/ # CLI unit tests
βββ tests/
β βββ e2e/ # End-to-end tests
β βββ integration/ # Integration tests
β βββ fixtures/ # Test fixtures
βββ .github/workflows/
βββ test.yml # CI test pipeline
Performance Considerations
PCU is optimized for performance in large monorepos:
// Intelligent caching reduces API calls
class Cache<T> {
constructor(
private readonly options: {
ttl: number; // Time to live
maxSize: number; // Memory limit
persistToDisk: boolean; // File caching
strategy: 'lru' | 'fifo' | 'lfu'; // Eviction strategy
}
) {}
async get(key: string): Promise<T | null>;
async set(key: string, value: T): Promise<void>;
getStats(): CacheStats; // Hit rates, memory usage
}