@tukuyomil032/broom 1.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.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +554 -0
  3. package/dist/commands/analyze.js +371 -0
  4. package/dist/commands/backup.js +257 -0
  5. package/dist/commands/clean.js +255 -0
  6. package/dist/commands/completion.js +714 -0
  7. package/dist/commands/config.js +474 -0
  8. package/dist/commands/doctor.js +280 -0
  9. package/dist/commands/duplicates.js +325 -0
  10. package/dist/commands/help.js +34 -0
  11. package/dist/commands/index.js +22 -0
  12. package/dist/commands/installer.js +266 -0
  13. package/dist/commands/optimize.js +270 -0
  14. package/dist/commands/purge.js +271 -0
  15. package/dist/commands/remove.js +184 -0
  16. package/dist/commands/reports.js +173 -0
  17. package/dist/commands/schedule.js +249 -0
  18. package/dist/commands/status.js +468 -0
  19. package/dist/commands/touchid.js +230 -0
  20. package/dist/commands/uninstall.js +336 -0
  21. package/dist/commands/update.js +182 -0
  22. package/dist/commands/watch.js +258 -0
  23. package/dist/index.js +131 -0
  24. package/dist/scanners/base.js +21 -0
  25. package/dist/scanners/browser-cache.js +111 -0
  26. package/dist/scanners/dev-cache.js +64 -0
  27. package/dist/scanners/docker.js +96 -0
  28. package/dist/scanners/downloads.js +66 -0
  29. package/dist/scanners/homebrew.js +82 -0
  30. package/dist/scanners/index.js +126 -0
  31. package/dist/scanners/installer.js +87 -0
  32. package/dist/scanners/ios-backups.js +82 -0
  33. package/dist/scanners/node-modules.js +75 -0
  34. package/dist/scanners/temp-files.js +65 -0
  35. package/dist/scanners/trash.js +90 -0
  36. package/dist/scanners/user-cache.js +62 -0
  37. package/dist/scanners/user-logs.js +53 -0
  38. package/dist/scanners/xcode.js +124 -0
  39. package/dist/types/index.js +23 -0
  40. package/dist/ui/index.js +5 -0
  41. package/dist/ui/monitors.js +345 -0
  42. package/dist/ui/output.js +304 -0
  43. package/dist/ui/prompts.js +270 -0
  44. package/dist/utils/config.js +133 -0
  45. package/dist/utils/debug.js +119 -0
  46. package/dist/utils/fs.js +283 -0
  47. package/dist/utils/help.js +265 -0
  48. package/dist/utils/index.js +6 -0
  49. package/dist/utils/paths.js +142 -0
  50. package/dist/utils/report.js +404 -0
  51. package/package.json +87 -0
