Skip to content

Commit 86ab339

Browse files
committed
feat: add experimental mode for extended file pruning
- Introduce `--experimental-default-files` option for aggressive pruning. - Update CLI help and README with experimental usage examples. - Modify `Pruner` class to handle experimental file lists. - Enhance tests to cover experimental mode functionality.
1 parent ca06657 commit 86ab339

File tree

6 files changed

+379
-12
lines changed

6 files changed

+379
-12
lines changed

README.md

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ Options:
104104
-w, --workspace Enable workspace/monorepo mode
105105
--workspace-root <dir> Specify workspace root (auto-detected if not provided)
106106
--no-root Skip pruning root node_modules in workspace mode
107+
--experimental-default-files Enable experimental extended file list for more aggressive pruning
107108
-h, --help Show help
108109
109110
Examples:
@@ -116,6 +117,10 @@ Workspace Examples:
116117
prune-mod --workspace # Auto-detect and prune all packages
117118
prune-mod -w --no-root # Prune only package node_modules
118119
prune-mod -w --workspace-root /monorepo # Specify workspace root
120+
121+
Experimental Examples:
122+
prune-mod --experimental-default-files # Use extended file list
123+
prune-mod -w --experimental-default-files # Combine with workspace mode
119124
```
120125

121126
### Real-world examples
@@ -193,6 +198,30 @@ prune-mod safely removes these types of files:
193198
- Binary executables
194199
- Critical system files
195200

201+
### Experimental Extended File List
202+
203+
For even more aggressive space savings, prune-mod offers an experimental mode that removes additional safe files:
204+
205+
```bash
206+
# Enable experimental extended file list
207+
prune-mod --experimental-default-files
208+
209+
# Use with other options
210+
prune-mod --experimental-default-files --workspace --verbose
211+
```
212+
213+
**Experimental mode adds 140+ additional file patterns** including:
214+
- Extended documentation files (CHANGELOG.md, CODE_OF_CONDUCT.md, SECURITY.md)
215+
- Advanced configuration files (webpack.config.*, rollup.config.*, vite.config.*)
216+
- Git and version control files (.gitignore, .gitkeep, .dockerignore)
217+
- CI/CD configurations (azure-pipelines.yml, .drone.yml, buildkite.yml)
218+
- Code quality tools (.codeclimate.yml, codecov.yml, sonar-project.properties)
219+
- Build outputs and caches (dist/, build/, .cache/, .next/, .nuxt/)
220+
- Source maps and minified files (*.map, *.min.js, *.min.css)
221+
- Environment and runtime files (.env.example, .nvmrc, .python-version)
222+
223+
**Safety note:** Experimental mode is thoroughly tested but more aggressive. Always test with `--dry-run` first to ensure it meets your needs.
224+
196225
## Programming API
197226

198227
Use prune-mod in your Node.js applications:
@@ -205,7 +234,10 @@ const pruner = new Pruner({
205234
verbose: true,
206235
dryRun: false,
207236
exceptions: ['*.config.*'], // Files to keep
208-
globs: ['**/*.tmp'] // Files to remove
237+
globs: ['**/*.tmp'], // Files to remove
238+
experimental: {
239+
defaultFiles: true // Enable extended file list
240+
}
209241
});
210242

211243
const stats = await pruner.prune();
@@ -254,6 +286,11 @@ interface PrunerOptions {
254286
workspace?: boolean; // Enable workspace mode (default: false)
255287
workspaceRoot?: string; // Custom workspace root (auto-detected if not set)
256288
includeRoot?: boolean; // Include root node_modules (default: true)
289+
290+
// Experimental options
291+
experimental?: {
292+
defaultFiles?: boolean; // Enable extended file list (default: false)
293+
};
257294
}
258295
```
259296

