@reliverse/dler 2.0.0 → 2.0.2

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 (135) hide show
  1. package/dist/cli.d.ts +2 -0
  2. package/dist/cli.js +3 -0
  3. package/dist/cmds/build/cmd.d.ts +2 -0
  4. package/dist/cmds/build/cmd.js +564 -0
  5. package/dist/cmds/clean/cmd.d.ts +2 -0
  6. package/dist/cmds/clean/cmd.js +146 -0
  7. package/dist/cmds/clean/impl.d.ts +2 -0
  8. package/dist/cmds/clean/impl.js +627 -0
  9. package/dist/cmds/clean/presets.d.ts +10 -0
  10. package/dist/cmds/clean/presets.js +112 -0
  11. package/dist/cmds/clean/types.d.ts +62 -0
  12. package/dist/cmds/clean/types.js +0 -0
  13. package/dist/cmds/init/cmd.d.ts +3 -0
  14. package/dist/cmds/init/cmd.js +56 -0
  15. package/dist/cmds/init/impl/config.d.ts +45 -0
  16. package/dist/cmds/init/impl/config.js +99 -0
  17. package/dist/cmds/init/impl/generators.d.ts +6 -0
  18. package/dist/cmds/init/impl/generators.js +178 -0
  19. package/dist/cmds/init/impl/prompts.d.ts +2 -0
  20. package/dist/cmds/init/impl/prompts.js +98 -0
  21. package/dist/cmds/init/impl/types.d.ts +22 -0
  22. package/dist/cmds/init/impl/types.js +0 -0
  23. package/dist/cmds/init/impl/utils.d.ts +4 -0
  24. package/dist/cmds/init/impl/utils.js +11 -0
  25. package/dist/cmds/init/impl/validators.d.ts +4 -0
  26. package/dist/cmds/init/impl/validators.js +42 -0
  27. package/dist/cmds/integrate/cmd.d.ts +3 -0
  28. package/dist/cmds/integrate/cmd.js +70 -0
  29. package/dist/cmds/integrate/impl.d.ts +7 -0
  30. package/dist/cmds/integrate/impl.js +127 -0
  31. package/dist/cmds/integrate/integrations/base.d.ts +13 -0
  32. package/dist/cmds/integrate/integrations/base.js +41 -0
  33. package/dist/cmds/integrate/integrations/nextjs.d.ts +16 -0
  34. package/dist/cmds/integrate/integrations/nextjs.js +167 -0
  35. package/dist/cmds/integrate/integrations/registry.d.ts +7 -0
  36. package/dist/cmds/integrate/integrations/registry.js +31 -0
  37. package/dist/cmds/integrate/integrations/ultracite.d.ts +11 -0
  38. package/dist/cmds/integrate/integrations/ultracite.js +40 -0
  39. package/dist/cmds/integrate/types.d.ts +39 -0
  40. package/dist/cmds/integrate/types.js +0 -0
  41. package/dist/cmds/integrate/utils/biome.d.ts +4 -0
  42. package/dist/cmds/integrate/utils/biome.js +140 -0
  43. package/dist/cmds/integrate/utils/context.d.ts +3 -0
  44. package/dist/cmds/integrate/utils/context.js +111 -0
  45. package/dist/cmds/integrate/utils/temp.d.ts +3 -0
  46. package/dist/cmds/integrate/utils/temp.js +36 -0
  47. package/dist/cmds/perf/analysis/bundle.d.ts +20 -0
  48. package/dist/cmds/perf/analysis/bundle.js +225 -0
  49. package/dist/cmds/perf/analysis/filesystem.d.ts +27 -0
  50. package/dist/cmds/perf/analysis/filesystem.js +246 -0
  51. package/dist/cmds/perf/analysis/monorepo.d.ts +29 -0
  52. package/dist/cmds/perf/analysis/monorepo.js +307 -0
  53. package/dist/cmds/perf/benchmarks/command.d.ts +21 -0
  54. package/dist/cmds/perf/benchmarks/command.js +162 -0
  55. package/dist/cmds/perf/benchmarks/memory.d.ts +41 -0
  56. package/dist/cmds/perf/benchmarks/memory.js +169 -0
  57. package/dist/cmds/perf/benchmarks/runner.d.ts +22 -0
  58. package/dist/cmds/perf/benchmarks/runner.js +157 -0
  59. package/dist/cmds/perf/cmd.d.ts +2 -0
  60. package/dist/cmds/perf/cmd.js +238 -0
  61. package/dist/cmds/perf/impl.d.ts +24 -0
  62. package/dist/cmds/perf/impl.js +304 -0
  63. package/dist/cmds/perf/reporters/console.d.ts +12 -0
  64. package/dist/cmds/perf/reporters/console.js +257 -0
  65. package/dist/cmds/perf/reporters/html.d.ts +27 -0
  66. package/dist/cmds/perf/reporters/html.js +881 -0
  67. package/dist/cmds/perf/reporters/json.d.ts +9 -0
  68. package/dist/cmds/perf/reporters/json.js +32 -0
  69. package/dist/cmds/perf/types.d.ts +184 -0
  70. package/dist/cmds/perf/types.js +0 -0
  71. package/dist/cmds/perf/utils/cache.d.ts +23 -0
  72. package/dist/cmds/perf/utils/cache.js +171 -0
  73. package/dist/cmds/perf/utils/formatter.d.ts +17 -0
  74. package/dist/cmds/perf/utils/formatter.js +134 -0
  75. package/dist/cmds/perf/utils/stats.d.ts +15 -0
  76. package/dist/cmds/perf/utils/stats.js +101 -0
  77. package/dist/cmds/publish/cmd.d.ts +3 -0
  78. package/dist/cmds/publish/cmd.js +189 -0
  79. package/dist/cmds/shell/cmd.d.ts +3 -0
  80. package/dist/cmds/shell/cmd.js +50 -0
  81. package/dist/cmds/tsc/cache.d.ts +27 -0
  82. package/dist/cmds/tsc/cache.js +160 -0
  83. package/dist/cmds/tsc/cmd.d.ts +2 -0
  84. package/dist/cmds/tsc/cmd.js +111 -0
  85. package/dist/cmds/tsc/impl.d.ts +41 -0
  86. package/dist/cmds/tsc/impl.js +572 -0
  87. package/dist/cmds/tsc/types.d.ts +57 -0
  88. package/dist/cmds/tsc/types.js +0 -0
  89. package/package.json +4 -11
  90. package/src/cli.ts +8 -0
  91. package/src/cmds/build/cmd.ts +582 -0
  92. package/src/cmds/clean/cmd.ts +166 -0
  93. package/src/cmds/clean/impl.ts +900 -0
  94. package/src/cmds/clean/presets.ts +158 -0
  95. package/src/cmds/clean/types.ts +71 -0
  96. package/src/cmds/init/cmd.ts +68 -0
  97. package/src/cmds/init/impl/config.ts +105 -0
  98. package/src/cmds/init/impl/generators.ts +220 -0
  99. package/src/cmds/init/impl/prompts.ts +137 -0
  100. package/src/cmds/init/impl/types.ts +25 -0
  101. package/src/cmds/init/impl/utils.ts +17 -0
  102. package/src/cmds/init/impl/validators.ts +55 -0
  103. package/src/cmds/integrate/cmd.ts +82 -0
  104. package/src/cmds/integrate/impl.ts +204 -0
  105. package/src/cmds/integrate/integrations/base.ts +69 -0
  106. package/src/cmds/integrate/integrations/nextjs.ts +227 -0
  107. package/src/cmds/integrate/integrations/registry.ts +45 -0
  108. package/src/cmds/integrate/integrations/ultracite.ts +53 -0
  109. package/src/cmds/integrate/types.ts +48 -0
  110. package/src/cmds/integrate/utils/biome.ts +173 -0
  111. package/src/cmds/integrate/utils/context.ts +148 -0
  112. package/src/cmds/integrate/utils/temp.ts +47 -0
  113. package/src/cmds/perf/analysis/bundle.ts +311 -0
  114. package/src/cmds/perf/analysis/filesystem.ts +324 -0
  115. package/src/cmds/perf/analysis/monorepo.ts +439 -0
  116. package/src/cmds/perf/benchmarks/command.ts +230 -0
  117. package/src/cmds/perf/benchmarks/memory.ts +249 -0
  118. package/src/cmds/perf/benchmarks/runner.ts +220 -0
  119. package/src/cmds/perf/cmd.ts +285 -0
  120. package/src/cmds/perf/impl.ts +411 -0
  121. package/src/cmds/perf/reporters/console.ts +331 -0
  122. package/src/cmds/perf/reporters/html.ts +984 -0
  123. package/src/cmds/perf/reporters/json.ts +42 -0
  124. package/src/cmds/perf/types.ts +220 -0
  125. package/src/cmds/perf/utils/cache.ts +234 -0
  126. package/src/cmds/perf/utils/formatter.ts +190 -0
  127. package/src/cmds/perf/utils/stats.ts +153 -0
  128. package/src/cmds/publish/cmd.ts +215 -0
  129. package/src/cmds/shell/cmd.ts +61 -0
  130. package/src/cmds/tsc/cache.ts +237 -0
  131. package/src/cmds/tsc/cmd.ts +139 -0
  132. package/src/cmds/tsc/impl.ts +855 -0
  133. package/src/cmds/tsc/types.ts +66 -0
  134. package/tsconfig.json +9 -0
  135. package/cli.js +0 -1316
