appclean 1.8.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/GUI_IMPLEMENTATION_STATUS.md +143 -0
- package/MD_Files/INDEX.md +51 -0
- package/MD_Files/PUBLICATION_SUCCESS_REPORT.md +227 -0
- package/PHASE2_COMPLETION.md +281 -0
- package/PHASE3_COMPLETION.md +364 -0
- package/README.md +446 -376
- package/assets/logo.svg +34 -0
- package/dist/core/appUpdateChecker.js +12 -16
- package/dist/core/appUpdateChecker.js.map +1 -1
- package/dist/core/detector.js +14 -18
- package/dist/core/detector.js.map +1 -1
- package/dist/core/duplicateFileFinder.js +12 -19
- package/dist/core/duplicateFileFinder.js.map +1 -1
- package/dist/core/orphanedDependencyDetector.js +19 -26
- package/dist/core/orphanedDependencyDetector.js.map +1 -1
- package/dist/core/performanceOptimizer.js +6 -10
- package/dist/core/performanceOptimizer.js.map +1 -1
- package/dist/core/permissionHandler.js +21 -25
- package/dist/core/permissionHandler.js.map +1 -1
- package/dist/core/pluginSystem.js +9 -13
- package/dist/core/pluginSystem.js.map +1 -1
- package/dist/core/removalRecorder.js +12 -19
- package/dist/core/removalRecorder.js.map +1 -1
- package/dist/core/remover.js +59 -66
- package/dist/core/remover.js.map +1 -1
- package/dist/core/reportGenerator.d.ts +1 -1
- package/dist/core/reportGenerator.d.ts.map +1 -1
- package/dist/core/reportGenerator.js +27 -34
- package/dist/core/reportGenerator.js.map +1 -1
- package/dist/core/scheduledCleanup.js +23 -30
- package/dist/core/scheduledCleanup.js.map +1 -1
- package/dist/core/serviceFileDetector.js +24 -31
- package/dist/core/serviceFileDetector.js.map +1 -1
- package/dist/core/verificationModule.js +10 -14
- package/dist/core/verificationModule.js.map +1 -1
- package/dist/index.js +190 -90
- package/dist/index.js.map +1 -1
- package/dist/managers/brewManager.d.ts.map +1 -1
- package/dist/managers/brewManager.js +35 -41
- package/dist/managers/brewManager.js.map +1 -1
- package/dist/managers/customManager.d.ts +2 -1
- package/dist/managers/customManager.d.ts.map +1 -1
- package/dist/managers/customManager.js +79 -53
- package/dist/managers/customManager.js.map +1 -1
- package/dist/managers/linuxManager.js +29 -36
- package/dist/managers/linuxManager.js.map +1 -1
- package/dist/managers/npmManager.js +27 -34
- package/dist/managers/npmManager.js.map +1 -1
- package/dist/types/index.js +1 -2
- package/dist/ui/client/api/client.d.ts +24 -0
- package/dist/ui/client/api/client.d.ts.map +1 -0
- package/dist/ui/client/api/client.js +96 -0
- package/dist/ui/client/api/client.js.map +1 -0
- package/dist/ui/client/app.d.ts +7 -0
- package/dist/ui/client/app.d.ts.map +1 -0
- package/dist/ui/client/app.js +71 -0
- package/dist/ui/client/app.js.map +1 -0
- package/dist/ui/client/index.html +107 -0
- package/dist/ui/client/pages/appDetails.d.ts +8 -0
- package/dist/ui/client/pages/appDetails.d.ts.map +1 -0
- package/dist/ui/client/pages/appDetails.js +287 -0
- package/dist/ui/client/pages/appDetails.js.map +1 -0
- package/dist/ui/client/pages/appSearch.d.ts +2 -0
- package/dist/ui/client/pages/appSearch.d.ts.map +1 -0
- package/dist/ui/client/pages/appSearch.js +210 -0
- package/dist/ui/client/pages/appSearch.js.map +1 -0
- package/dist/ui/client/pages/dashboard.d.ts +2 -0
- package/dist/ui/client/pages/dashboard.d.ts.map +1 -0
- package/dist/ui/client/pages/dashboard.js +154 -0
- package/dist/ui/client/pages/dashboard.js.map +1 -0
- package/dist/ui/client/pages/settings.d.ts +7 -0
- package/dist/ui/client/pages/settings.d.ts.map +1 -0
- package/dist/ui/client/pages/settings.js +279 -0
- package/dist/ui/client/pages/settings.js.map +1 -0
- package/dist/ui/client/state/appStore.d.ts +38 -0
- package/dist/ui/client/state/appStore.d.ts.map +1 -0
- package/dist/ui/client/state/appStore.js +121 -0
- package/dist/ui/client/state/appStore.js.map +1 -0
- package/dist/ui/client/state/dashboardStore.d.ts +31 -0
- package/dist/ui/client/state/dashboardStore.d.ts.map +1 -0
- package/dist/ui/client/state/dashboardStore.js +70 -0
- package/dist/ui/client/state/dashboardStore.js.map +1 -0
- package/dist/ui/client/state/uiStore.d.ts +43 -0
- package/dist/ui/client/state/uiStore.d.ts.map +1 -0
- package/dist/ui/client/state/uiStore.js +109 -0
- package/dist/ui/client/state/uiStore.js.map +1 -0
- package/dist/ui/client/styles/animations.css +327 -0
- package/dist/ui/client/styles/base.css +214 -0
- package/dist/ui/client/styles/components.css +400 -0
- package/dist/ui/client/styles/layout.css +224 -0
- package/dist/ui/client/styles/variables.css +140 -0
- package/dist/ui/client/utils/events.d.ts +19 -0
- package/dist/ui/client/utils/events.d.ts.map +1 -0
- package/dist/ui/client/utils/events.js +54 -0
- package/dist/ui/client/utils/events.js.map +1 -0
- package/dist/ui/client/utils/formatting.d.ts +11 -0
- package/dist/ui/client/utils/formatting.d.ts.map +1 -0
- package/dist/ui/client/utils/formatting.js +104 -0
- package/dist/ui/client/utils/formatting.js.map +1 -0
- package/dist/ui/client/utils/router.d.ts +25 -0
- package/dist/ui/client/utils/router.d.ts.map +1 -0
- package/dist/ui/client/utils/router.js +90 -0
- package/dist/ui/client/utils/router.js.map +1 -0
- package/dist/ui/guiServer.d.ts +8 -1
- package/dist/ui/guiServer.d.ts.map +1 -1
- package/dist/ui/guiServer.js +148 -110
- package/dist/ui/guiServer.js.map +1 -1
- package/dist/ui/menu.js +18 -27
- package/dist/ui/menu.js.map +1 -1
- package/dist/ui/prompts.js +34 -47
- package/dist/ui/prompts.js.map +1 -1
- package/dist/ui/server/middleware/errorHandler.d.ts +19 -0
- package/dist/ui/server/middleware/errorHandler.d.ts.map +1 -0
- package/dist/ui/server/middleware/errorHandler.js +100 -0
- package/dist/ui/server/middleware/errorHandler.js.map +1 -0
- package/dist/ui/server/routes/apps.d.ts +8 -0
- package/dist/ui/server/routes/apps.d.ts.map +1 -0
- package/dist/ui/server/routes/apps.js +74 -0
- package/dist/ui/server/routes/apps.js.map +1 -0
- package/dist/ui/server/routes/dashboard.d.ts +4 -0
- package/dist/ui/server/routes/dashboard.d.ts.map +1 -0
- package/dist/ui/server/routes/dashboard.js +57 -0
- package/dist/ui/server/routes/dashboard.js.map +1 -0
- package/dist/ui/server/routes/settings.d.ts +6 -0
- package/dist/ui/server/routes/settings.d.ts.map +1 -0
- package/dist/ui/server/routes/settings.js +31 -0
- package/dist/ui/server/routes/settings.js.map +1 -0
- package/dist/ui/server/services/appService.d.ts +45 -0
- package/dist/ui/server/services/appService.d.ts.map +1 -0
- package/dist/ui/server/services/appService.js +114 -0
- package/dist/ui/server/services/appService.js.map +1 -0
- package/dist/ui/server/services/removalService.d.ts +24 -0
- package/dist/ui/server/services/removalService.d.ts.map +1 -0
- package/dist/ui/server/services/removalService.js +83 -0
- package/dist/ui/server/services/removalService.js.map +1 -0
- package/dist/utils/filesystem.js +32 -49
- package/dist/utils/filesystem.js.map +1 -1
- package/dist/utils/logger.js +9 -18
- package/dist/utils/logger.js.map +1 -1
- package/dist/utils/platform.js +10 -22
- package/dist/utils/platform.js.map +1 -1
- package/dist/utils/upgrade.d.ts +22 -0
- package/dist/utils/upgrade.d.ts.map +1 -0
- package/dist/utils/upgrade.js +94 -0
- package/dist/utils/upgrade.js.map +1 -0
- package/package.json +4 -2
- package/src/core/appUpdateChecker.ts +1 -1
- package/src/core/detector.ts +6 -6
- package/src/core/duplicateFileFinder.ts +1 -1
- package/src/core/orphanedDependencyDetector.ts +2 -2
- package/src/core/performanceOptimizer.ts +1 -1
- package/src/core/permissionHandler.ts +2 -2
- package/src/core/pluginSystem.ts +1 -1
- package/src/core/removalRecorder.ts +2 -2
- package/src/core/remover.ts +11 -11
- package/src/core/reportGenerator.ts +2 -2
- package/src/core/scheduledCleanup.ts +2 -2
- package/src/core/serviceFileDetector.ts +2 -2
- package/src/core/verificationModule.ts +2 -2
- package/src/index.ts +133 -6
- package/src/managers/brewManager.ts +11 -9
- package/src/managers/customManager.ts +71 -30
- package/src/managers/linuxManager.ts +3 -3
- package/src/managers/npmManager.ts +3 -3
- package/src/ui/client/api/client.ts +163 -0
- package/src/ui/client/app.ts +121 -0
- package/src/ui/client/index.html +107 -0
- package/src/ui/client/pages/appDetails.ts +356 -0
- package/src/ui/client/pages/appSearch.ts +270 -0
- package/src/ui/client/pages/dashboard.ts +189 -0
- package/src/ui/client/pages/settings.ts +342 -0
- package/src/ui/client/state/appStore.ts +169 -0
- package/src/ui/client/state/dashboardStore.ts +113 -0
- package/src/ui/client/state/uiStore.ts +166 -0
- package/src/ui/client/styles/animations.css +327 -0
- package/src/ui/client/styles/base.css +214 -0
- package/src/ui/client/styles/components.css +400 -0
- package/src/ui/client/styles/layout.css +224 -0
- package/src/ui/client/styles/variables.css +140 -0
- package/src/ui/client/utils/events.ts +74 -0
- package/src/ui/client/utils/formatting.ts +157 -0
- package/src/ui/client/utils/router.ts +161 -0
- package/src/ui/guiServer.ts +206 -105
- package/src/ui/prompts.ts +1 -1
- package/src/ui/server/middleware/errorHandler.ts +174 -0
- package/src/ui/server/routes/apps.ts +132 -0
- package/src/ui/server/routes/dashboard.ts +93 -0
- package/src/ui/server/routes/settings.ts +63 -0
- package/src/ui/server/services/appService.ts +184 -0
- package/src/ui/server/services/removalService.ts +138 -0
- package/src/utils/upgrade.ts +143 -0
- package/tsconfig.json +3 -2
- package/INDEX.md +0 -165
- /package/{ACTION_CHECKLIST.md → MD_Files/ACTION_CHECKLIST.md} +0 -0
- /package/{APPCLEAN_SUMMARY.md → MD_Files/APPCLEAN_SUMMARY.md} +0 -0
- /package/{CHANGELOG.md → MD_Files/CHANGELOG.md} +0 -0
- /package/{CODE_OF_CONDUCT.md → MD_Files/CODE_OF_CONDUCT.md} +0 -0
- /package/{CODE_REVIEW_REPORT.md → MD_Files/CODE_REVIEW_REPORT.md} +0 -0
- /package/{COMMUNITY_POSTS.md → MD_Files/COMMUNITY_POSTS.md} +0 -0
- /package/{DEPLOYMENT_GUIDE.md → MD_Files/DEPLOYMENT_GUIDE.md} +0 -0
- /package/{DEPLOYMENT_STATUS.md → MD_Files/DEPLOYMENT_STATUS.md} +0 -0
- /package/{EXECUTIVE_REPORT.md → MD_Files/EXECUTIVE_REPORT.md} +0 -0
- /package/{GITHUB_OPTIMIZATION.md → MD_Files/GITHUB_OPTIMIZATION.md} +0 -0
- /package/{MARKETING_SUMMARY.md → MD_Files/MARKETING_SUMMARY.md} +0 -0
- /package/{NPM_PACKAGE_OPTIMIZATION.md → MD_Files/NPM_PACKAGE_OPTIMIZATION.md} +0 -0
- /package/{NPM_PUBLISH.md → MD_Files/NPM_PUBLISH.md} +0 -0
- /package/{PROJECT_SUMMARY.txt → MD_Files/PROJECT_SUMMARY.txt} +0 -0
- /package/{QUICKSTART.md → MD_Files/QUICKSTART.md} +0 -0
- /package/{SETUP_GITHUB.md → MD_Files/SETUP_GITHUB.md} +0 -0
- /package/{TESTING_SUMMARY.md → MD_Files/TESTING_SUMMARY.md} +0 -0
- /package/{setup-github.sh → MD_Files/setup-github.sh} +0 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import { Logger } from './logger.js';
|
|
3
|
+
export class UpgradeManager {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.packageName = 'appclean';
|
|
6
|
+
this.currentVersion = '1.9.0';
|
|
7
|
+
}
|
|
8
|
+
async getVersionInfo() {
|
|
9
|
+
try {
|
|
10
|
+
const output = execSync(`npm view ${this.packageName} version --json`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
11
|
+
const latestVersion = output.replace(/"/g, '');
|
|
12
|
+
const isUpdateAvailable = this.compareVersions(this.currentVersion, latestVersion);
|
|
13
|
+
return {
|
|
14
|
+
current: this.currentVersion,
|
|
15
|
+
latest: latestVersion,
|
|
16
|
+
isUpdateAvailable,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
Logger.debug('Failed to check npm registry: ' + error.message);
|
|
21
|
+
return {
|
|
22
|
+
current: this.currentVersion,
|
|
23
|
+
latest: this.currentVersion,
|
|
24
|
+
isUpdateAvailable: false,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
compareVersions(current, latest) {
|
|
29
|
+
const currentParts = current.split('.').map(Number);
|
|
30
|
+
const latestParts = latest.split('.').map(Number);
|
|
31
|
+
for (let i = 0; i < 3; i++) {
|
|
32
|
+
const curr = currentParts[i] || 0;
|
|
33
|
+
const lat = latestParts[i] || 0;
|
|
34
|
+
if (lat > curr)
|
|
35
|
+
return true;
|
|
36
|
+
if (lat < curr)
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
async upgrade() {
|
|
42
|
+
try {
|
|
43
|
+
Logger.info('Checking for updates...');
|
|
44
|
+
const versionInfo = await this.getVersionInfo();
|
|
45
|
+
if (!versionInfo.isUpdateAvailable) {
|
|
46
|
+
return {
|
|
47
|
+
success: true,
|
|
48
|
+
message: `AppClean is already up to date (v${versionInfo.current})`,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
Logger.info(`Upgrading from v${versionInfo.current} to v${versionInfo.latest}...`);
|
|
52
|
+
execSync(`npm install -g ${this.packageName}@latest`, {
|
|
53
|
+
stdio: 'inherit',
|
|
54
|
+
});
|
|
55
|
+
return {
|
|
56
|
+
success: true,
|
|
57
|
+
message: `Successfully upgraded to v${versionInfo.latest}`,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
const errorMsg = error.message;
|
|
62
|
+
return {
|
|
63
|
+
success: false,
|
|
64
|
+
message: `Upgrade failed: ${errorMsg}`,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
getCurrentVersion() {
|
|
69
|
+
return this.currentVersion;
|
|
70
|
+
}
|
|
71
|
+
async checkForUpdates() {
|
|
72
|
+
return this.getVersionInfo();
|
|
73
|
+
}
|
|
74
|
+
async uninstall() {
|
|
75
|
+
try {
|
|
76
|
+
Logger.info('Uninstalling AppClean...');
|
|
77
|
+
execSync(`npm uninstall -g ${this.packageName}`, {
|
|
78
|
+
stdio: 'inherit',
|
|
79
|
+
});
|
|
80
|
+
return {
|
|
81
|
+
success: true,
|
|
82
|
+
message: `AppClean has been successfully uninstalled from your system.`,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
const errorMsg = error.message;
|
|
87
|
+
return {
|
|
88
|
+
success: false,
|
|
89
|
+
message: `Uninstall failed: ${errorMsg}`,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=upgrade.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upgrade.js","sourceRoot":"","sources":["../../src/utils/upgrade.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "appclean",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"description": "A powerful CLI tool to intelligently find and safely uninstall applications from your system with all their artifacts",
|
|
5
6
|
"main": "dist/index.js",
|
|
6
7
|
"bin": {
|
|
7
8
|
"appclean": "dist/index.js"
|
|
8
9
|
},
|
|
9
10
|
"scripts": {
|
|
10
|
-
"build": "tsc",
|
|
11
|
+
"build": "tsc && npm run copy-assets",
|
|
12
|
+
"copy-assets": "mkdir -p dist/ui/client/styles && cp src/ui/client/index.html dist/ui/client/ && cp src/ui/client/styles/*.css dist/ui/client/styles/",
|
|
11
13
|
"dev": "ts-node src/index.ts",
|
|
12
14
|
"start": "node dist/index.js",
|
|
13
15
|
"test": "jest",
|
package/src/core/detector.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { NpmManager } from '../managers/npmManager';
|
|
2
|
-
import { BrewManager } from '../managers/brewManager';
|
|
3
|
-
import { LinuxManager } from '../managers/linuxManager';
|
|
4
|
-
import { CustomManager } from '../managers/customManager';
|
|
5
|
-
import { isMacOS, isLinux } from '../utils/platform';
|
|
1
|
+
import { NpmManager } from '../managers/npmManager.js';
|
|
2
|
+
import { BrewManager } from '../managers/brewManager.js';
|
|
3
|
+
import { LinuxManager } from '../managers/linuxManager.js';
|
|
4
|
+
import { CustomManager } from '../managers/customManager.js';
|
|
5
|
+
import { isMacOS, isLinux } from '../utils/platform.js';
|
|
6
6
|
import { InstalledApp, ArtifactPath, SearchOptions } from '../types';
|
|
7
|
-
import { getFileSize } from '../utils/filesystem';
|
|
7
|
+
import { getFileSize } from '../utils/filesystem.js';
|
|
8
8
|
|
|
9
9
|
export class Detector {
|
|
10
10
|
private npmManager: NpmManager;
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { execSync } from 'child_process';
|
|
8
|
-
import { getHomeDir } from '../utils/platform';
|
|
8
|
+
import { getHomeDir } from '../utils/platform.js';
|
|
9
9
|
import path from 'path';
|
|
10
10
|
import fs from 'fs';
|
|
11
|
-
import { Logger } from '../utils/logger';
|
|
11
|
+
import { Logger } from '../utils/logger.js';
|
|
12
12
|
|
|
13
13
|
export interface OrphanedPackage {
|
|
14
14
|
name: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { execSync } from 'child_process';
|
|
2
|
-
import { isMacOS, isLinux, isWindows } from '../utils/platform';
|
|
3
|
-
import { Logger } from '../utils/logger';
|
|
2
|
+
import { isMacOS, isLinux, isWindows } from '../utils/platform.js';
|
|
3
|
+
import { Logger } from '../utils/logger.js';
|
|
4
4
|
|
|
5
5
|
export class PermissionHandler {
|
|
6
6
|
/**
|
package/src/core/pluginSystem.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import { getHomeDir } from '../utils/platform';
|
|
3
|
+
import { getHomeDir } from '../utils/platform.js';
|
|
4
4
|
import { ArtifactPath } from '../types';
|
|
5
|
-
import { formatDate, formatBytes } from '../utils/logger';
|
|
5
|
+
import { formatDate, formatBytes } from '../utils/logger.js';
|
|
6
6
|
|
|
7
7
|
export interface RemovalRecord {
|
|
8
8
|
timestamp: Date;
|
package/src/core/remover.ts
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
2
|
import { execSync } from 'child_process';
|
|
3
|
-
import { getHomeDir } from '../utils/platform';
|
|
3
|
+
import { getHomeDir } from '../utils/platform.js';
|
|
4
4
|
import {
|
|
5
5
|
deleteFile,
|
|
6
6
|
deleteDirectory,
|
|
7
7
|
pathExists,
|
|
8
8
|
getDirectorySize,
|
|
9
|
-
} from '../utils/filesystem';
|
|
9
|
+
} from '../utils/filesystem.js';
|
|
10
10
|
import { ArtifactPath, RemovalOptions, RemovalResult } from '../types';
|
|
11
|
-
import { Logger, formatBytes } from '../utils/logger';
|
|
12
|
-
import { NpmManager } from '../managers/npmManager';
|
|
13
|
-
import { BrewManager } from '../managers/brewManager';
|
|
14
|
-
import { LinuxManager } from '../managers/linuxManager';
|
|
15
|
-
import { PermissionHandler } from './permissionHandler';
|
|
16
|
-
import { ServiceFileDetector } from './serviceFileDetector';
|
|
17
|
-
import { RemovalRecorder, RemovalRecord } from './removalRecorder';
|
|
18
|
-
import { ReportGenerator } from './reportGenerator';
|
|
19
|
-
import { VerificationModule } from './verificationModule';
|
|
11
|
+
import { Logger, formatBytes } from '../utils/logger.js';
|
|
12
|
+
import { NpmManager } from '../managers/npmManager.js';
|
|
13
|
+
import { BrewManager } from '../managers/brewManager.js';
|
|
14
|
+
import { LinuxManager } from '../managers/linuxManager.js';
|
|
15
|
+
import { PermissionHandler } from './permissionHandler.js';
|
|
16
|
+
import { ServiceFileDetector } from './serviceFileDetector.js';
|
|
17
|
+
import { RemovalRecorder, RemovalRecord } from './removalRecorder.js';
|
|
18
|
+
import { ReportGenerator } from './reportGenerator.js';
|
|
19
|
+
import { VerificationModule } from './verificationModule.js';
|
|
20
20
|
|
|
21
21
|
export class Remover {
|
|
22
22
|
async previewRemoval(artifacts: ArtifactPath[]): Promise<void> {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
|
-
import { RemovalRecord, DeletedArtifact } from './removalRecorder';
|
|
5
|
-
import { formatBytes, formatDate } from '../utils/logger';
|
|
4
|
+
import { RemovalRecord, DeletedArtifact } from './removalRecorder.js';
|
|
5
|
+
import { formatBytes, formatDate } from '../utils/logger.js';
|
|
6
6
|
|
|
7
7
|
export const REMOVAL_DISCLAIMER = `
|
|
8
8
|
╔════════════════════════════════════════════════════════════════════════════╗
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* v1.6.0 Feature
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { getHomeDir } from '../utils/platform';
|
|
7
|
+
import { getHomeDir } from '../utils/platform.js';
|
|
8
8
|
import path from 'path';
|
|
9
9
|
import fs from 'fs';
|
|
10
|
-
import { Logger } from '../utils/logger';
|
|
10
|
+
import { Logger } from '../utils/logger.js';
|
|
11
11
|
|
|
12
12
|
export type CleanupFrequency = 'daily' | 'weekly' | 'monthly' | 'custom';
|
|
13
13
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
|
-
import { isMacOS, isLinux, getHomeDir } from '../utils/platform';
|
|
3
|
-
import { pathExists, readFile, listDirectory } from '../utils/filesystem';
|
|
2
|
+
import { isMacOS, isLinux, getHomeDir } from '../utils/platform.js';
|
|
3
|
+
import { pathExists, readFile, listDirectory } from '../utils/filesystem.js';
|
|
4
4
|
import { ArtifactPath } from '../types';
|
|
5
5
|
|
|
6
6
|
export interface ServiceFile {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { execSync } from 'child_process';
|
|
2
|
-
import { isMacOS, isLinux, isWindows } from '../utils/platform';
|
|
3
|
-
import { pathExists } from '../utils/filesystem';
|
|
2
|
+
import { isMacOS, isLinux, isWindows } from '../utils/platform.js';
|
|
3
|
+
import { pathExists } from '../utils/filesystem.js';
|
|
4
4
|
|
|
5
5
|
export type VerificationStatus = 'verified_removed' | 'still_exists' | 'partial_removal' | 'unknown';
|
|
6
6
|
|
package/src/index.ts
CHANGED
|
@@ -3,14 +3,15 @@
|
|
|
3
3
|
import { Command } from 'commander';
|
|
4
4
|
import chalk from 'chalk';
|
|
5
5
|
import ora from 'ora';
|
|
6
|
-
import { Detector } from './core/detector';
|
|
7
|
-
import { Remover } from './core/remover';
|
|
6
|
+
import { Detector } from './core/detector.js';
|
|
7
|
+
import { Remover } from './core/remover.js';
|
|
8
|
+
import { GUIServer } from './ui/guiServer.js';
|
|
8
9
|
import {
|
|
9
10
|
showMainMenu,
|
|
10
11
|
showAppMenu,
|
|
11
12
|
showHeader,
|
|
12
13
|
showHelp,
|
|
13
|
-
} from './ui/menu';
|
|
14
|
+
} from './ui/menu.js';
|
|
14
15
|
import {
|
|
15
16
|
promptSearchQuery,
|
|
16
17
|
promptSelectApp,
|
|
@@ -20,11 +21,12 @@ import {
|
|
|
20
21
|
promptSortBy,
|
|
21
22
|
displayAppDetails,
|
|
22
23
|
promptFinalConfirmation,
|
|
23
|
-
} from './ui/prompts';
|
|
24
|
-
import { Logger, formatBytes } from './utils/logger';
|
|
24
|
+
} from './ui/prompts.js';
|
|
25
|
+
import { Logger, formatBytes } from './utils/logger.js';
|
|
26
|
+
import { UpgradeManager } from './utils/upgrade.js';
|
|
25
27
|
import { InstalledApp } from './types';
|
|
26
28
|
|
|
27
|
-
const VERSION = '
|
|
29
|
+
const VERSION = '2.0.0';
|
|
28
30
|
|
|
29
31
|
async function interactiveMode(): Promise<void> {
|
|
30
32
|
showHeader();
|
|
@@ -424,6 +426,131 @@ async function main(): Promise<void> {
|
|
|
424
426
|
}
|
|
425
427
|
});
|
|
426
428
|
|
|
429
|
+
program
|
|
430
|
+
.command('gui')
|
|
431
|
+
.description('Launch AppClean GUI server (opens at http://localhost:3000)')
|
|
432
|
+
.option('--port <number>', 'Port to run GUI server on', '3000')
|
|
433
|
+
.action(async (options) => {
|
|
434
|
+
const port = parseInt(options.port, 10);
|
|
435
|
+
|
|
436
|
+
if (isNaN(port) || port < 1 || port > 65535) {
|
|
437
|
+
Logger.error('Invalid port number. Please use a port between 1 and 65535.');
|
|
438
|
+
process.exit(1);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
const guiServer = new GUIServer(port);
|
|
442
|
+
|
|
443
|
+
try {
|
|
444
|
+
await guiServer.start();
|
|
445
|
+
Logger.info(`AppClean GUI is running at ${chalk.cyan(`http://localhost:${port}`)}`);
|
|
446
|
+
Logger.info('Press Ctrl+C to stop the server');
|
|
447
|
+
|
|
448
|
+
// Keep the server running - handle graceful shutdown
|
|
449
|
+
process.on('SIGINT', async () => {
|
|
450
|
+
Logger.info('Shutting down...');
|
|
451
|
+
await guiServer.stop();
|
|
452
|
+
process.exit(0);
|
|
453
|
+
});
|
|
454
|
+
} catch (error) {
|
|
455
|
+
Logger.error(`Failed to start GUI server: ${(error as Error).message}`);
|
|
456
|
+
process.exit(1);
|
|
457
|
+
}
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
program
|
|
461
|
+
.command('upgrade')
|
|
462
|
+
.description('Upgrade AppClean to the latest version')
|
|
463
|
+
.action(async () => {
|
|
464
|
+
const upgradeManager = new UpgradeManager();
|
|
465
|
+
|
|
466
|
+
Logger.space();
|
|
467
|
+
|
|
468
|
+
try {
|
|
469
|
+
const result = await upgradeManager.upgrade();
|
|
470
|
+
|
|
471
|
+
if (result.success) {
|
|
472
|
+
Logger.success(result.message);
|
|
473
|
+
} else {
|
|
474
|
+
Logger.warn(result.message);
|
|
475
|
+
}
|
|
476
|
+
} catch (error) {
|
|
477
|
+
Logger.error(`Upgrade failed: ${(error as Error).message}`);
|
|
478
|
+
process.exit(1);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
Logger.space();
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
program
|
|
485
|
+
.command('check-update')
|
|
486
|
+
.description('Check if a new version of AppClean is available')
|
|
487
|
+
.action(async () => {
|
|
488
|
+
const upgradeManager = new UpgradeManager();
|
|
489
|
+
|
|
490
|
+
Logger.space();
|
|
491
|
+
|
|
492
|
+
try {
|
|
493
|
+
const versionInfo = await upgradeManager.checkForUpdates();
|
|
494
|
+
|
|
495
|
+
Logger.info(`Current version: ${chalk.cyan(`v${versionInfo.current}`)}`);
|
|
496
|
+
Logger.info(`Latest version: ${chalk.cyan(`v${versionInfo.latest}`)}`);
|
|
497
|
+
|
|
498
|
+
if (versionInfo.isUpdateAvailable) {
|
|
499
|
+
Logger.warn(
|
|
500
|
+
`A new version is available! Run ${chalk.bold('appclean upgrade')} to update.`
|
|
501
|
+
);
|
|
502
|
+
} else {
|
|
503
|
+
Logger.success('AppClean is up to date!');
|
|
504
|
+
}
|
|
505
|
+
} catch (error) {
|
|
506
|
+
Logger.error(
|
|
507
|
+
`Failed to check for updates: ${(error as Error).message}`
|
|
508
|
+
);
|
|
509
|
+
process.exit(1);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
Logger.space();
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
program
|
|
516
|
+
.command('uninstall')
|
|
517
|
+
.description('Uninstall AppClean from your system')
|
|
518
|
+
.option('--force', 'Skip confirmation prompt')
|
|
519
|
+
.action(async (options) => {
|
|
520
|
+
Logger.space();
|
|
521
|
+
Logger.warn('⚠️ This will uninstall AppClean from your system.');
|
|
522
|
+
|
|
523
|
+
// Show confirmation if not using --force
|
|
524
|
+
if (!options.force) {
|
|
525
|
+
const { promptConfirmRemoval } = await import('./ui/prompts');
|
|
526
|
+
const confirmed = await promptConfirmRemoval('AppClean');
|
|
527
|
+
|
|
528
|
+
if (!confirmed) {
|
|
529
|
+
Logger.info('Uninstall cancelled');
|
|
530
|
+
Logger.space();
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
const upgradeManager = new UpgradeManager();
|
|
536
|
+
|
|
537
|
+
try {
|
|
538
|
+
const result = await upgradeManager.uninstall();
|
|
539
|
+
|
|
540
|
+
if (result.success) {
|
|
541
|
+
Logger.success(result.message);
|
|
542
|
+
Logger.info('Thank you for using AppClean!');
|
|
543
|
+
} else {
|
|
544
|
+
Logger.warn(result.message);
|
|
545
|
+
}
|
|
546
|
+
} catch (error) {
|
|
547
|
+
Logger.error(`Uninstall failed: ${(error as Error).message}`);
|
|
548
|
+
process.exit(1);
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
Logger.space();
|
|
552
|
+
});
|
|
553
|
+
|
|
427
554
|
program.on('command:*', () => {
|
|
428
555
|
if (process.argv.length < 3) {
|
|
429
556
|
interactiveMode().catch((error) => {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { execSync } from 'child_process';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import { getHomeDir } from '../utils/platform';
|
|
4
|
-
import { pathExists, listDirectory } from '../utils/filesystem';
|
|
3
|
+
import { getHomeDir } from '../utils/platform.js';
|
|
4
|
+
import { pathExists, listDirectory } from '../utils/filesystem.js';
|
|
5
5
|
import { InstalledApp, ArtifactPath } from '../types';
|
|
6
|
-
import { Logger } from '../utils/logger';
|
|
6
|
+
import { Logger } from '../utils/logger.js';
|
|
7
7
|
|
|
8
8
|
export class BrewManager {
|
|
9
9
|
private brewPrefix: string;
|
|
@@ -28,16 +28,18 @@ export class BrewManager {
|
|
|
28
28
|
const packages: InstalledApp[] = [];
|
|
29
29
|
|
|
30
30
|
try {
|
|
31
|
-
|
|
32
|
-
const
|
|
31
|
+
// Use 'brew list -1' which outputs one package per line
|
|
32
|
+
const output = execSync('brew list -1').toString();
|
|
33
|
+
const lines = output.split('\n').filter((line) => line.trim().length > 0);
|
|
33
34
|
|
|
34
|
-
for (const pkg of
|
|
35
|
-
const
|
|
35
|
+
for (const pkg of lines) {
|
|
36
|
+
const packageName = pkg.trim();
|
|
37
|
+
const cellarPath = path.join(this.brewPrefix, 'Cellar', packageName);
|
|
36
38
|
packages.push({
|
|
37
|
-
name:
|
|
39
|
+
name: packageName,
|
|
38
40
|
version: 'unknown',
|
|
39
41
|
installMethod: 'brew',
|
|
40
|
-
mainPath:
|
|
42
|
+
mainPath: cellarPath,
|
|
41
43
|
installedDate: undefined,
|
|
42
44
|
});
|
|
43
45
|
}
|
|
@@ -1,21 +1,57 @@
|
|
|
1
1
|
import path from 'path';
|
|
2
|
-
import { getHomeDir } from '../utils/platform';
|
|
2
|
+
import { getHomeDir } from '../utils/platform.js';
|
|
3
3
|
import {
|
|
4
4
|
pathExists,
|
|
5
5
|
listDirectory,
|
|
6
6
|
readFile,
|
|
7
7
|
listDirectoryDeep,
|
|
8
|
-
} from '../utils/filesystem';
|
|
8
|
+
} from '../utils/filesystem.js';
|
|
9
9
|
import { InstalledApp, ArtifactPath } from '../types';
|
|
10
10
|
|
|
11
11
|
export class CustomManager {
|
|
12
|
+
// List of known system utilities that should be excluded
|
|
13
|
+
private readonly systemBinaries = new Set([
|
|
14
|
+
'2to3', 'actool', 'afclip', 'arch', 'asa', 'awk', 'bash', 'basename',
|
|
15
|
+
'bc', 'bdiff', 'bg', 'bison', 'cat', 'cc', 'chgrp', 'chmod', 'chown',
|
|
16
|
+
'cksum', 'clang', 'cmake', 'codesign', 'comm', 'cp', 'cpp', 'cut',
|
|
17
|
+
'date', 'dd', 'defaults', 'df', 'diff', 'diffstat', 'dill', 'dirname',
|
|
18
|
+
'dmesg', 'du', 'ed', 'env', 'expand', 'expr', 'false', 'file', 'find',
|
|
19
|
+
'flex', 'fold', 'fsync', 'gawk', 'gcc', 'gcov', 'gdb', 'getconf', 'getopt',
|
|
20
|
+
'git', 'git-receive-pack', 'git-shell', 'git-upload-archive', 'git-upload-pack',
|
|
21
|
+
'glob', 'gnumake', 'go', 'grep', 'gzip', 'head', 'hexdump', 'hostname',
|
|
22
|
+
'id', 'install', 'ipcalc', 'join', 'kill', 'killall', 'lame', 'ld',
|
|
23
|
+
'ldd', 'less', 'lex', 'link', 'ln', 'locale', 'localedef', 'locate',
|
|
24
|
+
'logger', 'login', 'logname', 'ls', 'lsattr', 'lsof', 'lz4', 'make',
|
|
25
|
+
'man', 'md5sum', 'mddigest', 'mknod', 'mmap', 'mount', 'mv', 'netstat',
|
|
26
|
+
'nl', 'nm', 'nohup', 'od', 'openssl', 'paste', 'patch', 'pax', 'pbcopy',
|
|
27
|
+
'pbpaste', 'perl', 'php', 'ping', 'pkill', 'plutil', 'printf', 'ps',
|
|
28
|
+
'pwd', 'python', 'python3', 'python2', 'ranlib', 'realpath', 'renice',
|
|
29
|
+
'rev', 'rm', 'rmdir', 'ruby', 'sed', 'seq', 'sh', 'shasum', 'shell_cmds',
|
|
30
|
+
'sleep', 'sort', 'split', 'stat', 'strings', 'strip', 'sudo', 'sum',
|
|
31
|
+
'swift', 'swiftc', 'tail', 'tar', 'tee', 'test', 'tic', 'touch', 'tr',
|
|
32
|
+
'true', 'tsort', 'tty', 'uname', 'uncompress', 'uniq', 'unlink', 'unzip',
|
|
33
|
+
'users', 'uuidgen', 'uuencode', 'uudecode', 'vchk', 'vis', 'wc', 'what',
|
|
34
|
+
'whereis', 'which', 'while', 'whoami', 'whois', 'xargs', 'xcode-select',
|
|
35
|
+
'xcodebuild', 'xml2-config', 'xmllint', 'xz', 'yes', 'zcat', 'zip', 'zsh',
|
|
36
|
+
// PostScript and Ghostscript utilities
|
|
37
|
+
'dvipdf', 'eps2eps', 'pdf2ps', 'ps2ascii', 'ps2epsi', 'ps2pdf', 'ps2pdf12',
|
|
38
|
+
'ps2pdf13', 'ps2pdf14', 'ps2pdfwr', 'ps2ps', 'ps2ps2', 'pf2afm', 'pfbtopfa',
|
|
39
|
+
'pphs', 'printafm', 'prlcopy', 'prlctl', 'prlexec', 'prlsrvctl', 'prl_convert',
|
|
40
|
+
'prl_disk_tool', 'prl_perf_ctl',
|
|
41
|
+
// Ghostscript
|
|
42
|
+
'gsbj', 'gsdj', 'gsdj500', 'gslj', 'gslp', 'gsnd',
|
|
43
|
+
// System scripts (shell scripts)
|
|
44
|
+
'lprsetup.sh', 'unix-lpr.sh', 'uninstall-container.sh', 'update-container.sh',
|
|
45
|
+
]);
|
|
46
|
+
|
|
12
47
|
async findCustomInstalledApps(): Promise<InstalledApp[]> {
|
|
13
48
|
const apps: InstalledApp[] = [];
|
|
14
49
|
const home = getHomeDir();
|
|
15
50
|
|
|
51
|
+
// Only check user-installed binaries in ~/.local/bin and /usr/local/bin
|
|
52
|
+
// Completely skip /usr/bin as it's all system utilities
|
|
16
53
|
const customBinPaths = [
|
|
17
54
|
'/usr/local/bin',
|
|
18
|
-
'/usr/bin',
|
|
19
55
|
`${home}/.local/bin`,
|
|
20
56
|
];
|
|
21
57
|
|
|
@@ -31,47 +67,52 @@ export class CustomManager {
|
|
|
31
67
|
// Skip if already found
|
|
32
68
|
if (foundBinaries.has(binary)) continue;
|
|
33
69
|
|
|
34
|
-
//
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
//
|
|
38
|
-
if (
|
|
39
|
-
|
|
40
|
-
apps.push({
|
|
41
|
-
name: binary,
|
|
42
|
-
version: 'unknown',
|
|
43
|
-
installMethod: 'custom',
|
|
44
|
-
mainPath: fullPath,
|
|
45
|
-
installedDate: undefined,
|
|
46
|
-
});
|
|
70
|
+
// Skip known system binaries
|
|
71
|
+
if (this.systemBinaries.has(binary)) continue;
|
|
72
|
+
|
|
73
|
+
// Skip if it looks like a system binary
|
|
74
|
+
if (await this.isSystemBinary(binary, fullPath)) {
|
|
75
|
+
continue;
|
|
47
76
|
}
|
|
77
|
+
|
|
78
|
+
foundBinaries.add(binary);
|
|
79
|
+
apps.push({
|
|
80
|
+
name: binary,
|
|
81
|
+
version: 'unknown',
|
|
82
|
+
installMethod: 'custom',
|
|
83
|
+
mainPath: fullPath,
|
|
84
|
+
installedDate: undefined,
|
|
85
|
+
});
|
|
48
86
|
}
|
|
49
87
|
}
|
|
50
88
|
|
|
51
89
|
return apps;
|
|
52
90
|
}
|
|
53
91
|
|
|
54
|
-
private async
|
|
92
|
+
private async isSystemBinary(binaryName: string, binaryPath: string): Promise<boolean> {
|
|
55
93
|
try {
|
|
56
94
|
const content = readFile(binaryPath);
|
|
57
|
-
if (!content)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return 'custom'; // Custom node script
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (content.includes('python') || content.includes('#!/usr/bin/env python')) {
|
|
65
|
-
return 'custom'; // Custom python script
|
|
95
|
+
if (!content) {
|
|
96
|
+
// Binary files don't have text content - likely compiled system binaries
|
|
97
|
+
// We'll only accept text-based scripts (node, python, bash)
|
|
98
|
+
return true;
|
|
66
99
|
}
|
|
67
100
|
|
|
68
|
-
|
|
69
|
-
|
|
101
|
+
// Check for common shebangs/markers that indicate user scripts
|
|
102
|
+
if (content.includes('#!/usr/bin/env node') ||
|
|
103
|
+
content.includes('#!/usr/bin/env python') ||
|
|
104
|
+
content.includes('#!/bin/bash') ||
|
|
105
|
+
content.includes('#!/bin/sh') ||
|
|
106
|
+
content.includes('#!/usr/bin/env python3') ||
|
|
107
|
+
content.includes('#!/usr/bin/perl')) {
|
|
108
|
+
return false; // It's a user script
|
|
70
109
|
}
|
|
71
110
|
|
|
72
|
-
|
|
111
|
+
// If we can't identify it, assume it's a system binary
|
|
112
|
+
return true;
|
|
73
113
|
} catch {
|
|
74
|
-
|
|
114
|
+
// If we can't read it, assume it's a system binary
|
|
115
|
+
return true;
|
|
75
116
|
}
|
|
76
117
|
}
|
|
77
118
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { execSync } from 'child_process';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import { getHomeDir } from '../utils/platform';
|
|
4
|
-
import { pathExists, listDirectory } from '../utils/filesystem';
|
|
3
|
+
import { getHomeDir } from '../utils/platform.js';
|
|
4
|
+
import { pathExists, listDirectory } from '../utils/filesystem.js';
|
|
5
5
|
import { InstalledApp, ArtifactPath } from '../types';
|
|
6
|
-
import { Logger } from '../utils/logger';
|
|
6
|
+
import { Logger } from '../utils/logger.js';
|
|
7
7
|
|
|
8
8
|
export class LinuxManager {
|
|
9
9
|
private packageManager: 'apt' | 'yum' | 'dnf' | 'unknown' = 'unknown';
|