nukelear 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.
- package/LICENSE +21 -0
- package/README.md +468 -0
- package/dist/config.js +27 -0
- package/dist/index.js +62 -0
- package/dist/package.json +61 -0
- package/dist/tli.js +55 -0
- package/dist/utils.js +50 -0
- package/package.json +61 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Ajaykumar Nadar
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# Nukelear 💣
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/nukelear)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
[](https://github.com/ajaykumarn3000/nukelear/issues)
|
|
8
|
+
[](https://github.com/ajaykumarn3000/nukelear/stargazers)
|
|
9
|
+
[](https://github.com/ajaykumarn3000/nukelear/network)
|
|
10
|
+
[](https://github.com/ajaykumarn3000/nukelear/graphs/contributors)
|
|
11
|
+
|
|
12
|
+
**Recursively delete package files and dependencies from nested project
|
|
13
|
+
folders.**
|
|
14
|
+
|
|
15
|
+
[⭐ Star on GitHub](https://github.com/ajaykumarn3000/nukelear) •
|
|
16
|
+
[🐛 Report Bug](https://github.com/ajaykumarn3000/nukelear/issues) •
|
|
17
|
+
[💡 Request Feature](https://github.com/ajaykumarn3000/nukelear/discussions) •
|
|
18
|
+
[🤝 Contribute](https://github.com/ajaykumarn3000/nukelear/blob/main/CONTRIBUTING.md)
|
|
19
|
+
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 🎯 What is Nukelear?
|
|
25
|
+
|
|
26
|
+
Nukelear is a powerful CLI tool designed to help developers reclaim disk storage
|
|
27
|
+
by efficiently deleting unwanted package files and dependency folders from
|
|
28
|
+
nested project structures.
|
|
29
|
+
|
|
30
|
+
### The Problem
|
|
31
|
+
|
|
32
|
+
If you have a large, nested development folder structure (like `Dev/` containing
|
|
33
|
+
multiple stack-specific subfolders - `python/`, `nodejs/`, `nextjs/`, etc.) and
|
|
34
|
+
install libraries/packages for development or demonstration, those
|
|
35
|
+
`node_modules` directories, Python `venv`, and other dependency folders can
|
|
36
|
+
consume **gigabytes** of storage over time. Manually tracking and deleting these
|
|
37
|
+
folders from hundreds of projects is tedious and error-prone.
|
|
38
|
+
|
|
39
|
+
### The Solution
|
|
40
|
+
|
|
41
|
+
Nukelear scans your entire development folder structure and lets you selectively
|
|
42
|
+
delete package files and dependency directories from all projects in one
|
|
43
|
+
command. No more forgotten `node_modules` sitting around for months or years.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## ✨ Features
|
|
48
|
+
|
|
49
|
+
- 🎯 **Recursive Scanning** - Finds and deletes unwanted files across deeply
|
|
50
|
+
nested project structures
|
|
51
|
+
- 📦 **Multi-Technology Support** - Delete dependencies for Python, Node.js,
|
|
52
|
+
Next.js, VSCode, and macOS
|
|
53
|
+
- 🖥️ **Interactive TUI** - User-friendly terminal interface for selecting what
|
|
54
|
+
to delete
|
|
55
|
+
- ⚡ **Bulk Operations** - Clean up multiple projects with a single command
|
|
56
|
+
- 🛡️ **Safe by Default** - Review selections before confirming deletion
|
|
57
|
+
- 🚀 **Zero Configuration** - Works out of the box with sensible defaults
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 🚀 Quick Start
|
|
62
|
+
|
|
63
|
+
### Using npx (Recommended)
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npx nukelear@latest <directory>
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Replace `<directory>` with the path to your root development folder.
|
|
70
|
+
|
|
71
|
+
### Install Globally
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
npm install -g nukelear
|
|
75
|
+
nukelear <directory>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### System Requirements
|
|
79
|
+
|
|
80
|
+
- **Node.js**: 18.0 or higher
|
|
81
|
+
- **npm**: 7.0 or higher (or **yarn**/**pnpm** equivalent)
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## 📖 Usage
|
|
86
|
+
|
|
87
|
+
### Interactive Mode (Recommended)
|
|
88
|
+
|
|
89
|
+
When you run Nukelear without specifying technologies, you'll be presented with
|
|
90
|
+
an interactive interface:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
$ npx nukelear ~/Dev
|
|
94
|
+
|
|
95
|
+
┌ nukelear
|
|
96
|
+
│
|
|
97
|
+
◇ Select technologies to nuke:
|
|
98
|
+
│ ◈ Node.js (node_modules, dist, build)
|
|
99
|
+
│ ◈ Python (venv, .venv, __pycache__)
|
|
100
|
+
│ ◈ Next.js (.next, node_modules, dist, build)
|
|
101
|
+
│ ◈ VSCode (.vscode)
|
|
102
|
+
│ ◈ macOS (.DS_Store)
|
|
103
|
+
│
|
|
104
|
+
◇ Confirm deletion?
|
|
105
|
+
│ This will permanently delete the selected directories.
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Non-Interactive Mode (Flags)
|
|
109
|
+
|
|
110
|
+
Skip all prompts by specifying technologies via flags:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
# Delete only Node.js dependencies
|
|
114
|
+
nukelear ~/Dev --node
|
|
115
|
+
|
|
116
|
+
# Delete multiple technologies at once
|
|
117
|
+
nukelear ~/Dev --node --python
|
|
118
|
+
|
|
119
|
+
# Delete everything
|
|
120
|
+
nukelear ~/Dev --node --next --python --vscode --macos
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## 🛠️ Supported Technologies
|
|
126
|
+
|
|
127
|
+
Nukelear can delete dependencies for the following technologies:
|
|
128
|
+
|
|
129
|
+
| Flag | Description | Directories Deleted |
|
|
130
|
+
| ---------- | -------------------------------------- | ------------------------------- |
|
|
131
|
+
| `--node` | Node.js project dependencies | `node_modules`, `dist`, `build` |
|
|
132
|
+
| `--next` | Next.js project dependencies and cache | `.next`, `node_modules`, `dist` |
|
|
133
|
+
| `--python` | Python virtual environments and cache | `venv`, `.venv`, `__pycache__` |
|
|
134
|
+
| `--vscode` | VSCode workspace settings | `.vscode` |
|
|
135
|
+
| `--macos` | macOS system files | `.DS_Store` |
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## ⚙️ Configuration
|
|
140
|
+
|
|
141
|
+
Nukelear's technology definitions and file mappings are defined in
|
|
142
|
+
`nukelear.config.ts`:
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
type ConfigItem = {
|
|
146
|
+
name: string;
|
|
147
|
+
value: string;
|
|
148
|
+
directories: string[];
|
|
149
|
+
};
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Each item in the config specifies:
|
|
153
|
+
|
|
154
|
+
- **name** - Display name in the UI
|
|
155
|
+
- **value** - CLI flag name
|
|
156
|
+
- **directories** - Array of directory/file names to delete recursively
|
|
157
|
+
|
|
158
|
+
To add support for a new technology, simply add it to the `nukelearConfig` array
|
|
159
|
+
in `nukelear.config.ts`.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 🏗️ Local Development
|
|
164
|
+
|
|
165
|
+
Want to contribute to Nukelear or test changes locally? Here's how to get
|
|
166
|
+
started:
|
|
167
|
+
|
|
168
|
+
### Prerequisites
|
|
169
|
+
|
|
170
|
+
- Node.js 18.0 or higher
|
|
171
|
+
- npm 7.0 or higher
|
|
172
|
+
- Git
|
|
173
|
+
|
|
174
|
+
### Clone and Setup
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
# Clone the repository
|
|
178
|
+
git clone https://github.com/ajaykumarn3000/nukelear.git
|
|
179
|
+
cd nukelear
|
|
180
|
+
|
|
181
|
+
# Install dependencies
|
|
182
|
+
npm install
|
|
183
|
+
|
|
184
|
+
# Run in development mode
|
|
185
|
+
npm run dev ~/Dev
|
|
186
|
+
|
|
187
|
+
# Build the project
|
|
188
|
+
npm run build
|
|
189
|
+
|
|
190
|
+
# Test the CLI locally (creates a global symlink)
|
|
191
|
+
npm link
|
|
192
|
+
nukelear ~/Dev
|
|
193
|
+
|
|
194
|
+
# Unlink when done testing
|
|
195
|
+
npm unlink -g nukelear
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Available Scripts
|
|
199
|
+
|
|
200
|
+
| Script | Description |
|
|
201
|
+
| ------------------ | ---------------------------------------------------------- |
|
|
202
|
+
| `npm run dev` | Run the CLI in development mode with `tsx` |
|
|
203
|
+
| `npm run build` | Build and lint the project for production |
|
|
204
|
+
| `npm run lint` | Run ESLint to check for code issues |
|
|
205
|
+
| `npm run lint:fix` | Auto-fix ESLint issues where possible |
|
|
206
|
+
| `npm run format` | Format code with Prettier |
|
|
207
|
+
| `npm run clean` | Remove the `dist` directory |
|
|
208
|
+
| `npm run deploy` | Build and publish to npm (maintainers only) |
|
|
209
|
+
| `npm run prepare` | Run `husky` prepare script to set up git hooks (auto-run). |
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## 📁 Project Structure
|
|
214
|
+
|
|
215
|
+
```text
|
|
216
|
+
nukelear/
|
|
217
|
+
├── index.ts # Main CLI entry point
|
|
218
|
+
├── tli.ts # Interactive TUI prompts
|
|
219
|
+
├── utils.ts # Core utility functions
|
|
220
|
+
├── nukelear.config.ts # Technology configuration
|
|
221
|
+
├── package.json # Project configuration
|
|
222
|
+
├── tsconfig.json # TypeScript configuration
|
|
223
|
+
├── eslint.config.js # ESLint configuration
|
|
224
|
+
├── commitlint.config.js # Conventional commits configuration
|
|
225
|
+
├── dist/ # Compiled output (created after build)
|
|
226
|
+
└── README.md # This file
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Key Files Explained
|
|
230
|
+
|
|
231
|
+
- **index.ts** - Entry point that sets up the CLI, parses arguments, and
|
|
232
|
+
orchestrates the workflow
|
|
233
|
+
- **tli.ts** - Terminal UI helpers that provide interactive prompts for
|
|
234
|
+
selecting technologies and confirming deletion
|
|
235
|
+
- **utils.ts** - Core functions for scanning directories and recursively
|
|
236
|
+
deleting files
|
|
237
|
+
- **nukelear.config.ts** - Configuration that defines supported technologies and
|
|
238
|
+
their associated directories
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## 🔄 How Nukelear Works (Behind the Scenes)
|
|
243
|
+
|
|
244
|
+
High-level flow when running `nukelear <directory>`:
|
|
245
|
+
|
|
246
|
+
1. **Parse CLI Arguments** - Use Commander.js to parse the directory path and
|
|
247
|
+
optional flags
|
|
248
|
+
2. **Validate Directory** - Ensure the provided directory exists and is
|
|
249
|
+
accessible
|
|
250
|
+
3. **Interactive Selection** (if no flags provided) - Use interactive prompts to
|
|
251
|
+
let users select which technologies to delete
|
|
252
|
+
4. **Scan for Directories** - Recursively scan the directory tree to find all
|
|
253
|
+
instances of the selected directories
|
|
254
|
+
5. **Confirmation** - Display a summary of what will be deleted and ask for
|
|
255
|
+
confirmation
|
|
256
|
+
6. **Delete Recursively** - Remove all matching directories and files
|
|
257
|
+
7. **Report Results** - Show a summary of what was deleted and storage freed
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## 📊 Example Scenarios
|
|
262
|
+
|
|
263
|
+
### Scenario 1: Clean a Multi-Stack Development Folder
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
$ nukelear ~/Dev --node --python
|
|
267
|
+
|
|
268
|
+
Scanning ~/Dev for Node.js and Python dependencies...
|
|
269
|
+
|
|
270
|
+
Found:
|
|
271
|
+
• 47 node_modules directories (~3.2 GB)
|
|
272
|
+
• 12 venv directories (~450 MB)
|
|
273
|
+
• 8 __pycache__ directories (~120 MB)
|
|
274
|
+
|
|
275
|
+
Total space that will be freed: ~3.77 GB
|
|
276
|
+
|
|
277
|
+
Proceed with deletion? (yes/no)
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Scenario 2: Interactive Selection
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
$ nukelear ~/Dev
|
|
284
|
+
|
|
285
|
+
? Select technologies to nuke:
|
|
286
|
+
◉ Node.js
|
|
287
|
+
◉ Next.js
|
|
288
|
+
○ Python
|
|
289
|
+
○ VSCode
|
|
290
|
+
○ macOS
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
### Scenario 3: Targeted Cleanup
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
# Only clean Python environments
|
|
297
|
+
$ nukelear ~/Dev --python
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## 📋 CLI Reference
|
|
303
|
+
|
|
304
|
+
### Basic Usage
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
nukelear <directory> [options]
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Options
|
|
311
|
+
|
|
312
|
+
| Flag | Description |
|
|
313
|
+
| --------------- | -------------------------------------- |
|
|
314
|
+
| `-v, --version` | Output the current version of Nukelear |
|
|
315
|
+
| `-h, --help` | Display help and available options |
|
|
316
|
+
| `--node` | Delete Node.js dependencies |
|
|
317
|
+
| `--next` | Delete Next.js dependencies |
|
|
318
|
+
| `--python` | Delete Python virtual environments |
|
|
319
|
+
| `--vscode` | Delete VSCode workspace settings |
|
|
320
|
+
| `--macos` | Delete macOS system files |
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## 🚨 Safety & Best Practices
|
|
325
|
+
|
|
326
|
+
### Before Running Nukelear
|
|
327
|
+
|
|
328
|
+
1. **Backup Important Data** - If you have uncommitted changes, commit or stash
|
|
329
|
+
them first
|
|
330
|
+
2. **Review Selections** - Always confirm the directories that will be deleted
|
|
331
|
+
3. **Test on a Small Folder** - Try Nukelear on a small test directory first
|
|
332
|
+
4. **Version Control** - Ensure all important code is committed to git
|
|
333
|
+
|
|
334
|
+
### Recovery
|
|
335
|
+
|
|
336
|
+
If you accidentally delete important files:
|
|
337
|
+
|
|
338
|
+
- **Git Repositories** - Run `npm install`, `pip install -r requirements.txt`,
|
|
339
|
+
etc. to restore dependencies from lock files
|
|
340
|
+
- **Untracked Files** - These cannot be recovered; ensure they're committed to
|
|
341
|
+
version control
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
## 📄 Project Policies & Community Files
|
|
346
|
+
|
|
347
|
+
For details on contributing, security, and community standards, see:
|
|
348
|
+
|
|
349
|
+
- [LICENSE](./LICENSE)
|
|
350
|
+
- [Code of Conduct](./CODE_OF_CONDUCT.md)
|
|
351
|
+
- [Contributing Guidelines](./CONTRIBUTING.md)
|
|
352
|
+
- [Security Policy](./SECURITY.md)
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## 🐛 Issues and Support
|
|
357
|
+
|
|
358
|
+
We're here to help! If you encounter any issues or have questions:
|
|
359
|
+
|
|
360
|
+
### 🚨 Bug Reports
|
|
361
|
+
|
|
362
|
+
- **GitHub Issues**:
|
|
363
|
+
[Report bugs here](https://github.com/ajaykumarn3000/nukelear/issues)
|
|
364
|
+
- Please use our bug report template for faster resolution
|
|
365
|
+
|
|
366
|
+
### 💡 Feature Requests
|
|
367
|
+
|
|
368
|
+
- **GitHub Discussions**:
|
|
369
|
+
[Suggest new features](https://github.com/ajaykumarn3000/nukelear/discussions)
|
|
370
|
+
- Help us understand your use case (e.g., new technology support)
|
|
371
|
+
|
|
372
|
+
### ❓ Questions and Support
|
|
373
|
+
|
|
374
|
+
- **GitHub Discussions**:
|
|
375
|
+
[Ask questions here](https://github.com/ajaykumarn3000/nukelear/discussions)
|
|
376
|
+
- **Documentation**: Check this README for common use cases
|
|
377
|
+
|
|
378
|
+
### 🔍 Before Reporting
|
|
379
|
+
|
|
380
|
+
1. **Search existing issues** to avoid duplicates
|
|
381
|
+
2. **Check the latest version** - your issue might already be fixed
|
|
382
|
+
3. **Review the documentation** - the answer might already be here
|
|
383
|
+
4. **Test with a minimal example** - helps us reproduce the issue
|
|
384
|
+
|
|
385
|
+
---
|
|
386
|
+
|
|
387
|
+
## 🌟 Community
|
|
388
|
+
|
|
389
|
+
Join our growing community of developers:
|
|
390
|
+
|
|
391
|
+
- ⭐ **Star the project** on GitHub to show your support
|
|
392
|
+
- 🐛 **Report issues** to help us improve
|
|
393
|
+
- 💬 **Join discussions** to share ideas and ask questions
|
|
394
|
+
- 🤝 **Contribute code** to make Nukelear even better
|
|
395
|
+
- 📢 **Share with others** who might find Nukelear useful
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
## 🔒 Security
|
|
400
|
+
|
|
401
|
+
If you discover a security vulnerability, please report it privately by emailing
|
|
402
|
+
[ajaykumarn3000@gmail.com](mailto:ajaykumarn3000@gmail.com). Please do not
|
|
403
|
+
report security vulnerabilities through public GitHub issues.
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
## 📊 Project Stats
|
|
408
|
+
|
|
409
|
+
- **Language**: TypeScript
|
|
410
|
+
- **Package Manager**: npm
|
|
411
|
+
- **License**: MIT
|
|
412
|
+
- **Maintained**: ✅ Actively maintained
|
|
413
|
+
- **Node.js**: 18.0+ required
|
|
414
|
+
|
|
415
|
+
### Key Dependencies
|
|
416
|
+
|
|
417
|
+
- Runtime: `@clack/prompts` (interactive prompts), `chalk` (colors), `commander`
|
|
418
|
+
(CLI parsing)
|
|
419
|
+
- Dev: `eslint`, `prettier`, `husky`, `@commitlint/cli`, `typescript`, `tsx`
|
|
420
|
+
|
|
421
|
+
---
|
|
422
|
+
|
|
423
|
+
## 🗺️ Roadmap
|
|
424
|
+
|
|
425
|
+
We're continuously working to improve Nukelear. Here's what's on our radar:
|
|
426
|
+
|
|
427
|
+
- [ ] **Additional Technologies**: Ruby, PHP, Go, Java, Rust support
|
|
428
|
+
- [ ] **Dry Run Mode**: Preview what will be deleted without actually deleting
|
|
429
|
+
- [ ] **Ignore Files**: Support for `.nukelearignore` to exclude specific paths
|
|
430
|
+
- [ ] **Statistics**: Show disk space freed per technology
|
|
431
|
+
- [ ] **Parallel Processing**: Speed up scanning of very large directory trees
|
|
432
|
+
- [ ] **Configuration Profiles**: Save and reuse common deletion patterns
|
|
433
|
+
|
|
434
|
+
Want to contribute to any of these? We'd love your help!
|
|
435
|
+
|
|
436
|
+
---
|
|
437
|
+
|
|
438
|
+
## 📜 License
|
|
439
|
+
|
|
440
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
|
|
441
|
+
for details.
|
|
442
|
+
|
|
443
|
+
---
|
|
444
|
+
|
|
445
|
+
## 🙏 Acknowledgments
|
|
446
|
+
|
|
447
|
+
Nukelear stands on the shoulders of giants. We're grateful to:
|
|
448
|
+
|
|
449
|
+
- **Open Source Community**: For the amazing tools and libraries we integrate
|
|
450
|
+
- **Tool Maintainers**: clack, chalk, and commander contributors
|
|
451
|
+
- **Contributors**: Everyone who has contributed code, reported issues, or
|
|
452
|
+
shared feedback
|
|
453
|
+
- **Users**: The developer community that uses and trusts Nukelear
|
|
454
|
+
|
|
455
|
+
---
|
|
456
|
+
|
|
457
|
+
<div align="center">
|
|
458
|
+
|
|
459
|
+
**Made with ❤️ by [Ajaykumar Nadar](https://github.com/ajaykumarn3000/)**
|
|
460
|
+
|
|
461
|
+
_Building tools that developers love to use_
|
|
462
|
+
|
|
463
|
+
[⭐ Star on GitHub](https://github.com/ajaykumarn3000/nukelear) •
|
|
464
|
+
[🐛 Report Bug](https://github.com/ajaykumarn3000/nukelear/issues) •
|
|
465
|
+
[💡 Request Feature](https://github.com/ajaykumarn3000/nukelear/discussions) •
|
|
466
|
+
[🤝 Contribute](https://github.com/ajaykumarn3000/nukelear/blob/main/CONTRIBUTING.md)
|
|
467
|
+
|
|
468
|
+
</div>
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export const config = [
|
|
2
|
+
{
|
|
3
|
+
name: 'Python',
|
|
4
|
+
value: 'python',
|
|
5
|
+
directories: ['venv', '.venv', '__pycache__'],
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
name: 'Node.js',
|
|
9
|
+
value: 'node',
|
|
10
|
+
directories: ['node_modules', 'dist', 'build'],
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
name: 'Next.js',
|
|
14
|
+
value: 'next',
|
|
15
|
+
directories: ['node_modules', '.next', 'dist', 'build'],
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: 'VSCode',
|
|
19
|
+
value: 'vscode',
|
|
20
|
+
directories: ['.vscode'],
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: 'MacOS',
|
|
24
|
+
value: 'macos',
|
|
25
|
+
directories: ['.DS_Store'],
|
|
26
|
+
},
|
|
27
|
+
];
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import * as p from '@clack/prompts';
|
|
3
|
+
import { chalkStderr } from 'chalk';
|
|
4
|
+
import packageJSON from './package.json' with { type: 'json' };
|
|
5
|
+
import { config } from './config.js';
|
|
6
|
+
import { getTechnology, selectDirectories, confirmNuke } from './tli.js';
|
|
7
|
+
import { findTargetDirectories, nukeDirectories } from './utils.js';
|
|
8
|
+
import { Command, Option } from 'commander';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
import fs from 'node:fs';
|
|
11
|
+
const { green } = chalkStderr;
|
|
12
|
+
const handleSigTerm = () => process.exit(0);
|
|
13
|
+
process.on('SIGINT', handleSigTerm);
|
|
14
|
+
process.on('SIGTERM', handleSigTerm);
|
|
15
|
+
async function main() {
|
|
16
|
+
const program = new Command(packageJSON.name)
|
|
17
|
+
.version(packageJSON.version, '-v, --version', 'Output the current version of Nukelear.')
|
|
18
|
+
.argument('<directory>')
|
|
19
|
+
.usage('<directory> [options]')
|
|
20
|
+
.helpOption('-h, --help', 'Display this help message.');
|
|
21
|
+
for (const tool of config) {
|
|
22
|
+
program.addOption(new Option(`--${tool.value}`, `${tool.directories.join(', ')}`));
|
|
23
|
+
}
|
|
24
|
+
program.parse(process.argv);
|
|
25
|
+
const options = program.opts();
|
|
26
|
+
const { args } = program;
|
|
27
|
+
const projectName = args[0];
|
|
28
|
+
const basePath = path.resolve(process.cwd(), projectName);
|
|
29
|
+
if (!fs.existsSync(basePath)) {
|
|
30
|
+
p.outro(`The directory ${green(projectName)} does not exist.`);
|
|
31
|
+
return process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
const technologies = Object.keys(options).length
|
|
34
|
+
? Object.keys(options)
|
|
35
|
+
: await getTechnology();
|
|
36
|
+
const dirsToNuke = new Set();
|
|
37
|
+
for (const tech of technologies) {
|
|
38
|
+
const toolConfig = config.find(tool => tool.value === tech);
|
|
39
|
+
if (toolConfig) {
|
|
40
|
+
toolConfig.directories.forEach(dir => dirsToNuke.add(dir));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const foundDirs = await findTargetDirectories(basePath, dirsToNuke);
|
|
44
|
+
if (foundDirs.size === 0) {
|
|
45
|
+
p.outro('No target directories found to nuke.');
|
|
46
|
+
return process.exit(0);
|
|
47
|
+
}
|
|
48
|
+
const confirmedDirs = await selectDirectories(foundDirs);
|
|
49
|
+
const isConfirmed = await confirmNuke();
|
|
50
|
+
if (isConfirmed) {
|
|
51
|
+
await nukeDirectories(confirmedDirs);
|
|
52
|
+
p.outro('Nuking completed successfully!');
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
p.outro('Nuking operation cancelled.');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
main().catch(err => {
|
|
59
|
+
console.error(err);
|
|
60
|
+
p.outro('An error occurred: ' + err.message);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nukelear",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "npx eslint . && npm run clean && tsc",
|
|
8
|
+
"clean": "rm -rf dist",
|
|
9
|
+
"lint": "eslint . ",
|
|
10
|
+
"lint:fix": "eslint . --fix",
|
|
11
|
+
"format:check": "prettier --check .",
|
|
12
|
+
"format": "prettier --write .",
|
|
13
|
+
"dev": "tsx index.ts",
|
|
14
|
+
"deploy": "npm run build && npm publish --access public",
|
|
15
|
+
"prepare": "husky"
|
|
16
|
+
},
|
|
17
|
+
"bin": {
|
|
18
|
+
"nukelear": "./dist/index.js"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "https://github.com/ajaykumarn3000/nukelear.git"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"nukelear",
|
|
29
|
+
"cli",
|
|
30
|
+
"tools"
|
|
31
|
+
],
|
|
32
|
+
"author": {
|
|
33
|
+
"username": "ajaykumarn3000",
|
|
34
|
+
"url": "https://ajaykumarn3000.in",
|
|
35
|
+
"name": "Ajaykumar Nadar",
|
|
36
|
+
"email": "ajaykumarn3000@gmail.com"
|
|
37
|
+
},
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"type": "module",
|
|
40
|
+
"packageManager": "pnpm@10.27.0",
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@clack/prompts": "^0.11.0",
|
|
43
|
+
"chalk": "^5.6.2",
|
|
44
|
+
"commander": "^14.0.2",
|
|
45
|
+
"tsx": "^4.21.0"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@commitlint/cli": "^20.3.0",
|
|
49
|
+
"@commitlint/config-conventional": "^20.3.0",
|
|
50
|
+
"@eslint/js": "^9.39.2",
|
|
51
|
+
"@eslint/json": "^0.14.0",
|
|
52
|
+
"@eslint/markdown": "^7.5.1",
|
|
53
|
+
"@types/node": "^25.0.3",
|
|
54
|
+
"eslint": "^9.39.2",
|
|
55
|
+
"globals": "^17.0.0",
|
|
56
|
+
"husky": "^9.1.7",
|
|
57
|
+
"prettier": "^3.7.4",
|
|
58
|
+
"typescript": "^5.9.3",
|
|
59
|
+
"typescript-eslint": "^8.51.0"
|
|
60
|
+
}
|
|
61
|
+
}
|
package/dist/tli.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as p from '@clack/prompts';
|
|
2
|
+
import { chalkStderr } from 'chalk';
|
|
3
|
+
import { config } from './config.js';
|
|
4
|
+
const { cyan } = chalkStderr;
|
|
5
|
+
export async function getDirectory() {
|
|
6
|
+
const directoryName = await p.text({
|
|
7
|
+
message: `Enter the ${cyan('directory name')}`,
|
|
8
|
+
});
|
|
9
|
+
if (p.isCancel(directoryName)) {
|
|
10
|
+
p.cancel('Operation cancelled.');
|
|
11
|
+
return process.exit(0);
|
|
12
|
+
}
|
|
13
|
+
return directoryName;
|
|
14
|
+
}
|
|
15
|
+
export async function getTechnology() {
|
|
16
|
+
const technology = await p.multiselect({
|
|
17
|
+
message: `Select ${cyan('technologies')} to nuke`,
|
|
18
|
+
options: config.map(tool => ({
|
|
19
|
+
value: tool.value,
|
|
20
|
+
label: tool.name,
|
|
21
|
+
hint: tool.directories.join(', '),
|
|
22
|
+
})),
|
|
23
|
+
});
|
|
24
|
+
if (p.isCancel(technology)) {
|
|
25
|
+
p.cancel('Operation cancelled.');
|
|
26
|
+
return process.exit(0);
|
|
27
|
+
}
|
|
28
|
+
return technology;
|
|
29
|
+
}
|
|
30
|
+
export async function selectDirectories(directories) {
|
|
31
|
+
const confirmedDirectories = await p.multiselect({
|
|
32
|
+
message: `Select ${cyan('directories')} to nuke`,
|
|
33
|
+
options: Array.from(directories).map(dir => ({
|
|
34
|
+
value: dir,
|
|
35
|
+
label: dir,
|
|
36
|
+
})),
|
|
37
|
+
initialValues: Array.from(directories),
|
|
38
|
+
});
|
|
39
|
+
if (p.isCancel(confirmedDirectories)) {
|
|
40
|
+
p.cancel('Operation cancelled.');
|
|
41
|
+
return process.exit(0);
|
|
42
|
+
}
|
|
43
|
+
return confirmedDirectories;
|
|
44
|
+
}
|
|
45
|
+
export async function confirmNuke() {
|
|
46
|
+
const confirmation = await p.confirm({
|
|
47
|
+
message: `Are you sure you want to nuke the selected directories?`,
|
|
48
|
+
initialValue: true,
|
|
49
|
+
});
|
|
50
|
+
if (p.isCancel(confirmation)) {
|
|
51
|
+
p.cancel('Operation cancelled.');
|
|
52
|
+
return process.exit(0);
|
|
53
|
+
}
|
|
54
|
+
return confirmation;
|
|
55
|
+
}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import * as p from '@clack/prompts';
|
|
4
|
+
const SKIP_DIRS = new Set(['.git']);
|
|
5
|
+
export async function findTargetDirectories(dir, targetDirs, foundDirs = new Set()) {
|
|
6
|
+
try {
|
|
7
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
8
|
+
for (const entry of entries) {
|
|
9
|
+
const fullPath = path.join(dir, entry.name);
|
|
10
|
+
if (targetDirs.has(entry.name)) {
|
|
11
|
+
foundDirs.add(fullPath);
|
|
12
|
+
}
|
|
13
|
+
else if (entry.isDirectory() && !SKIP_DIRS.has(entry.name)) {
|
|
14
|
+
try {
|
|
15
|
+
await findTargetDirectories(fullPath, targetDirs, foundDirs);
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
// Handle permission errors gracefully
|
|
19
|
+
if (error instanceof Error &&
|
|
20
|
+
'code' in error &&
|
|
21
|
+
error.code !== 'EACCES') {
|
|
22
|
+
console.error(`Error traversing ${fullPath}:`, error.message);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
if (error instanceof Error && 'code' in error && error.code !== 'EACCES') {
|
|
30
|
+
console.error(`Error reading directory ${dir}:`, error.message);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return foundDirs;
|
|
34
|
+
}
|
|
35
|
+
export async function nukeDirectories(directories) {
|
|
36
|
+
await p.tasks(directories.map(dir => {
|
|
37
|
+
return {
|
|
38
|
+
title: `Nuking ${dir}`,
|
|
39
|
+
task: async () => {
|
|
40
|
+
try {
|
|
41
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
42
|
+
return `Nuked ${dir}`;
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
return `Failed to nuke ${dir}: ${error}`;
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}));
|
|
50
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nukelear",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "npx eslint . && npm run clean && tsc",
|
|
8
|
+
"clean": "rm -rf dist",
|
|
9
|
+
"lint": "eslint . ",
|
|
10
|
+
"lint:fix": "eslint . --fix",
|
|
11
|
+
"format:check": "prettier --check .",
|
|
12
|
+
"format": "prettier --write .",
|
|
13
|
+
"dev": "tsx index.ts",
|
|
14
|
+
"deploy": "npm run build && npm publish --access public",
|
|
15
|
+
"prepare": "husky"
|
|
16
|
+
},
|
|
17
|
+
"bin": {
|
|
18
|
+
"nukelear": "./dist/index.js"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "https://github.com/ajaykumarn3000/nukelear.git"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"nukelear",
|
|
29
|
+
"cli",
|
|
30
|
+
"tools"
|
|
31
|
+
],
|
|
32
|
+
"author": {
|
|
33
|
+
"username": "ajaykumarn3000",
|
|
34
|
+
"url": "https://ajaykumarn3000.in",
|
|
35
|
+
"name": "Ajaykumar Nadar",
|
|
36
|
+
"email": "ajaykumarn3000@gmail.com"
|
|
37
|
+
},
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"type": "module",
|
|
40
|
+
"packageManager": "pnpm@10.27.0",
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@clack/prompts": "^0.11.0",
|
|
43
|
+
"chalk": "^5.6.2",
|
|
44
|
+
"commander": "^14.0.2",
|
|
45
|
+
"tsx": "^4.21.0"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@commitlint/cli": "^20.3.0",
|
|
49
|
+
"@commitlint/config-conventional": "^20.3.0",
|
|
50
|
+
"@eslint/js": "^9.39.2",
|
|
51
|
+
"@eslint/json": "^0.14.0",
|
|
52
|
+
"@eslint/markdown": "^7.5.1",
|
|
53
|
+
"@types/node": "^25.0.3",
|
|
54
|
+
"eslint": "^9.39.2",
|
|
55
|
+
"globals": "^17.0.0",
|
|
56
|
+
"husky": "^9.1.7",
|
|
57
|
+
"prettier": "^3.7.4",
|
|
58
|
+
"typescript": "^5.9.3",
|
|
59
|
+
"typescript-eslint": "^8.51.0"
|
|
60
|
+
}
|
|
61
|
+
}
|