@@ -0,0 +1,627 @@
1
+ import { existsSync, rmSync, statSync } from "node:fs";
2
+ import { join, resolve } from "node:path";
3
+ import { logger } from "@reliverse/dler-logger";
4
+ import pMap from "@reliverse/dler-mapper";
5
+ import { createIgnoreFilter, normalizePatterns } from "@reliverse/dler-matcher";
6
+ import {
7
+ getWorkspacePatterns,
8
+ hasWorkspaces,
9
+ readPackageJSON
10
+ } from "@reliverse/dler-pkg-tsc";
11
+ import { confirmPrompt } from "@reliverse/dler-prompt";
12
+ import {
13
+ LOCK_FILE_PATTERNS,
14
+ mergePatterns,
15
+ parseCustomPatterns,
16
+ parsePresets,
17
+ validatePatterns
18
+ } from "./presets.js";
19
+ const DEFAULT_CONCURRENCY = 5;
20
+ const findMonorepoRoot = async (startDir, useCwd = false) => {
21
+ let currentDir = resolve(startDir ?? process.cwd());
22
+ if (useCwd) {
23
+ const pkgPath = join(currentDir, "package.json");
24
+ if (existsSync(pkgPath)) {
25
+ const pkg = await readPackageJSON(currentDir);
26
+ if (pkg && hasWorkspaces(pkg)) {
27
+ return currentDir;
28
+ }
29
+ }
30
+ return null;
31
+ }
32
+ while (currentDir !== "/") {
33
+ const pkgPath = join(currentDir, "package.json");
34
+ if (existsSync(pkgPath)) {
35
+ const pkg = await readPackageJSON(currentDir);
36
+ if (pkg && hasWorkspaces(pkg)) {
37
+ return currentDir;
38
+ }
39
+ }
40
+ const parentDir = resolve(currentDir, "..");
41
+ if (parentDir === currentDir) break;
42
+ currentDir = parentDir;
43
+ }
44
+ return null;
45
+ };
46
+ const resolvePackageInfo = async (packagePath, isRoot = false) => {
47
+ const pkgJsonPath = join(packagePath, "package.json");
48
+ if (!existsSync(pkgJsonPath)) {
49
+ return null;
50
+ }
51
+ try {
52
+ const pkg = await readPackageJSON(packagePath);
53
+ if (!pkg?.name) {
54
+ return null;
55
+ }
56
+ return {
57
+ name: pkg.name,
58
+ path: packagePath,
59
+ isRoot
60
+ };
61
+ } catch {
62
+ return null;
63
+ }
64
+ };
65
+ const getWorkspacePackages = async (cwd, useCwd = false) => {
66
+ const monorepoRoot = await findMonorepoRoot(cwd, useCwd);
67
+ if (!monorepoRoot) {
68
+ throw new Error(
69
+ "\u274C No monorepo found. Ensure package.json has 'workspaces' field."
70
+ );
71
+ }
72
+ const rootPkg = await readPackageJSON(monorepoRoot);
73
+ if (!rootPkg) {
74
+ throw new Error("\u274C Could not read root package.json");
75
+ }
76
+ const patterns = getWorkspacePatterns(rootPkg);
77
+ if (!patterns.length) {
78
+ throw new Error("\u274C No workspace patterns found in package.json");
79
+ }
80
+ const packages = [];
81
+ const seenPaths = /* @__PURE__ */ new Set();
82
+ for (const pattern of patterns) {
83
+ if (pattern.includes("*")) {
84
+ const glob = new Bun.Glob(pattern);
85
+ const matches = glob.scanSync({ cwd: monorepoRoot, onlyFiles: false });
86
+ for (const match of matches) {
87
+ const packagePath = resolve(monorepoRoot, match);
88
+ if (seenPaths.has(packagePath)) continue;
89
+ seenPaths.add(packagePath);
90
+ const pkgInfo = await resolvePackageInfo(packagePath, false);
91
+ if (pkgInfo) {
92
+ packages.push(pkgInfo);
93
+ }
94
+ }
95
+ } else {
96
+ const packagePath = resolve(monorepoRoot, pattern);
97
+ if (seenPaths.has(packagePath)) continue;
98
+ seenPaths.add(packagePath);
99
+ const pkgInfo = await resolvePackageInfo(packagePath, false);
100
+ if (pkgInfo) {
101
+ packages.push(pkgInfo);
102
+ }
103
+ }
104
+ }
105
+ return packages;
106
+ };
107
+ const getSingleRepoPackages = async (cwd) => {
108
+ const currentDir = resolve(cwd ?? process.cwd());
109
+ const pkgInfo = await resolvePackageInfo(currentDir, true);
110
+ if (!pkgInfo) {
111
+ throw new Error("\u274C No package.json found in current directory");
112
+ }
113
+ return [pkgInfo];
114
+ };
115
+ const calculateSize = (path) => {
116
+ try {
117
+ const stats = statSync(path);
118
+ if (stats.isDirectory()) {
119
+ return calculateDirectorySize(path);
120
+ }
121
+ return stats.size;
122
+ } catch {
123
+ return 0;
124
+ }
125
+ };
126
+ const calculateDirectorySize = (dirPath) => {
127
+ try {
128
+ let totalSize = 0;
129
+ const entries = existsSync(dirPath) && statSync(dirPath).isDirectory() ? Array.from(
130
+ new Bun.Glob("**/*").scanSync({ cwd: dirPath, onlyFiles: true })
131
+ ) : [];
132
+ for (const entry of entries) {
133
+ try {
134
+ const fullPath = join(dirPath, entry);
135
+ const stats = statSync(fullPath);
136
+ totalSize += stats.size;
137
+ } catch {
138
+ }
139
+ }
140
+ return totalSize;
141
+ } catch {
142
+ return 0;
143
+ }
144
+ };
145
+ const isAbsolutePath = (path) => path.startsWith("/") || path.length > 1 && path[1] === ":";
146
+ const findMatchingFiles = (targetDir, patterns, subdirs = false) => {
147
+ const matches = [];
148
+ const searchDirs = subdirs ? [targetDir] : [targetDir];
149
+ for (const pattern of patterns) {
150
+ if (isAbsolutePath(pattern)) {
151
+ if (existsSync(pattern)) {
152
+ const stats = statSync(pattern);
153
+ const size = calculateSize(pattern);
154
+ matches.push({
155
+ path: pattern,
156
+ size,
157
+ isDirectory: stats.isDirectory(),
158
+ category: getCategoryForPattern(pattern)
159
+ });
160
+ }
161
+ continue;
162
+ }
163
+ for (const searchDir of searchDirs) {
164
+ try {
165
+ const glob = new Bun.Glob(pattern);
166
+ const globMatches = glob.scanSync({
167
+ cwd: searchDir,
168
+ onlyFiles: false,
169
+ dot: true
170
+ // Include hidden files/directories
171
+ });
172
+ for (const match of globMatches) {
173
+ const fullPath = join(searchDir, match);
174
+ if (existsSync(fullPath)) {
175
+ const stats = statSync(fullPath);
176
+ const size = calculateSize(fullPath);
177
+ matches.push({
178
+ path: fullPath,
179
+ size,
180
+ isDirectory: stats.isDirectory(),
181
+ category: getCategoryForPattern(pattern)
182
+ });
183
+ }
184
+ }
185
+ } catch (error) {
186
+ if (process.env.DEBUG) {
187
+ console.warn(`Glob error for pattern ${pattern}:`, error);
188
+ }
189
+ }
190
+ }
191
+ }
192
+ return matches;
193
+ };
194
+ const getCategoryForPattern = (pattern) => {
195
+ if (pattern.includes("dist")) return "build";
196
+ if (pattern.includes("_generated")) return "db";
197
+ if (pattern.includes(".basehub")) return "cms";
198
+ if (pattern.includes(".next") || pattern.includes(".nuxt") || pattern.includes(".expo"))
199
+ return "frontend";
200
+ if (pattern.includes(".source")) return "docs";
201
+ if (pattern.includes(".react-email")) return "email";
202
+ if (pattern.includes(".turbo") || pattern.includes(".vercel") || pattern.includes(".wrangler"))
203
+ return "build-tools";
204
+ if (pattern.includes("node_modules")) return "deps";
205
+ return "other";
206
+ };
207
+ const deleteFile = (filePath) => {
208
+ try {
209
+ rmSync(filePath, { recursive: true, force: true });
210
+ return null;
211
+ } catch (error) {
212
+ return {
213
+ path: filePath,
214
+ error: error instanceof Error ? error.message : String(error)
215
+ };
216
+ }
217
+ };
218
+ const deleteFiles = async (files, dryRun = false) => {
219
+ if (dryRun) {
220
+ return {
221
+ deletedCount: files.length,
222
+ deletedSize: files.reduce((sum, file) => sum + file.size, 0),
223
+ errors: []
224
+ };
225
+ }
226
+ let deletedCount = 0;
227
+ let deletedSize = 0;
228
+ const errors = [];
229
+ for (const file of files) {
230
+ const error = deleteFile(file.path);
231
+ if (error) {
232
+ errors.push(error);
233
+ } else {
234
+ deletedCount++;
235
+ deletedSize += file.size;
236
+ }
237
+ }
238
+ return { deletedCount, deletedSize, errors };
239
+ };
240
+ const discoverPackageFiles = async (pkg, patterns, options) => {
241
+ const { subdirs = false, verbose = false } = options;
242
+ if (verbose) {
243
+ logger.info(`\u{1F50D} Scanning ${pkg.name}...`);
244
+ }
245
+ const files = findMatchingFiles(pkg.path, patterns, subdirs);
246
+ if (verbose && files.length > 0) {
247
+ logger.info(` Found ${files.length} files/directories to clean`);
248
+ }
249
+ return {
250
+ package: pkg,
251
+ files,
252
+ deletedCount: 0,
253
+ deletedSize: 0,
254
+ errors: []
255
+ };
256
+ };
257
+ const cleanPackage = async (pkg, patterns, options) => {
258
+ const { subdirs = false, dryRun = false, verbose = false } = options;
259
+ if (verbose) {
260
+ logger.info(`\u{1F50D} Scanning ${pkg.name}...`);
261
+ }
262
+ const files = findMatchingFiles(pkg.path, patterns, subdirs);
263
+ if (verbose && files.length > 0) {
264
+ logger.info(` Found ${files.length} files/directories to clean`);
265
+ }
266
+ const { deletedCount, deletedSize, errors } = await deleteFiles(
267
+ files,
268
+ dryRun
269
+ );
270
+ if (verbose) {
271
+ const status = errors.length === 0 ? "\u2705" : "\u26A0\uFE0F";
272
+ logger.log(
273
+ `${status} ${pkg.name}: ${deletedCount} deleted, ${errors.length} errors`
274
+ );
275
+ }
276
+ return {
277
+ package: pkg,
278
+ files,
279
+ deletedCount,
280
+ deletedSize,
281
+ errors
282
+ };
283
+ };
284
+ const cleanLockFiles = async (rootDir, deleteLockFiles, dryRun = false) => {
285
+ if (!deleteLockFiles) {
286
+ return { deletedCount: 0, deletedSize: 0, errors: [] };
287
+ }
288
+ const lockFiles = [];
289
+ for (const pattern of LOCK_FILE_PATTERNS) {
290
+ const fullPath = join(rootDir, pattern);
291
+ if (existsSync(fullPath)) {
292
+ const stats = statSync(fullPath);
293
+ lockFiles.push({
294
+ path: fullPath,
295
+ size: stats.size,
296
+ isDirectory: false,
297
+ category: "deps"
298
+ });
299
+ }
300
+ }
301
+ return deleteFiles(lockFiles, dryRun);
302
+ };
303
+ const formatBytes = (bytes) => {
304
+ if (bytes === 0) return "0 B";
305
+ const k = 1024;
306
+ const sizes = ["B", "KB", "MB", "GB"];
307
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
308
+ return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
309
+ };
310
+ const displayPreview = (results, lockFilesResult) => {
311
+ logger.log("\u2501".repeat(60));
312
+ logger.log("\u{1F9F9} Clean Preview:");
313
+ logger.log("\u2501".repeat(60));
314
+ let totalFiles = 0;
315
+ let totalSize = 0;
316
+ for (const result of results) {
317
+ if (result.files.length === 0) continue;
318
+ logger.log(
319
+ `
320
+ \u{1F4E6} ${result.package.name}${result.package.isRoot ? " (root)" : ""}:`
321
+ );
322
+ const byCategory = result.files.reduce(
323
+ (acc, file) => {
324
+ if (!acc[file.category]) acc[file.category] = [];
325
+ acc[file.category].push(file);
326
+ return acc;
327
+ },
328
+ {}
329
+ );
330
+ for (const [category, files] of Object.entries(byCategory)) {
331
+ const categorySize = files.reduce((sum, file) => sum + file.size, 0);
332
+ logger.log(
333
+ ` ${category}: ${files.length} files (${formatBytes(categorySize)})`
334
+ );
335
+ if (files.length <= 5) {
336
+ for (const file of files) {
337
+ const relativePath = file.path.replace(result.package.path + "/", "");
338
+ logger.log(` \u2022 ${relativePath}`);
339
+ }
340
+ } else {
341
+ logger.log(` \u2022 ... and ${files.length - 5} more files`);
342
+ }
343
+ }
344
+ totalFiles += result.files.length;
345
+ totalSize += result.files.reduce((sum, file) => sum + file.size, 0);
346
+ }
347
+ if (lockFilesResult.deletedCount > 0) {
348
+ logger.log(
349
+ `
350
+ \u{1F512} Lock files: ${lockFilesResult.deletedCount} files (${formatBytes(lockFilesResult.deletedSize)})`
351
+ );
352
+ totalFiles += lockFilesResult.deletedCount;
353
+ totalSize += lockFilesResult.deletedSize;
354
+ }
355
+ logger.log(`
356
+ \u{1F4CA} Total: ${totalFiles} files (${formatBytes(totalSize)})`);
357
+ logger.log("\u2501".repeat(60));
358
+ };
359
+ const askConfirmation = async (force) => {
360
+ if (force) {
361
+ return true;
362
+ }
363
+ try {
364
+ return await confirmPrompt("Proceed with deletion?", false);
365
+ } catch {
366
+ return false;
367
+ }
368
+ };
369
+ export const runCleanOnAllPackages = async (ignore, cwd, options = {}) => {
370
+ const {
371
+ presets: presetsString,
372
+ custom: customString,
373
+ dryRun = false,
374
+ force = false,
375
+ verbose = false,
376
+ deleteLockFiles = false
377
+ } = options;
378
+ const presets = parsePresets(presetsString);
379
+ const customPatterns = parseCustomPatterns(customString);
380
+ validatePatterns(presets, customPatterns);
381
+ const patterns = mergePatterns(presets, customPatterns);
382
+ const hasAbsolutePaths = customPatterns.some(
383
+ (pattern) => isAbsolutePath(pattern)
384
+ );
385
+ if (verbose) {
386
+ logger.info("\u{1F50D} Discovering files to clean...");
387
+ }
388
+ const result = await (async () => {
389
+ if (hasAbsolutePaths && presets.length === 0 && customPatterns.every((pattern) => isAbsolutePath(pattern))) {
390
+ if (verbose) {
391
+ logger.info(` Processing absolute paths directly`);
392
+ }
393
+ const files = [];
394
+ for (const pattern of patterns) {
395
+ if (isAbsolutePath(pattern) && existsSync(pattern)) {
396
+ const stats = statSync(pattern);
397
+ const size = calculateSize(pattern);
398
+ files.push({
399
+ path: pattern,
400
+ size,
401
+ isDirectory: stats.isDirectory(),
402
+ category: getCategoryForPattern(pattern)
403
+ });
404
+ }
405
+ }
406
+ displayPreview(
407
+ [
408
+ {
409
+ package: { name: "Absolute paths", path: "", isRoot: true },
410
+ files,
411
+ deletedCount: 0,
412
+ deletedSize: 0,
413
+ errors: []
414
+ }
415
+ ],
416
+ { deletedCount: 0, deletedSize: 0 }
417
+ );
418
+ if (!dryRun) {
419
+ const shouldProceed = await askConfirmation(force);
420
+ if (!shouldProceed) {
421
+ logger.info("\u274C Clean cancelled by user");
422
+ process.exit(0);
423
+ }
424
+ const { deletedCount, deletedSize: deletedSize2, errors } = await deleteFiles(
425
+ files,
426
+ dryRun
427
+ );
428
+ const summary2 = {
429
+ totalPackages: 1,
430
+ processedPackages: 1,
431
+ totalFiles: files.length,
432
+ totalSize: files.reduce((sum, file) => sum + file.size, 0),
433
+ deletedFiles: deletedCount,
434
+ deletedSize: deletedSize2,
435
+ errors,
436
+ hasErrors: errors.length > 0,
437
+ results: [
438
+ {
439
+ package: { name: "Absolute paths", path: "", isRoot: true },
440
+ files,
441
+ deletedCount,
442
+ deletedSize: deletedSize2,
443
+ errors
444
+ }
445
+ ]
446
+ };
447
+ logger.log("\n" + "\u2501".repeat(60));
448
+ logger.log("\u{1F4CA} Clean Summary:");
449
+ logger.log(
450
+ ` Files ${dryRun ? "would be" : ""} deleted: ${summary2.deletedFiles}`
451
+ );
452
+ logger.log(
453
+ ` Size ${dryRun ? "would be" : ""} freed: ${formatBytes(summary2.deletedSize)}`
454
+ );
455
+ if (summary2.hasErrors) {
456
+ logger.log(` Errors: ${summary2.errors.length}`);
457
+ logger.error("\n\u274C Errors occurred during cleanup:");
458
+ for (const error of summary2.errors) {
459
+ logger.error(` \u2022 ${error.path}: ${error.error}`);
460
+ }
461
+ }
462
+ logger.log("\u2501".repeat(60));
463
+ return summary2;
464
+ }
465
+ if (dryRun) {
466
+ const summary2 = {
467
+ totalPackages: 1,
468
+ processedPackages: 1,
469
+ totalFiles: files.length,
470
+ totalSize: files.reduce((sum, file) => sum + file.size, 0),
471
+ deletedFiles: files.length,
472
+ deletedSize: files.reduce((sum, file) => sum + file.size, 0),
473
+ errors: [],
474
+ hasErrors: false,
475
+ results: [
476
+ {
477
+ package: { name: "Absolute paths", path: "", isRoot: true },
478
+ files,
479
+ deletedCount: files.length,
480
+ deletedSize: files.reduce((sum, file) => sum + file.size, 0),
481
+ errors: []
482
+ }
483
+ ]
484
+ };
485
+ logger.log("\n" + "\u2501".repeat(60));
486
+ logger.log("\u{1F4CA} Clean Summary:");
487
+ logger.log(` Files would be deleted: ${summary2.deletedFiles}`);
488
+ logger.log(
489
+ ` Size would be freed: ${formatBytes(summary2.deletedSize)}`
490
+ );
491
+ logger.log("\u2501".repeat(60));
492
+ return summary2;
493
+ }
494
+ }
495
+ let packages;
496
+ let isMonorepo = false;
497
+ const useCwd = !!cwd;
498
+ try {
499
+ packages = await getWorkspacePackages(cwd, useCwd);
500
+ isMonorepo = true;
501
+ if (verbose) {
502
+ logger.info(` Found ${packages.length} packages in monorepo`);
503
+ }
504
+ } catch {
505
+ packages = await getSingleRepoPackages(cwd);
506
+ if (verbose) {
507
+ logger.info(` Single repo mode: ${packages[0]?.name}`);
508
+ }
509
+ }
510
+ if (isMonorepo && ignore) {
511
+ const ignoreFilter = createIgnoreFilter(ignore);
512
+ const filteredPackages = ignoreFilter(packages);
513
+ const ignoredCount = packages.length - filteredPackages.length;
514
+ if (ignoredCount > 0) {
515
+ const patterns2 = normalizePatterns(ignore);
516
+ logger.info(
517
+ ` Ignoring ${ignoredCount} packages matching: ${patterns2.join(", ")}`
518
+ );
519
+ }
520
+ packages = filteredPackages;
521
+ }
522
+ const results = await pMap(
523
+ packages,
524
+ async (pkg) => discoverPackageFiles(pkg, patterns, options),
525
+ {
526
+ concurrency: DEFAULT_CONCURRENCY,
527
+ stopOnError: false
528
+ }
529
+ );
530
+ const rootDir = cwd ?? process.cwd();
531
+ const lockFilesResult = await cleanLockFiles(
532
+ rootDir,
533
+ deleteLockFiles,
534
+ dryRun
535
+ );
536
+ displayPreview(results, lockFilesResult);
537
+ if (!dryRun) {
538
+ const shouldProceed = await askConfirmation(force);
539
+ if (!shouldProceed) {
540
+ logger.info("\u274C Clean cancelled by user");
541
+ process.exit(0);
542
+ }
543
+ const cleanedResults = await pMap(
544
+ packages,
545
+ async (pkg) => cleanPackage(pkg, patterns, options),
546
+ {
547
+ concurrency: DEFAULT_CONCURRENCY,
548
+ stopOnError: false
549
+ }
550
+ );
551
+ if (deleteLockFiles) {
552
+ await cleanLockFiles(rootDir, true, false);
553
+ }
554
+ const totalFiles2 = cleanedResults.reduce((sum, r) => sum + r.files.length, 0) + lockFilesResult.deletedCount;
555
+ const totalSize2 = cleanedResults.reduce(
556
+ (sum, r) => sum + r.files.reduce((s, f) => s + f.size, 0),
557
+ 0
558
+ ) + lockFilesResult.deletedSize;
559
+ const deletedFiles2 = cleanedResults.reduce((sum, r) => sum + r.deletedCount, 0) + lockFilesResult.deletedCount;
560
+ const deletedSize2 = cleanedResults.reduce((sum, r) => sum + r.deletedSize, 0) + lockFilesResult.deletedSize;
561
+ const allErrors2 = cleanedResults.flatMap((r) => r.errors);
562
+ const summary2 = {
563
+ totalPackages: packages.length,
564
+ processedPackages: cleanedResults.length,
565
+ totalFiles: totalFiles2,
566
+ totalSize: totalSize2,
567
+ deletedFiles: deletedFiles2,
568
+ deletedSize: deletedSize2,
569
+ errors: allErrors2,
570
+ hasErrors: allErrors2.length > 0,
571
+ results: cleanedResults
572
+ };
573
+ logger.log("\n" + "\u2501".repeat(60));
574
+ logger.log("\u{1F4CA} Clean Summary:");
575
+ logger.log(` Packages processed: ${summary2.processedPackages}`);
576
+ logger.log(
577
+ ` Files ${dryRun ? "would be" : ""} deleted: ${summary2.deletedFiles}`
578
+ );
579
+ logger.log(
580
+ ` Size ${dryRun ? "would be" : ""} freed: ${formatBytes(summary2.deletedSize)}`
581
+ );
582
+ if (summary2.hasErrors) {
583
+ logger.log(` Errors: ${summary2.errors.length}`);
584
+ logger.error("\n\u274C Errors occurred during cleanup:");
585
+ for (const error of summary2.errors) {
586
+ logger.error(` \u2022 ${error.path}: ${error.error}`);
587
+ }
588
+ }
589
+ logger.log("\u2501".repeat(60));
590
+ return summary2;
591
+ }
592
+ const totalFiles = results.reduce((sum, r) => sum + r.files.length, 0) + lockFilesResult.deletedCount;
593
+ const totalSize = results.reduce(
594
+ (sum, r) => sum + r.files.reduce((s, f) => s + f.size, 0),
595
+ 0
596
+ ) + lockFilesResult.deletedSize;
597
+ const deletedFiles = results.reduce((sum, r) => sum + r.deletedCount, 0) + lockFilesResult.deletedCount;
598
+ const deletedSize = results.reduce((sum, r) => sum + r.deletedSize, 0) + lockFilesResult.deletedSize;
599
+ const allErrors = results.flatMap((r) => r.errors);
600
+ const summary = {
601
+ totalPackages: packages.length,
602
+ processedPackages: results.length,
603
+ totalFiles,
604
+ totalSize,
605
+ deletedFiles,
606
+ deletedSize,
607
+ errors: allErrors,
608
+ hasErrors: allErrors.length > 0,
609
+ results
610
+ };
611
+ logger.log("\n" + "\u2501".repeat(60));
612
+ logger.log("\u{1F4CA} Clean Summary:");
613
+ logger.log(` Packages processed: ${summary.processedPackages}`);
614
+ logger.log(` Files would be deleted: ${summary.deletedFiles}`);
615
+ logger.log(` Size would be freed: ${formatBytes(summary.deletedSize)}`);
616
+ if (summary.hasErrors) {
617
+ logger.log(` Errors: ${summary.errors.length}`);
618
+ logger.error("\n\u274C Errors occurred during cleanup:");
619
+ for (const error of summary.errors) {
620
+ logger.error(` \u2022 ${error.path}: ${error.error}`);
621
+ }
622
+ }
623
+ logger.log("\u2501".repeat(60));
624
+ return summary;
625
+ })();
626
+ return result;
627
+ };
@@ -0,0 +1,10 @@
1
+ import type { PresetCategory } from "./types.js";
2
+ export declare const PRESET_CATEGORIES: Record<string, PresetCategory>;
3
+ export declare const LOCK_FILE_PATTERNS: string[];
4
+ export declare const parsePresets: (presetsString?: string) => string[];
5
+ export declare const parseCustomPatterns: (customString?: string) => string[];
6
+ export declare const getPresetPatterns: (presets: string[]) => string[];
7
+ export declare const getPresetOrder: (presets: string[]) => number[];
8
+ export declare const getPresetDescription: (presets: string[]) => string;
9
+ export declare const mergePatterns: (presets: string[], customPatterns: string[]) => string[];
10
+ export declare const validatePatterns: (presets: string[], customPatterns: string[]) => void;