@@ -0,0 +1,474 @@
1
+ /**
2
+ * Config command - Manage broom configuration
3
+ */
4
+ import chalk from 'chalk';
5
+ import { Command } from 'commander';
6
+ import { enhanceCommandHelp } from '../utils/help.js';
7
+ import { loadConfig, saveConfig, getConfigPath } from '../utils/config.js';
8
+ import { DEFAULT_CONFIG } from '../types/index.js';
9
+ import { printHeader, success, warning, error, info } from '../ui/output.js';
10
+ import { confirmAction, inputPrompt } from '../ui/prompts.js';
11
+ /**
12
+ * List current configuration
13
+ */
14
+ async function listConfig() {
15
+ const config = await loadConfig();
16
+ console.log(chalk.bold('📝 Current Configuration'));
17
+ console.log();
18
+ console.log(`Config file: ${chalk.dim(getConfigPath())}`);
19
+ console.log();
20
+ // Whitelist
21
+ console.log(chalk.bold('Whitelist (protected paths):'));
22
+ if (config.whitelist.length === 0) {
23
+ console.log(chalk.dim(' No paths in whitelist'));
24
+ }
25
+ else {
26
+ config.whitelist.forEach((path, i) => {
27
+ console.log(` ${chalk.cyan(`${i + 1}.`)} ${path}`);
28
+ });
29
+ }
30
+ console.log();
31
+ // Blacklist
32
+ console.log(chalk.bold('Blacklist (always include):'));
33
+ if (config.blacklist.length === 0) {
34
+ console.log(chalk.dim(' No paths in blacklist'));
35
+ }
36
+ else {
37
+ config.blacklist.forEach((path, i) => {
38
+ console.log(` ${chalk.cyan(`${i + 1}.`)} ${path}`);
39
+ });
40
+ }
41
+ console.log();
42
+ // Settings
43
+ console.log(chalk.bold('Settings:'));
44
+ console.log(` Auto confirm: ${config.autoConfirm ? chalk.green('Yes') : chalk.yellow('No')}`);
45
+ console.log(` Safety level: ${chalk.cyan(config.safetyLevel)}`);
46
+ }
47
+ /**
48
+ * Add path to whitelist
49
+ */
50
+ async function addToWhitelist(path) {
51
+ const config = await loadConfig();
52
+ if (config.whitelist.includes(path)) {
53
+ warning(`Path already in whitelist: ${path}`);
54
+ return;
55
+ }
56
+ config.whitelist.push(path);
57
+ await saveConfig(config);
58
+ success(`Added to whitelist: ${path}`);
59
+ }
60
+ /**
61
+ * Remove path from whitelist
62
+ */
63
+ async function removeFromWhitelist(index) {
64
+ const config = await loadConfig();
65
+ if (index < 1 || index > config.whitelist.length) {
66
+ error(`Invalid index: ${index}`);
67
+ return;
68
+ }
69
+ const removed = config.whitelist.splice(index - 1, 1)[0];
70
+ await saveConfig(config);
71
+ success(`Removed from whitelist: ${removed}`);
72
+ }
73
+ /**
74
+ * Add path to blacklist
75
+ */
76
+ async function addToBlacklist(path) {
77
+ const config = await loadConfig();
78
+ if (config.blacklist.includes(path)) {
79
+ warning(`Path already in blacklist: ${path}`);
80
+ return;
81
+ }
82
+ config.blacklist.push(path);
83
+ await saveConfig(config);
84
+ success(`Added to blacklist: ${path}`);
85
+ }
86
+ /**
87
+ * Remove path from blacklist
88
+ */
89
+ async function removeFromBlacklist(index) {
90
+ const config = await loadConfig();
91
+ if (index < 1 || index > config.blacklist.length) {
92
+ error(`Invalid index: ${index}`);
93
+ return;
94
+ }
95
+ const removed = config.blacklist.splice(index - 1, 1)[0];
96
+ await saveConfig(config);
97
+ success(`Removed from blacklist: ${removed}`);
98
+ }
99
+ /**
100
+ * Set safety level
101
+ */
102
+ async function setSafetyLevel(level) {
103
+ const validLevels = ['safe', 'moderate', 'risky'];
104
+ if (!validLevels.includes(level)) {
105
+ error(`Invalid safety level: ${level}`);
106
+ info(`Valid levels: ${validLevels.join(', ')}`);
107
+ return;
108
+ }
109
+ const config = await loadConfig();
110
+ config.safetyLevel = level;
111
+ await saveConfig(config);
112
+ success(`Safety level set to: ${level}`);
113
+ }
114
+ /**
115
+ * Reset configuration
116
+ */
117
+ async function resetConfig() {
118
+ const confirmed = await confirmAction('Reset configuration to defaults?', false);
119
+ if (!confirmed) {
120
+ warning('Reset cancelled');
121
+ return;
122
+ }
123
+ await saveConfig({ ...DEFAULT_CONFIG });
124
+ success('Configuration reset to defaults');
125
+ }
126
+ /**
127
+ * Execute config command
128
+ */
129
+ export async function configCommand(action, value, options) {
130
+ printHeader('⚙️ Configuration');
131
+ // Handle --list flag
132
+ if (options?.list) {
133
+ await listConfig();
134
+ return;
135
+ }
136
+ // Handle --reset flag
137
+ if (options?.reset) {
138
+ await resetConfig();
139
+ return;
140
+ }
141
+ // Interactive mode - default if no action specified
142
+ if (!action || action === 'interactive' || action === 'edit') {
143
+ await interactiveConfigEdit();
144
+ return;
145
+ }
146
+ // Handle actions
147
+ switch (action) {
148
+ case 'whitelist-add':
149
+ if (!value) {
150
+ const path = await inputPrompt('Enter path to add to whitelist:');
151
+ if (path)
152
+ await addToWhitelist(path);
153
+ }
154
+ else {
155
+ await addToWhitelist(value);
156
+ }
157
+ break;
158
+ case 'whitelist-remove':
159
+ if (!value) {
160
+ await listConfig();
161
+ const index = await inputPrompt('Enter index to remove:');
162
+ if (index)
163
+ await removeFromWhitelist(parseInt(index));
164
+ }
165
+ else {
166
+ await removeFromWhitelist(parseInt(value));
167
+ }
168
+ break;
169
+ case 'blacklist-add':
170
+ if (!value) {
171
+ const path = await inputPrompt('Enter path to add to blacklist:');
172
+ if (path)
173
+ await addToBlacklist(path);
174
+ }
175
+ else {
176
+ await addToBlacklist(value);
177
+ }
178
+ break;
179
+ case 'blacklist-remove':
180
+ if (!value) {
181
+ await listConfig();
182
+ const index = await inputPrompt('Enter index to remove:');
183
+ if (index)
184
+ await removeFromBlacklist(parseInt(index));
185
+ }
186
+ else {
187
+ await removeFromBlacklist(parseInt(value));
188
+ }
189
+ break;
190
+ case 'safety':
191
+ if (!value) {
192
+ info('Valid safety levels: safe, moderate, risky');
193
+ const level = await inputPrompt('Enter safety level:');
194
+ if (level)
195
+ await setSafetyLevel(level);
196
+ }
197
+ else {
198
+ await setSafetyLevel(value);
199
+ }
200
+ break;
201
+ case 'reset':
202
+ await resetConfig();
203
+ break;
204
+ default:
205
+ error(`Unknown action: ${action}`);
206
+ console.log();
207
+ console.log(chalk.bold('Available actions:'));
208
+ console.log(' interactive Interactive configuration editor');
209
+ console.log(' whitelist-add [path] Add path to whitelist');
210
+ console.log(' whitelist-remove [index] Remove path from whitelist');
211
+ console.log(' blacklist-add [path] Add path to blacklist');
212
+ console.log(' blacklist-remove [index] Remove path from blacklist');
213
+ console.log(' safety [level] Set safety level (safe, moderate, risky)');
214
+ console.log(' reset Reset configuration to defaults');
215
+ }
216
+ }
217
+ /**
218
+ * Interactive configuration editor
219
+ */
220
+ async function interactiveConfigEdit() {
221
+ const config = await loadConfig();
222
+ let shouldExit = false;
223
+ while (!shouldExit) {
224
+ console.log();
225
+ console.log(chalk.bold('⚙️ Configuration Editor'));
226
+ console.log(chalk.dim('Select an option to configure:'));
227
+ console.log();
228
+ console.log(` ${chalk.cyan('1')} Monitor Preset (Current: ${config.monitorPreset})`);
229
+ console.log(` ${chalk.cyan('2')} Safety Level (Current: ${config.safetyLevel})`);
230
+ console.log(` ${chalk.cyan('3')} Auto Confirm (Current: ${config.autoConfirm ? 'Yes' : 'No'})`);
231
+ console.log(` ${chalk.cyan('4')} Dry Run (Current: ${config.dryRun ? 'Yes' : 'No'})`);
232
+ console.log(` ${chalk.cyan('5')} Verbose (Current: ${config.verbose ? 'Yes' : 'No'})`);
233
+ console.log(` ${chalk.cyan('6')} Manage Whitelist (${config.whitelist.length} items)`);
234
+ console.log(` ${chalk.cyan('7')} Manage Blacklist (${config.blacklist.length} items)`);
235
+ console.log(` ${chalk.cyan('8')} View All Settings`);
236
+ console.log(` ${chalk.cyan('9')} Reset to Defaults`);
237
+ console.log(` ${chalk.cyan('0')} Exit`);
238
+ console.log();
239
+ const choice = await inputPrompt('Choose an option (0-9):');
240
+ switch (choice) {
241
+ case '1':
242
+ await configureMonitorPreset(config);
243
+ break;
244
+ case '2':
245
+ await configureSafetyLevel(config);
246
+ break;
247
+ case '3':
248
+ config.autoConfirm = !config.autoConfirm;
249
+ await saveConfig(config);
250
+ success(`Auto Confirm set to: ${config.autoConfirm ? 'Yes' : 'No'}`);
251
+ break;
252
+ case '4':
253
+ config.dryRun = !config.dryRun;
254
+ await saveConfig(config);
255
+ success(`Dry Run set to: ${config.dryRun ? 'Yes' : 'No'}`);
256
+ break;
257
+ case '5':
258
+ config.verbose = !config.verbose;
259
+ await saveConfig(config);
260
+ success(`Verbose set to: ${config.verbose ? 'Yes' : 'No'}`);
261
+ break;
262
+ case '6':
263
+ await manageWhitelist(config);
264
+ break;
265
+ case '7':
266
+ await manageBlacklist(config);
267
+ break;
268
+ case '8':
269
+ await listConfig();
270
+ break;
271
+ case '9':
272
+ const confirmed = await confirmAction('Reset configuration to defaults?', false);
273
+ if (confirmed) {
274
+ await saveConfig({ ...DEFAULT_CONFIG });
275
+ success('Configuration reset to defaults');
276
+ }
277
+ else {
278
+ warning('Reset cancelled');
279
+ }
280
+ break;
281
+ case '0':
282
+ shouldExit = true;
283
+ console.log();
284
+ success('Configuration saved and exiting');
285
+ break;
286
+ default:
287
+ error('Invalid option');
288
+ }
289
+ }
290
+ }
291
+ /**
292
+ * Configure monitor preset
293
+ */
294
+ async function configureMonitorPreset(config) {
295
+ console.log();
296
+ console.log(chalk.bold('Monitor Presets:'));
297
+ console.log(` ${chalk.cyan('1')} Classic Grid Layout (CPU, Memory, Disk, Network in grid)`);
298
+ console.log(` ${chalk.cyan('2')} Minimal Compact (Simple single-panel layout)`);
299
+ console.log(` ${chalk.cyan('3')} Detailed Information (Comprehensive system info)`);
300
+ console.log(` ${chalk.cyan('4')} Linux-style Dashboard (Like htop/top)`);
301
+ console.log(` ${chalk.cyan('5')} Modern Colorful Dashboard (Color-rich modern design)`);
302
+ console.log();
303
+ const choice = await inputPrompt('Select preset (1-5):');
304
+ if (!choice) {
305
+ return;
306
+ }
307
+ const preset = parseInt(choice);
308
+ if (preset >= 1 && preset <= 5) {
309
+ config.monitorPreset = preset;
310
+ await saveConfig(config);
311
+ success(`Monitor preset set to: ${preset}`);
312
+ }
313
+ else {
314
+ error('Invalid preset selection');
315
+ }
316
+ }
317
+ /**
318
+ * Configure safety level
319
+ */
320
+ async function configureSafetyLevel(config) {
321
+ console.log();
322
+ console.log(chalk.bold('Safety Levels:'));
323
+ console.log(` ${chalk.cyan('1')} Safe - Only remove very safe files`);
324
+ console.log(` ${chalk.cyan('2')} Moderate - Remove common temporary files (default)`);
325
+ console.log(` ${chalk.cyan('3')} Risky - Remove more aggressive including some system files`);
326
+ console.log();
327
+ const choice = await inputPrompt('Select safety level (1-3):');
328
+ switch (choice) {
329
+ case '1':
330
+ config.safetyLevel = 'safe';
331
+ await saveConfig(config);
332
+ success('Safety level set to: safe');
333
+ break;
334
+ case '2':
335
+ config.safetyLevel = 'moderate';
336
+ await saveConfig(config);
337
+ success('Safety level set to: moderate');
338
+ break;
339
+ case '3':
340
+ config.safetyLevel = 'risky';
341
+ await saveConfig(config);
342
+ success('Safety level set to: risky');
343
+ break;
344
+ default:
345
+ error('Invalid safety level selection');
346
+ }
347
+ }
348
+ /**
349
+ * Manage whitelist
350
+ */
351
+ async function manageWhitelist(config) {
352
+ let managing = true;
353
+ while (managing) {
354
+ console.log();
355
+ console.log(chalk.bold('Whitelist Management'));
356
+ if (config.whitelist.length === 0) {
357
+ console.log(chalk.dim('No paths in whitelist'));
358
+ }
359
+ else {
360
+ config.whitelist.forEach((path, i) => {
361
+ console.log(` ${chalk.cyan(`${i + 1}.`)} ${path}`);
362
+ });
363
+ }
364
+ console.log();
365
+ console.log(` ${chalk.cyan('1')} Add path`);
366
+ console.log(` ${chalk.cyan('2')} Remove path`);
367
+ console.log(` ${chalk.cyan('0')} Back`);
368
+ console.log();
369
+ const choice = await inputPrompt('Choose option (0-2):');
370
+ switch (choice) {
371
+ case '1':
372
+ const path = await inputPrompt('Enter path to add:');
373
+ if (path && !config.whitelist.includes(path)) {
374
+ config.whitelist.push(path);
375
+ await saveConfig(config);
376
+ success(`Added to whitelist: ${path}`);
377
+ }
378
+ break;
379
+ case '2':
380
+ if (config.whitelist.length > 0) {
381
+ const index = await inputPrompt('Enter index to remove:');
382
+ if (!index) {
383
+ break;
384
+ }
385
+ const idx = parseInt(index) - 1;
386
+ if (idx >= 0 && idx < config.whitelist.length) {
387
+ const removed = config.whitelist.splice(idx, 1)[0];
388
+ await saveConfig(config);
389
+ success(`Removed from whitelist: ${removed}`);
390
+ }
391
+ else {
392
+ error('Invalid index');
393
+ }
394
+ }
395
+ break;
396
+ case '0':
397
+ managing = false;
398
+ break;
399
+ default:
400
+ error('Invalid option');
401
+ }
402
+ }
403
+ }
404
+ /**
405
+ * Manage blacklist
406
+ */
407
+ async function manageBlacklist(config) {
408
+ let managing = true;
409
+ while (managing) {
410
+ console.log();
411
+ console.log(chalk.bold('Blacklist Management'));
412
+ if (config.blacklist.length === 0) {
413
+ console.log(chalk.dim('No paths in blacklist'));
414
+ }
415
+ else {
416
+ config.blacklist.forEach((path, i) => {
417
+ console.log(` ${chalk.cyan(`${i + 1}.`)} ${path}`);
418
+ });
419
+ }
420
+ console.log();
421
+ console.log(` ${chalk.cyan('1')} Add path`);
422
+ console.log(` ${chalk.cyan('2')} Remove path`);
423
+ console.log(` ${chalk.cyan('0')} Back`);
424
+ console.log();
425
+ const choice = await inputPrompt('Choose option (0-2):');
426
+ switch (choice) {
427
+ case '1':
428
+ const path = await inputPrompt('Enter path to add:');
429
+ if (path && !config.blacklist.includes(path)) {
430
+ config.blacklist.push(path);
431
+ await saveConfig(config);
432
+ success(`Added to blacklist: ${path}`);
433
+ }
434
+ break;
435
+ case '2':
436
+ if (config.blacklist.length > 0) {
437
+ const index = await inputPrompt('Enter index to remove:');
438
+ if (!index) {
439
+ break;
440
+ }
441
+ const idx = parseInt(index) - 1;
442
+ if (idx >= 0 && idx < config.blacklist.length) {
443
+ const removed = config.blacklist.splice(idx, 1)[0];
444
+ await saveConfig(config);
445
+ success(`Removed from blacklist: ${removed}`);
446
+ }
447
+ else {
448
+ error('Invalid index');
449
+ }
450
+ }
451
+ break;
452
+ case '0':
453
+ managing = false;
454
+ break;
455
+ default:
456
+ error('Invalid option');
457
+ }
458
+ }
459
+ }
460
+ /**
461
+ * Create config command
462
+ */
463
+ export function createConfigCommand() {
464
+ const cmd = new Command('config')
465
+ .description('Manage broom configuration (interactive or direct)')
466
+ .argument('[action]', 'Action to perform (interactive, whitelist-add, etc.)')
467
+ .argument('[value]', 'Value for the action')
468
+ .option('-l, --list', 'List current configuration')
469
+ .option('--reset', 'Reset configuration to defaults')
470
+ .action(async (action, value, options) => {
471
+ await configCommand(action, value, options);
472
+ });
473
+ return enhanceCommandHelp(cmd);
474
+ }