src/cli.ts

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ const { values, positionals } = parseArgs({
5151
default: false,
5252
description: "Skip pruning the root node_modules in workspace mode",
5353
},
54+
"experimental-default-files": {
55+
type: "boolean",
56+
default: false,
57+
description: "Enable experimental extended file list for more aggressive pruning",
58+
},
5459
},
5560
strict: false,
5661
allowPositionals: true,
@@ -64,14 +69,15 @@ Usage:
6469
prune-mod [options] [directory]
6570
6671
Options:
67-
-v, --verbose Verbose log output
68-
--exclude <glob> Glob of files that should not be pruned (can be specified multiple times)
69-
--include <glob> Globs of files that should always be pruned (can be specified multiple times)
70-
-d, --dry-run Show what would be pruned without actually removing files
71-
-w, --workspace Enable workspace/monorepo mode to prune all packages
72-
--workspace-root <dir> Specify the workspace root directory (auto-detected if not provided)
73-
--no-root Skip pruning the root node_modules in workspace mode
74-
-h, --help Show help
72+
-v, --verbose Verbose log output
73+
--exclude <glob> Glob of files that should not be pruned (can be specified multiple times)
74+
--include <glob> Globs of files that should always be pruned (can be specified multiple times)
75+
-d, --dry-run Show what would be pruned without actually removing files
76+
-w, --workspace Enable workspace/monorepo mode to prune all packages
77+
--workspace-root <dir> Specify the workspace root directory (auto-detected if not provided)
78+
--no-root Skip pruning the root node_modules in workspace mode
79+
--experimental-default-files Enable experimental extended file list for more aggressive pruning
80+
-h, --help Show help
7581
7682
Examples:
7783
prune-mod # Prune node_modules in current directory
@@ -83,6 +89,10 @@ Workspace/Monorepo Examples:
8389
prune-mod --workspace # Auto-detect and prune all packages in workspace
8490
prune-mod -w --no-root # Prune only package node_modules, skip root
8591
prune-mod -w --workspace-root /path/to/monorepo # Specify workspace root
92+
93+
Experimental Examples:
94+
prune-mod --experimental-default-files # Use extended file list for more aggressive pruning
95+
prune-mod -w --experimental-default-files # Combine workspace mode with experimental files
8696
`);
8797
}
8898

@@ -108,6 +118,9 @@ async function main() {
108118
workspace: Boolean(values.workspace),
109119
workspaceRoot: values["workspace-root"] as string | undefined,
110120
includeRoot: !Boolean(values["no-root"]),
121+
experimental: {
122+
defaultFiles: Boolean(values["experimental-default-files"]),
123+
},
111124
});
112125

113126
try {

src/constants.ts

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,182 @@ export const DefaultFiles = [
6969
"tslint.json",
7070
] as const;
7171

72+
export const ExperimentalDefaultFiles = [
73+
// Documentation & Project Files
74+
"CHANGELOG",
75+
"CHANGELOG.md",
76+
"CHANGELOG.txt",
77+
"HISTORY",
78+
"HISTORY.md",
79+
"CONTRIBUTING",
80+
"CONTRIBUTING.md",
81+
"CONTRIBUTING.txt",
82+
"README.md",
83+
"README.txt",
84+
"README.rst",
85+
"CODE_OF_CONDUCT.md",
86+
"SECURITY.md",
87+
"SUPPORT.md",
88+
"FUNDING.yml",
89+
90+
// Extended Configuration Files
91+
".eslintrc.yaml",
92+
".babelrc.js",
93+
".babelrc.json",
94+
"babel.config.js",
95+
"babel.config.json",
96+
"jest.config.json",
97+
"jest.config.ts",
98+
".prettierrc.yaml",
99+
"tsconfig.build.json",
100+
101+
// Git & Version Control
102+
".gitignore",
103+
".gitkeep",
104+
".gitmodules",
105+
".bzrignore",
106+
".hgignore",
107+
".svnignore",
108+
".dockerignore",
109+
110+
// Container & Deployment
111+
"Dockerfile",
112+
"docker-compose.yml",
113+
"docker-compose.yaml",
114+
"Procfile",
115+
116+
// Runtime Version Files
117+
".nvmrc",
118+
".node-version",
119+
".ruby-version",
120+
".python-version",
121+
122+
// Other Language Files
123+
"Rakefile",
124+
"Gemfile",
125+
"Gemfile.lock",
126+
"requirements.txt",
127+
"setup.py",
128+
"pyproject.toml",
129+
".pylintrc",
130+
".flake8",
131+
".mypy.ini",
132+
"tox.ini",
133+
"pytest.ini",
134+
135+
// Git Hooks & Pre-commit
136+
".pre-commit-config.yaml",
137+
".commitlintrc",
138+
".commitlintrc.js",
139+
".commitlintrc.json",
140+
".huskyrc",
141+
".huskyrc.js",
142+
".huskyrc.json",
143+
".lintstagedrc",
144+
".lintstagedrc.js",
145+
".lintstagedrc.json",
146+
"lint-staged.config.js",
147+
148+
// Documentation Tools
149+
".remarkrc",
150+
".remarkrc.js",
151+
".remarkrc.json",
152+
".markdownlint.json",
153+
".markdownlint.yaml",
154+
".markdownlint.yml",
155+
156+
// Build Tools
157+
"rollup.config.js",
158+
"rollup.config.ts",
159+
"webpack.config.js",
160+
"webpack.config.ts",
161+
"vite.config.js",
162+
"vite.config.ts",
163+
"vitest.config.js",
164+
"vitest.config.ts",
165+
166+
// Bundle Analysis & Performance
167+
".size-limit.json",
168+
"size-limit.config.js",
169+
".size-snapshot.json",
170+
"bundlesize.config.js",
171+
".bundlewatch.config.js",
172+
173+
// Testing Frameworks
174+
"ava.config.js",
175+
"ava.config.json",
176+
".taprc",
177+
"tap-snapshots",
178+
179+
// Coverage Tools
180+
".c8rc",
181+
".c8rc.js",
182+
".c8rc.json",
183+
".nycrc",
184+
".nycrc.js",
185+
".nycrc.json",
186+
"nyc.config.js",
187+
".istanbul.yml",
188+
189+
// Repository Management
190+
".github_changelog_generator",
191+
".dependabot.yml",
192+
".renovaterc",
193+
".renovaterc.js",
194+
".renovaterc.json",
195+
"renovate.json",
196+
".greenkeeper.json",
197+
198+
// CI/CD Services
199+
"codefresh.yml",
200+
"shippable.yml",
201+
"wercker.yml",
202+
".drone.yml",
203+
"azure-pipelines.yml",
204+
"buildkite.yml",
205+
206+
// Code Quality Services
207+
".codeclimate.yml",
208+
".scrutinizer.yml",
209+
".sonarqube.yml",
210+
"sonar-project.properties",
211+
".bettercodehub.yml",
212+
".codacy.yml",
213+
"codecov.yml",
214+
".codecov.yml",
215+
216+
// Framework/Library Build Outputs
217+
".storybook",
218+
"storybook-static",
219+
".next",
220+
".nuxt",
221+
".cache",
222+
".parcel-cache",
223+
"dist",
224+
"build",
225+
"lib",
226+
"esm",
227+
"umd",
228+
"cjs",
229+
"es",
230+
"types",
231+
"typings",
232+
233+
// Source Maps & Minified Files
234+
"*.d.ts.map",
235+
"*.js.map",
236+
"*.css.map",
237+
"*.min.js",
238+
"*.min.css",
239+
240+
// Environment Files
241+
".env.example",
242+
".env.local",
243+
".env.development",
244+
".env.production",
245+
".env.test",
246+
] as const;
247+
72248
export const DefaultDirectories = [
73249
"__tests__",
74250
"test",

src/prune.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import * as fs from "fs";
22
import { logger } from "./logger";
33
import { minimatch } from "minimatch";
4-
import { DefaultDirectories, DefaultExtensions, DefaultFiles } from "./constants";
4+
import {
5+
DefaultDirectories,
6+
DefaultExtensions,
7+
DefaultFiles,
8+
ExperimentalDefaultFiles,
9+
} from "./constants";
510
import type { PrunerOptions, Stats } from "./types";
611
import { WorkspaceDetector, type WorkspaceInfo, WorkspaceType } from "./workspace";
712
import {
@@ -46,7 +51,19 @@ export class Pruner {
4651
this.excepts = options.exceptions || [];
4752
this.globs = options.globs || [];
4853
this.dirs = new Set(options.directories || DefaultDirectories);
49-
this.files = new Set(options.files || DefaultFiles);
54+
55+
// Handle experimental default files
56+
let defaultFiles = [...DefaultFiles] as string[];
57+
if (options.experimental?.defaultFiles) {
58+
defaultFiles = [...DefaultFiles, ...ExperimentalDefaultFiles] as string[];
59+
if (this.verbose) {
60+
logger.info(
61+
`Experimental mode: Using extended file list with ${ExperimentalDefaultFiles.length} additional files`,
62+
);
63+
}
64+
}
65+
this.files = new Set(options.files || defaultFiles);
66+
5067
this.workspace = options.workspace || false;
5168
this.workspaceRoot = options.workspaceRoot;
5269
this.includeRoot = options.includeRoot !== false; // Default to true

src/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,7 @@ export interface PrunerOptions {
1818
workspace?: boolean;
1919
workspaceRoot?: string;
2020
includeRoot?: boolean;
21+
experimental?: {
22+
defaultFiles?: boolean;
23+
};
2124
}

0 commit comments

Comments
 (0)