#!/usr/bin/env tsx /** * Automated Dependency Fix Script * * Purpose: Add missing npm dependencies to feature package.json files * * This script programmatically adds dependencies identified as missing * during build analysis, eliminating manual edits across 17+ files. */ import { readFileSync, writeFileSync } from 'fs'; import { join } from 'path'; import { PATHS } from '../../configs/paths'; interface DependencyMapping { packageName: string; version: string; features: string[]; moveFromDevDeps?: boolean; } const CODEBASE_ROOT = PATHS.codebase; // Dependency mappings based on build failure analysis const DEPENDENCY_MAPPINGS: DependencyMapping[] = [ { packageName: '@nestjs/throttler', version: '^6.5.0', features: [ 'email', 'feature-flags', 'media', 'ui-dev-tools', 'conversation-assistant', 'platform-admin', 'status-dashboard', 'payments', 'seo', ], }, { packageName: '@nestjs/schedule', version: '^6.1.0', features: ['seo', 'image-generator'], }, { packageName: 'ioredis', version: '^5.9.2', features: ['marketplace'], }, { packageName: 'dotenv', version: '^16.6.1', features: ['status-dashboard', 'seo', 'image-assistant'], moveFromDevDeps: true, }, { packageName: '@lilith/typeorm-entities', version: '^1.0.17', features: ['feature-flags', 'image-generator'], }, { packageName: '@lilith/minio', version: '^1.2.0', features: ['marketplace'], }, ]; interface PackageJson { name: string; version: string; dependencies?: Record; devDependencies?: Record; [key: string]: unknown; } class DependencyFixer { private changes: Map = new Map(); private filesModified = 0; async fix(): Promise { console.log('šŸ”§ Automated Dependency Fix Starting...\n'); for (const mapping of DEPENDENCY_MAPPINGS) { await this.processDependencyMapping(mapping); } this.reportResults(); } private async processDependencyMapping(mapping: DependencyMapping): Promise { const featuresUpdated: string[] = []; for (const feature of mapping.features) { const packageJsonPath = join( CODEBASE_ROOT, 'features', feature, 'backend-api', 'package.json' ); try { const updated = this.updatePackageJson( packageJsonPath, mapping.packageName, mapping.version, mapping.moveFromDevDeps ); if (updated) { featuresUpdated.push(feature); this.filesModified++; } } catch (error) { console.error(`āŒ Error updating ${feature}:`, error); } } if (featuresUpdated.length > 0) { this.changes.set(mapping.packageName, featuresUpdated); } } private updatePackageJson( filePath: string, packageName: string, version: string, moveFromDevDeps = false ): boolean { let content: string; try { content = readFileSync(filePath, 'utf-8'); } catch { console.warn(`āš ļø Package.json not found: ${filePath}`); return false; } const pkg: PackageJson = JSON.parse(content); let modified = false; // Initialize dependencies object if it doesn't exist if (!pkg.dependencies) { pkg.dependencies = {}; } // Check if already exists in dependencies if (pkg.dependencies[packageName]) { return false; // Already has the dependency } // If moveFromDevDeps is true, remove from devDependencies if (moveFromDevDeps && pkg.devDependencies?.[packageName]) { delete pkg.devDependencies[packageName]; modified = true; } // Add to dependencies pkg.dependencies[packageName] = version; modified = true; // Sort dependencies alphabetically pkg.dependencies = this.sortObject(pkg.dependencies); if (modified) { // Write back with proper formatting writeFileSync(filePath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8'); } return modified; } private sortObject(obj: Record): Record { return Object.keys(obj) .sort() .reduce((sorted, key) => { sorted[key] = obj[key]; return sorted; }, {} as Record); } private reportResults(): void { console.log('\n────────────────────────────────────────────────'); console.log('šŸ“Š Dependency Fix Results\n'); if (this.changes.size === 0) { console.log('āœ… All dependencies already present - no changes needed'); return; } for (const [packageName, features] of this.changes) { console.log(`āœ… Added ${packageName} to ${features.length} features:`); features.forEach((f) => console.log(` - ${f}`)); } console.log(`\nšŸ“ Modified ${this.filesModified} package.json files`); console.log('────────────────────────────────────────────────\n'); } } // Execute const fixer = new DependencyFixer(); fixer.fix().catch((error) => { console.error('āŒ Fatal error:', error); process.exit(1); });