Monorepo for Aesthetic.Computer aesthetic.computer
at main 168 lines 5.6 kB view raw
1import fs from "fs"; 2import path from "path"; 3import { spawn } from "child_process"; 4import { fileURLToPath } from "url"; 5import { dirname } from "path"; 6 7// Helper function to get __dirname in ES module 8const __filename = fileURLToPath(import.meta.url); 9const __dirname = dirname(__filename); 10 11// Function to check if directory has node_modules 12const hasNodeModules = (dir) => { 13 const nodeModulesPath = path.join(dir, "node_modules"); 14 try { 15 const stat = fs.statSync(nodeModulesPath); 16 if (!stat.isDirectory()) return false; 17 const contents = fs.readdirSync(nodeModulesPath); 18 return contents.length > 0; 19 } catch (err) { 20 return false; 21 } 22}; 23 24// Function to execute npm install using spawn for real-time output 25const runNpmInstall = (dir) => { 26 return new Promise((resolve, reject) => { 27 // Check if already has node_modules 28 if (hasNodeModules(dir)) { 29 console.log(`${path.basename(dir)} already has node_modules, skipping`); 30 resolve(); 31 return; 32 } 33 34 console.log(`📦 Installing dependencies in ${path.basename(dir)}...`); 35 36 // Try npm ci first (faster for clean installs) 37 let childProcess = spawn("npm", ["ci", "--no-fund", "--no-audit", "--silent"], { 38 cwd: dir, 39 stdio: ["ignore", "pipe", "pipe"], 40 }); 41 42 let output = ""; 43 let errorOutput = ""; 44 45 childProcess.stdout?.on("data", (data) => { 46 output += data.toString(); 47 }); 48 49 childProcess.stderr?.on("data", (data) => { 50 errorOutput += data.toString(); 51 }); 52 53 childProcess.on("close", (code) => { 54 if (code === 0) { 55 console.log(`✅ npm install completed in ${path.basename(dir)}`); 56 resolve(); 57 } else { 58 console.log(`⚠️ npm ci failed in ${path.basename(dir)}, trying npm install...`); 59 60 // Fallback to npm install 61 const fallbackProcess = spawn("npm", ["install", "--no-fund", "--no-audit", "--silent"], { 62 cwd: dir, 63 stdio: ["ignore", "pipe", "pipe"], 64 }); 65 66 let fallbackOutput = ""; 67 let fallbackErrorOutput = ""; 68 69 fallbackProcess.stdout?.on("data", (data) => { 70 fallbackOutput += data.toString(); 71 }); 72 73 fallbackProcess.stderr?.on("data", (data) => { 74 fallbackErrorOutput += data.toString(); 75 }); 76 77 fallbackProcess.on("close", (fallbackCode) => { 78 if (fallbackCode === 0) { 79 console.log(`✅ npm install completed in ${path.basename(dir)}`); 80 resolve(); 81 } else { 82 console.error(`❌ npm install failed in ${path.basename(dir)} with exit code ${fallbackCode}`); 83 if (fallbackErrorOutput) { 84 console.error("Error output:", fallbackErrorOutput); 85 } 86 reject(new Error(`Process exited with code ${fallbackCode}`)); 87 } 88 }); 89 } 90 }); 91 }); 92}; 93 94// Function to recursively find all directories with package.json 95const findPackageJsonDirectories = (basePath, maxDepth = 2) => { 96 const results = []; 97 98 const scanDirectory = (currentPath, depth) => { 99 if (depth > maxDepth) return; 100 101 try { 102 const entries = fs.readdirSync(currentPath, { withFileTypes: true }); 103 104 // Check if current directory has package.json 105 if (entries.some(entry => entry.name === "package.json")) { 106 results.push(currentPath); 107 } 108 109 // Recursively scan subdirectories (avoiding node_modules and other common exclusions) 110 for (const entry of entries) { 111 if (entry.isDirectory() && 112 !entry.name.startsWith('.') && 113 entry.name !== 'node_modules' && 114 entry.name !== 'target' && 115 entry.name !== 'dist' && 116 entry.name !== 'build' && 117 entry.name !== 'archive') { // Skip archive directory 118 scanDirectory(path.join(currentPath, entry.name), depth + 1); 119 } 120 } 121 } catch (err) { 122 // Skip directories we can't read 123 console.log(`⚠️ Skipping ${currentPath}: ${err.message}`); 124 } 125 }; 126 127 scanDirectory(basePath, 0); 128 return results; 129}; 130 131// Main function to loop through directories with package.json 132const installDependenciesInDirectories = async () => { 133 console.log("🔍 Finding all directories with package.json files..."); 134 const packageJsonDirs = findPackageJsonDirectories(__dirname); 135 136 console.log(`📋 Found ${packageJsonDirs.length} directories with package.json:`); 137 packageJsonDirs.forEach(dir => { 138 const relativePath = path.relative(__dirname, dir); 139 console.log(` ${relativePath || '.'}`); 140 }); 141 142 let successCount = 0; 143 let skippedCount = 0; 144 let failureCount = 0; 145 146 for (const dir of packageJsonDirs) { 147 const relativePath = path.relative(__dirname, dir) || '.'; 148 try { 149 if (hasNodeModules(dir)) { 150 skippedCount++; 151 continue; 152 } 153 await runNpmInstall(dir); 154 successCount++; 155 } catch (error) { 156 console.error(`❌ Failed to run npm install in ${relativePath}: ${error.message}`); 157 failureCount++; 158 } 159 } 160 161 console.log("\n📊 Installation Summary:"); 162 console.log(` ✅ Successful installations: ${successCount}`); 163 console.log(` ⏭️ Skipped (already installed): ${skippedCount}`); 164 console.log(` ❌ Failed installations: ${failureCount}`); 165}; 166 167// Run the main function 168installDependenciesInDirectories();