( packageName: string, )
| 1607 | } |
| 1608 | |
| 1609 | async function attemptNpmUninstall( |
| 1610 | packageName: string, |
| 1611 | ): Promise<{ success: boolean; error?: string; warning?: string }> { |
| 1612 | const { code, stderr } = await execFileNoThrowWithCwd( |
| 1613 | 'npm', |
| 1614 | ['uninstall', '-g', packageName], |
| 1615 | // eslint-disable-next-line custom-rules/no-process-cwd -- matches original behavior |
| 1616 | { cwd: process.cwd() }, |
| 1617 | ) |
| 1618 | |
| 1619 | if (code === 0) { |
| 1620 | logForDebugging(`Removed global npm installation of ${packageName}`) |
| 1621 | return { success: true } |
| 1622 | } else if (stderr && !stderr.includes('npm ERR! code E404')) { |
| 1623 | // Check for ENOTEMPTY error and try manual removal |
| 1624 | if (stderr.includes('npm error code ENOTEMPTY')) { |
| 1625 | logForDebugging( |
| 1626 | `Failed to uninstall global npm package ${packageName}: ${stderr}`, |
| 1627 | { level: 'error' }, |
| 1628 | ) |
| 1629 | logForDebugging(`Attempting manual removal due to ENOTEMPTY error`) |
| 1630 | |
| 1631 | const manualResult = await manualRemoveNpmPackage(packageName) |
| 1632 | if (manualResult.success) { |
| 1633 | return { success: true, warning: manualResult.warning } |
| 1634 | } else if (manualResult.error) { |
| 1635 | return { |
| 1636 | success: false, |
| 1637 | error: `Failed to remove global npm installation of ${packageName}: ${stderr}. Manual removal also failed: ${manualResult.error}`, |
| 1638 | } |
| 1639 | } |
| 1640 | } |
| 1641 | |
| 1642 | // Only report as error if it's not a "package not found" error |
| 1643 | logForDebugging( |
| 1644 | `Failed to uninstall global npm package ${packageName}: ${stderr}`, |
| 1645 | { level: 'error' }, |
| 1646 | ) |
| 1647 | return { |
| 1648 | success: false, |
| 1649 | error: `Failed to remove global npm installation of ${packageName}: ${stderr}`, |
| 1650 | } |
| 1651 | } |
| 1652 | |
| 1653 | return { success: false } // Package not found, not an error |
| 1654 | } |
| 1655 | |
| 1656 | export async function cleanupNpmInstallations(): Promise<{ |
| 1657 | removed: number |
no test coverage detected