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

  1. Create a feature branch:

    git checkout -b feature/amazing-feature
    
  2. Make your changes following the coding standards

  3. Add tests for your changes:

    pnpm test:watch  # Run tests in watch mode
    
  4. Ensure quality checks pass:

    pnpm lint        # Check code style
    pnpm typecheck   # Type checking
    pnpm test        # Run all tests
    
  5. 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

  1. 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;
}
  1. Add business logic in packages/core/src/application/services/

  2. Create tests for both CLI and core logic

  3. Update documentation

Adding New Output Formats

  1. 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',
    };
  }
}
  1. Register formatter in the main formatter registry

  2. 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

  1. Fork the repository and create a feature branch
  2. Make your changes following the development workflow
  3. Ensure all tests pass and code quality checks succeed
  4. Update documentation if needed
  5. 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

  1. All tests pass
  2. Code coverage maintained (>85%)
  3. TypeScript types are correct
  4. Code style follows project standards
  5. Documentation updated
  6. Breaking changes documented
  7. 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

  1. Update version using changesets:

    pnpm changeset
    pnpm changeset version
    
  2. Build and test:

    pnpm build
    pnpm test
    pnpm test:e2e
    
  3. 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
}

Was this page helpful?