node-janitor 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 (54) hide show
  1. package/README.md +259 -0
  2. package/dist/cli.d.ts +3 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +337 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/core/cleaner.d.ts +10 -0
  7. package/dist/core/cleaner.d.ts.map +1 -0
  8. package/dist/core/cleaner.js +107 -0
  9. package/dist/core/cleaner.js.map +1 -0
  10. package/dist/core/deep-cleaner.d.ts +10 -0
  11. package/dist/core/deep-cleaner.d.ts.map +1 -0
  12. package/dist/core/deep-cleaner.js +228 -0
  13. package/dist/core/deep-cleaner.js.map +1 -0
  14. package/dist/core/scanner.d.ts +35 -0
  15. package/dist/core/scanner.d.ts.map +1 -0
  16. package/dist/core/scanner.js +172 -0
  17. package/dist/core/scanner.js.map +1 -0
  18. package/dist/index.d.ts +3 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +5 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/types/index.d.ts +183 -0
  23. package/dist/types/index.d.ts.map +1 -0
  24. package/dist/types/index.js +5 -0
  25. package/dist/types/index.js.map +1 -0
  26. package/dist/ui/progress.d.ts +20 -0
  27. package/dist/ui/progress.d.ts.map +1 -0
  28. package/dist/ui/progress.js +29 -0
  29. package/dist/ui/progress.js.map +1 -0
  30. package/dist/ui/prompts.d.ts +40 -0
  31. package/dist/ui/prompts.d.ts.map +1 -0
  32. package/dist/ui/prompts.js +106 -0
  33. package/dist/ui/prompts.js.map +1 -0
  34. package/dist/ui/spinner.d.ts +15 -0
  35. package/dist/ui/spinner.d.ts.map +1 -0
  36. package/dist/ui/spinner.js +30 -0
  37. package/dist/ui/spinner.js.map +1 -0
  38. package/dist/ui/table.d.ts +38 -0
  39. package/dist/ui/table.d.ts.map +1 -0
  40. package/dist/ui/table.js +117 -0
  41. package/dist/ui/table.js.map +1 -0
  42. package/dist/utils/formatter.d.ts +40 -0
  43. package/dist/utils/formatter.d.ts.map +1 -0
  44. package/dist/utils/formatter.js +103 -0
  45. package/dist/utils/formatter.js.map +1 -0
  46. package/dist/utils/fs-utils.d.ts +53 -0
  47. package/dist/utils/fs-utils.d.ts.map +1 -0
  48. package/dist/utils/fs-utils.js +155 -0
  49. package/dist/utils/fs-utils.js.map +1 -0
  50. package/dist/utils/logger.d.ts +26 -0
  51. package/dist/utils/logger.d.ts.map +1 -0
  52. package/dist/utils/logger.js +77 -0
  53. package/dist/utils/logger.js.map +1 -0
  54. package/package.json +72 -0
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Format bytes to human readable string
3
+ */
4
+ export declare function formatBytes(bytes: number): string;
5
+ /**
6
+ * Parse size string to bytes (e.g., "500MB" -> 524288000)
7
+ */
8
+ export declare function parseSize(sizeStr: string): number;
9
+ /**
10
+ * Parse duration string to days (e.g., "30d" -> 30, "3m" -> 90, "1y" -> 365)
11
+ */
12
+ export declare function parseDuration(durationStr: string): number;
13
+ /**
14
+ * Parse duration range (e.g., "30d-90d" -> { min: 30, max: 90 })
15
+ */
16
+ export declare function parseDurationRange(rangeStr: string): {
17
+ min: number;
18
+ max: number;
19
+ };
20
+ /**
21
+ * Format date relative to now
22
+ */
23
+ export declare function formatRelativeTime(date: Date): string;
24
+ /**
25
+ * Format date as string
26
+ */
27
+ export declare function formatDate(date: Date): string;
28
+ /**
29
+ * Get age in days from a date
30
+ */
31
+ export declare function getAgeDays(date: Date): number;
32
+ /**
33
+ * Format duration in human readable format
34
+ */
35
+ export declare function formatDuration(ms: number): string;
36
+ /**
37
+ * Format number with commas
38
+ */
39
+ export declare function formatNumber(num: number): string;
40
+ //# sourceMappingURL=formatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../../src/utils/formatter.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQjD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAkBjD;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAiBzD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAUjF;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAErD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAE7C;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAI7C;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAKjD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD"}
@@ -0,0 +1,103 @@
1
+ import dayjs from 'dayjs';
2
+ import relativeTime from 'dayjs/plugin/relativeTime.js';
3
+ dayjs.extend(relativeTime);
4
+ /**
5
+ * Format bytes to human readable string
6
+ */
7
+ export function formatBytes(bytes) {
8
+ if (bytes === 0)
9
+ return '0 B';
10
+ const k = 1024;
11
+ const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
12
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
13
+ return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
14
+ }
15
+ /**
16
+ * Parse size string to bytes (e.g., "500MB" -> 524288000)
17
+ */
18
+ export function parseSize(sizeStr) {
19
+ const match = sizeStr.match(/^(\d+(?:\.\d+)?)\s*(B|KB|MB|GB|TB)?$/i);
20
+ if (!match) {
21
+ throw new Error(`Invalid size format: ${sizeStr}`);
22
+ }
23
+ const value = parseFloat(match[1]);
24
+ const unit = (match[2] || 'B').toUpperCase();
25
+ const multipliers = {
26
+ 'B': 1,
27
+ 'KB': 1024,
28
+ 'MB': 1024 ** 2,
29
+ 'GB': 1024 ** 3,
30
+ 'TB': 1024 ** 4,
31
+ };
32
+ return Math.floor(value * multipliers[unit]);
33
+ }
34
+ /**
35
+ * Parse duration string to days (e.g., "30d" -> 30, "3m" -> 90, "1y" -> 365)
36
+ */
37
+ export function parseDuration(durationStr) {
38
+ const match = durationStr.match(/^(\d+)(d|w|m|y)$/i);
39
+ if (!match) {
40
+ throw new Error(`Invalid duration format: ${durationStr}. Use format like 30d, 4w, 3m, 1y`);
41
+ }
42
+ const value = parseInt(match[1], 10);
43
+ const unit = match[2].toLowerCase();
44
+ const multipliers = {
45
+ 'd': 1,
46
+ 'w': 7,
47
+ 'm': 30,
48
+ 'y': 365,
49
+ };
50
+ return value * multipliers[unit];
51
+ }
52
+ /**
53
+ * Parse duration range (e.g., "30d-90d" -> { min: 30, max: 90 })
54
+ */
55
+ export function parseDurationRange(rangeStr) {
56
+ const parts = rangeStr.split('-');
57
+ if (parts.length !== 2) {
58
+ throw new Error(`Invalid range format: ${rangeStr}. Use format like 30d-90d`);
59
+ }
60
+ return {
61
+ min: parseDuration(parts[0]),
62
+ max: parseDuration(parts[1]),
63
+ };
64
+ }
65
+ /**
66
+ * Format date relative to now
67
+ */
68
+ export function formatRelativeTime(date) {
69
+ return dayjs(date).fromNow();
70
+ }
71
+ /**
72
+ * Format date as string
73
+ */
74
+ export function formatDate(date) {
75
+ return dayjs(date).format('YYYY-MM-DD HH:mm');
76
+ }
77
+ /**
78
+ * Get age in days from a date
79
+ */
80
+ export function getAgeDays(date) {
81
+ const now = dayjs();
82
+ const target = dayjs(date);
83
+ return now.diff(target, 'day');
84
+ }
85
+ /**
86
+ * Format duration in human readable format
87
+ */
88
+ export function formatDuration(ms) {
89
+ if (ms < 1000)
90
+ return `${ms}ms`;
91
+ if (ms < 60000)
92
+ return `${(ms / 1000).toFixed(1)}s`;
93
+ if (ms < 3600000)
94
+ return `${(ms / 60000).toFixed(1)}m`;
95
+ return `${(ms / 3600000).toFixed(1)}h`;
96
+ }
97
+ /**
98
+ * Format number with commas
99
+ */
100
+ export function formatNumber(num) {
101
+ return num.toLocaleString();
102
+ }
103
+ //# sourceMappingURL=formatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter.js","sourceRoot":"","sources":["../../src/utils/formatter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Get folder size recursively
3
+ */
4
+ export declare function getFolderSize(folderPath: string): Promise<number>;
5
+ /**
6
+ * Get folder size using native commands (faster)
7
+ */
8
+ export declare function getFolderSizeFast(folderPath: string): Promise<number>;
9
+ /**
10
+ * Get last modified time of a folder (based on node_modules folder itself)
11
+ */
12
+ export declare function getLastModified(folderPath: string): Promise<Date>;
13
+ /**
14
+ * Count items in a folder (top-level only)
15
+ */
16
+ export declare function countPackages(nodeModulesPath: string): Promise<number>;
17
+ /**
18
+ * Check if file exists
19
+ */
20
+ export declare function fileExists(filePath: string): Promise<boolean>;
21
+ /**
22
+ * Delete folder using native commands (faster)
23
+ */
24
+ export declare function deleteFolderFast(folderPath: string): Promise<void>;
25
+ /**
26
+ * Delete folder using fs-extra (safer, cross-platform)
27
+ */
28
+ export declare function deleteFolder(folderPath: string): Promise<void>;
29
+ /**
30
+ * Ensure directory exists
31
+ */
32
+ export declare function ensureDir(dirPath: string): Promise<void>;
33
+ /**
34
+ * Read JSON file
35
+ */
36
+ export declare function readJson<T>(filePath: string): Promise<T>;
37
+ /**
38
+ * Write JSON file
39
+ */
40
+ export declare function writeJson(filePath: string, data: unknown): Promise<void>;
41
+ /**
42
+ * Get home directory path
43
+ */
44
+ export declare function getHomeDir(): string;
45
+ /**
46
+ * Get node-janitor data directory
47
+ */
48
+ export declare function getDataDir(): string;
49
+ /**
50
+ * Get backups directory
51
+ */
52
+ export declare function getBackupsDir(): string;
53
+ //# sourceMappingURL=fs-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-utils.d.ts","sourceRoot":"","sources":["../../src/utils/fs-utils.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,wBAAsB,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAqBvE;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAmB3E;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOvE;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAoB5E;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOnE;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMxE;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEpE;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9D;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAE9D;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9E;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC"}
@@ -0,0 +1,155 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'path';
3
+ import { exec } from 'child_process';
4
+ import { promisify } from 'util';
5
+ const execAsync = promisify(exec);
6
+ /**
7
+ * Get folder size recursively
8
+ */
9
+ export async function getFolderSize(folderPath) {
10
+ let totalSize = 0;
11
+ try {
12
+ const items = await fs.readdir(folderPath);
13
+ for (const item of items) {
14
+ const itemPath = path.join(folderPath, item);
15
+ const stats = await fs.stat(itemPath);
16
+ if (stats.isDirectory()) {
17
+ totalSize += await getFolderSize(itemPath);
18
+ }
19
+ else {
20
+ totalSize += stats.size;
21
+ }
22
+ }
23
+ }
24
+ catch {
25
+ // Ignore permission errors
26
+ }
27
+ return totalSize;
28
+ }
29
+ /**
30
+ * Get folder size using native commands (faster)
31
+ */
32
+ export async function getFolderSizeFast(folderPath) {
33
+ try {
34
+ if (process.platform === 'win32') {
35
+ // Windows: Use PowerShell
36
+ const { stdout } = await execAsync(`powershell -command "(Get-ChildItem -Recurse '${folderPath}' | Measure-Object -Property Length -Sum).Sum"`, { timeout: 30000 });
37
+ return parseInt(stdout.trim(), 10) || 0;
38
+ }
39
+ else {
40
+ // Unix: Use du
41
+ const { stdout } = await execAsync(`du -sk "${folderPath}"`, { timeout: 30000 });
42
+ const sizeKb = parseInt(stdout.split('\t')[0], 10);
43
+ return sizeKb * 1024;
44
+ }
45
+ }
46
+ catch {
47
+ // Fallback to recursive method
48
+ return getFolderSize(folderPath);
49
+ }
50
+ }
51
+ /**
52
+ * Get last modified time of a folder (based on node_modules folder itself)
53
+ */
54
+ export async function getLastModified(folderPath) {
55
+ try {
56
+ const stats = await fs.stat(folderPath);
57
+ return stats.mtime;
58
+ }
59
+ catch {
60
+ return new Date();
61
+ }
62
+ }
63
+ /**
64
+ * Count items in a folder (top-level only)
65
+ */
66
+ export async function countPackages(nodeModulesPath) {
67
+ try {
68
+ const items = await fs.readdir(nodeModulesPath);
69
+ // Filter out hidden files and scoped packages
70
+ let count = 0;
71
+ for (const item of items) {
72
+ if (item.startsWith('.'))
73
+ continue;
74
+ if (item.startsWith('@')) {
75
+ // Scoped package - count subpackages
76
+ const scopePath = path.join(nodeModulesPath, item);
77
+ const scopeItems = await fs.readdir(scopePath);
78
+ count += scopeItems.filter(i => !i.startsWith('.')).length;
79
+ }
80
+ else {
81
+ count++;
82
+ }
83
+ }
84
+ return count;
85
+ }
86
+ catch {
87
+ return 0;
88
+ }
89
+ }
90
+ /**
91
+ * Check if file exists
92
+ */
93
+ export async function fileExists(filePath) {
94
+ try {
95
+ await fs.access(filePath);
96
+ return true;
97
+ }
98
+ catch {
99
+ return false;
100
+ }
101
+ }
102
+ /**
103
+ * Delete folder using native commands (faster)
104
+ */
105
+ export async function deleteFolderFast(folderPath) {
106
+ if (process.platform === 'win32') {
107
+ await execAsync(`rd /s /q "${folderPath}"`, { timeout: 60000 });
108
+ }
109
+ else {
110
+ await execAsync(`rm -rf "${folderPath}"`, { timeout: 60000 });
111
+ }
112
+ }
113
+ /**
114
+ * Delete folder using fs-extra (safer, cross-platform)
115
+ */
116
+ export async function deleteFolder(folderPath) {
117
+ await fs.remove(folderPath);
118
+ }
119
+ /**
120
+ * Ensure directory exists
121
+ */
122
+ export async function ensureDir(dirPath) {
123
+ await fs.ensureDir(dirPath);
124
+ }
125
+ /**
126
+ * Read JSON file
127
+ */
128
+ export async function readJson(filePath) {
129
+ return fs.readJson(filePath);
130
+ }
131
+ /**
132
+ * Write JSON file
133
+ */
134
+ export async function writeJson(filePath, data) {
135
+ await fs.writeJson(filePath, data, { spaces: 2 });
136
+ }
137
+ /**
138
+ * Get home directory path
139
+ */
140
+ export function getHomeDir() {
141
+ return process.env.HOME || process.env.USERPROFILE || '~';
142
+ }
143
+ /**
144
+ * Get node-janitor data directory
145
+ */
146
+ export function getDataDir() {
147
+ return path.join(getHomeDir(), '.node-janitor');
148
+ }
149
+ /**
150
+ * Get backups directory
151
+ */
152
+ export function getBackupsDir() {
153
+ return path.join(getDataDir(), 'backups');
154
+ }
155
+ //# sourceMappingURL=fs-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-utils.js","sourceRoot":"","sources":["../../src/utils/fs-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'success';
2
+ interface LoggerOptions {
3
+ verbose?: boolean;
4
+ debug?: boolean;
5
+ silent?: boolean;
6
+ }
7
+ declare class Logger {
8
+ private options;
9
+ configure(options: LoggerOptions): void;
10
+ private shouldLog;
11
+ debug(message: string, ...args: unknown[]): void;
12
+ info(message: string, ...args: unknown[]): void;
13
+ success(message: string, ...args: unknown[]): void;
14
+ warn(message: string, ...args: unknown[]): void;
15
+ error(message: string, ...args: unknown[]): void;
16
+ title(message: string): void;
17
+ divider(): void;
18
+ blank(): void;
19
+ path(p: string): string;
20
+ size(s: string): string;
21
+ count(n: number): string;
22
+ age(days: number): string;
23
+ }
24
+ export declare const logger: Logger;
25
+ export default logger;
26
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;AAEvE,UAAU,aAAa;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,cAAM,MAAM;IACR,OAAO,CAAC,OAAO,CAAqB;IAEpC,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI;IAIvC,OAAO,CAAC,SAAS;IAMjB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAKhD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAK/C,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAKlD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAK/C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAMhD,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAO5B,OAAO,IAAI,IAAI;IAKf,KAAK,IAAI,IAAI;IAMb,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAIvB,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAIvB,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM;IAIxB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CAK5B;AAED,eAAO,MAAM,MAAM,QAAe,CAAC;AACnC,eAAe,MAAM,CAAC"}
@@ -0,0 +1,77 @@
1
+ import chalk from 'chalk';
2
+ class Logger {
3
+ options = {};
4
+ configure(options) {
5
+ this.options = { ...this.options, ...options };
6
+ }
7
+ shouldLog(level) {
8
+ if (this.options.silent)
9
+ return false;
10
+ if (level === 'debug' && !this.options.debug)
11
+ return false;
12
+ return true;
13
+ }
14
+ debug(message, ...args) {
15
+ if (!this.shouldLog('debug'))
16
+ return;
17
+ console.log(chalk.gray(`[DEBUG] ${message}`), ...args);
18
+ }
19
+ info(message, ...args) {
20
+ if (!this.shouldLog('info'))
21
+ return;
22
+ console.log(chalk.blue('ℹ'), message, ...args);
23
+ }
24
+ success(message, ...args) {
25
+ if (!this.shouldLog('success'))
26
+ return;
27
+ console.log(chalk.green('✅'), message, ...args);
28
+ }
29
+ warn(message, ...args) {
30
+ if (!this.shouldLog('warn'))
31
+ return;
32
+ console.log(chalk.yellow('⚠️'), message, ...args);
33
+ }
34
+ error(message, ...args) {
35
+ if (!this.shouldLog('error'))
36
+ return;
37
+ console.error(chalk.red('❌'), message, ...args);
38
+ }
39
+ // Special formatting methods
40
+ title(message) {
41
+ if (this.options.silent)
42
+ return;
43
+ console.log();
44
+ console.log(chalk.bold.cyan(`🧹 ${message}`));
45
+ console.log(chalk.gray('─'.repeat(50)));
46
+ }
47
+ divider() {
48
+ if (this.options.silent)
49
+ return;
50
+ console.log(chalk.gray('─'.repeat(50)));
51
+ }
52
+ blank() {
53
+ if (this.options.silent)
54
+ return;
55
+ console.log();
56
+ }
57
+ // Colored text helpers
58
+ path(p) {
59
+ return chalk.cyan(p);
60
+ }
61
+ size(s) {
62
+ return chalk.yellow(s);
63
+ }
64
+ count(n) {
65
+ return chalk.magenta(n.toString());
66
+ }
67
+ age(days) {
68
+ if (days < 30)
69
+ return chalk.green(`${days}d`);
70
+ if (days < 90)
71
+ return chalk.yellow(`${days}d`);
72
+ return chalk.red(`${days}d`);
73
+ }
74
+ }
75
+ export const logger = new Logger();
76
+ export default logger;
77
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "node-janitor",
3
+ "version": "1.0.0",
4
+ "description": "🧹 Smart CLI tool to clean up node_modules folders - free up disk space automatically",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "node-janitor": "dist/index.js",
8
+ "nj": "dist/index.js"
9
+ },
10
+ "type": "module",
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "dev": "tsc --watch",
14
+ "start": "node dist/index.js",
15
+ "test": "vitest",
16
+ "test:coverage": "vitest --coverage",
17
+ "lint": "eslint src --ext .ts",
18
+ "lint:fix": "eslint src --ext .ts --fix",
19
+ "format": "prettier --write \"src/**/*.ts\"",
20
+ "prepublishOnly": "npm run build"
21
+ },
22
+ "keywords": [
23
+ "node_modules",
24
+ "cleanup",
25
+ "disk-space",
26
+ "cli",
27
+ "npm",
28
+ "yarn",
29
+ "pnpm",
30
+ "janitor",
31
+ "cleaner",
32
+ "devtools"
33
+ ],
34
+ "author": "Patchy Bean",
35
+ "license": "MIT",
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "git+https://github.com/patchybean/node-janitor.git"
39
+ },
40
+ "homepage": "https://github.com/patchybean/node-janitor#readme",
41
+ "bugs": {
42
+ "url": "https://github.com/patchybean/node-janitor/issues"
43
+ },
44
+ "engines": {
45
+ "node": ">=18.0.0"
46
+ },
47
+ "files": [
48
+ "dist",
49
+ "README.md"
50
+ ],
51
+ "dependencies": {
52
+ "chalk": "^5.3.0",
53
+ "cli-progress": "^3.12.0",
54
+ "cli-table3": "^0.6.5",
55
+ "commander": "^12.1.0",
56
+ "cosmiconfig": "^9.0.0",
57
+ "dayjs": "^1.11.13",
58
+ "fs-extra": "^11.2.0",
59
+ "glob": "^11.0.0",
60
+ "inquirer": "^12.2.0",
61
+ "ora": "^8.1.1",
62
+ "p-limit": "^6.1.0"
63
+ },
64
+ "devDependencies": {
65
+ "@types/cli-progress": "^3.11.6",
66
+ "@types/fs-extra": "^11.0.4",
67
+ "@types/inquirer": "^9.0.7",
68
+ "@types/node": "^22.10.2",
69
+ "typescript": "^5.7.2",
70
+ "vitest": "^2.1.8"
71
+ }
72
+ }