torch-it 2.5.4 → 2.6.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 (3) hide show
  1. package/README.md +38 -17
  2. package/dist/torch-it.js +19 -15
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -3,6 +3,7 @@
3
3
  [![GitHub Release](https://img.shields.io/github/v/release/piyook/torch-it?include_prereleases&sort=semver)](https://github.com/piyook/torch-it/releases)
4
4
  [![tests workflow](https://github.com/piyook/torch-it/actions/workflows/tests.yaml/badge.svg)](https://github.com/piyook/torch-it/actions/workflows/tests.yaml)
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+ [![npm version](https://img.shields.io/npm/v/torch-it)](https://www.npmjs.com/package/torch-it)
6
7
 
7
8
  A powerful, all-in-one, zero-dependency, fully customizable tool to **reset, clean, and rebuild** your Node.js (and optionally Dockerized) project environments with a single command.
8
9
 
@@ -28,7 +29,7 @@ It's surprising how often this just fixes things. 🤞
28
29
  - **Comprehensive framework support** — handles React, Next.js, Vue, Vite, SvelteKit, Remix, Qwik, Nuxt, Astro, Angular, Solid, and 40+ more
29
30
  - **Smart file pattern matching** — removes `*.log`, `*.tgz`, `*.tar.gz`, and other temporary files automatically
30
31
  - **Fully customizable** — specify any directories or files to delete via `torchrc.json`
31
- - **Docker support** — removes containers, images, and volumes and rebuilds from scratch 🐳
32
+ - **Docker support** — optional Docker teardown, rebuild, and launch when you enable Docker mode 🐳
32
33
  - **Cross-platform** — works on Windows, Linux, and macOS
33
34
  - **Zero-dependency** — lightweight and no additional packages required
34
35
 
@@ -116,15 +117,25 @@ React, Next.js, Vue, Vite, SvelteKit, React Native, Expo, Remix, Qwik, Nuxt, Ast
116
117
  - **Cleans package manager caches** for npm, yarn, and pnpm.
117
118
  - **Reinstalls dependencies** using your preferred package manager (npm, yarn, or pnpm).
118
119
 
119
- ### Docker Operations (Only if Docker is Configured)
120
+ ### Docker Operations (Optional)
120
121
 
121
- If your project includes either a `Dockerfile`, `docker-compose.yml`, or `docker-compose.yaml`, `torch-it` will also:
122
+ Runs only when **Docker mode is on** (`dockerMode`: `true` or `--dockerMode=true`) **and** the project root has a `Dockerfile` and/or **`docker-compose.yml` / `docker-compose.yaml`**. Default is **off**.
122
123
 
123
- - **Stop and clean up Docker resources** (containers, images, volumes) if Docker is running.
124
- - **Rebuild Docker images** from scratch.
125
- - **Restart Docker services** in detached mode.
124
+ These steps target **Docker Compose**. You almost always want a Compose file; detection can trigger on a Dockerfile alone, but the commands below are Compose workflows, not a plain `docker build`.
126
125
 
127
- `torch-it` intelligently detects your project's configuration and only performs Docker operations when appropriate.
126
+ **What runs, in order**
127
+
128
+ | When | What |
129
+ |------|------|
130
+ | **Start of run** | Checks `docker`, daemon (`docker info`), and `docker compose ps`. If those pass, runs **`docker compose down --rmi all --volumes`** — stops the stack and removes images and volumes tied to those services. Happens **before** local file/cache cleanup. |
131
+ | **After dependency reinstall** | If **rebuild** is enabled: **`docker-compose build --pull --no-cache`**. This uses the **`docker-compose`** binary (with a hyphen); it is separate from **`docker compose`**. |
132
+ | **If rebuild succeeded** | **`docker compose up -d`** — starts the stack in the background. |
133
+
134
+ **`rebuild: false`:** still runs the teardown row when Docker mode is on; skips reinstall and skips rebuild + `up`.
135
+
136
+ **`--test`:** only prints what it would run; nothing above executes.
137
+
138
+ **Edge case:** If teardown hits trouble (e.g. `docker compose ps` fails) but Docker wasn’t skipped entirely, rebuild and `up` may still run. If Docker is skipped completely (no CLI, daemon down, no matching files, etc.), rebuild and `up` are skipped too.
128
139
 
129
140
  ---
130
141
 
@@ -138,12 +149,14 @@ Install torch-it globally to run it from anywhere:
138
149
  npm install -g torch-it
139
150
  ```
140
151
 
141
- Then, in your project root,simply run:
152
+ Then, in your project root, simply run:
142
153
 
143
154
  ```bash
144
155
  torch-it
145
156
  ```
146
157
 
158
+ In an interactive terminal, `torch-it` prints the same cleanup preview as `--config` and asks you to confirm (**Yes** / **No**, or **y** / **n**) before it removes anything or touches Docker. Non-interactive environments (no TTY), `--test` dry runs, and **`--yes`** or **`-y`** skip that prompt.
159
+
147
160
  For per-project customisation, create a `torchrc.json` file in your project root (see Customization section below) or use command line flags (see Command Line Options section below).
148
161
 
149
162
  ### Per-Project Installation (Alternative)
@@ -176,9 +189,19 @@ Or directly:
176
189
  npx torch-it
177
190
  ```
178
191
 
192
+ ### Confirmation prompt
193
+
194
+ Before destructive steps, `torch-it` shows effective settings and the files/directories that would be removed (same detail as `--config`), then asks **Continue? Type Yes or No (y/n):**. Answer **yes** or **y** to proceed; anything else cancels the run.
195
+
196
+ This prompt is skipped when:
197
+
198
+ - You pass **`--yes`** or **`-y`** (for CI, scripts, or automation).
199
+ - You use **`--test`** (dry run; nothing is changed).
200
+ - Standard input is **not a TTY** (for example some CI runners), so the tool proceeds without blocking.
201
+
179
202
  ### Dry Run (`--test`)
180
203
 
181
- Use `--test` to preview what `torch-it` would do without deleting directories, cleaning caches, installing dependencies, or changing Docker resources. Results are saved to the `torch-it.log` file.
204
+ Use `--test` to preview what `torch-it` would do without deleting directories, cleaning caches, installing dependencies, or changing Docker resources. Dry run does not show the interactive confirmation prompt.
182
205
 
183
206
  ```bash
184
207
  torch-it --test
@@ -210,7 +233,7 @@ For project-level customization, create a local `torchrc.json` file in your proj
210
233
  {
211
234
  "customPaths": ["apps/web/.next", "services/api/tmp", ".turbo/cache", "coverage-final.json"],
212
235
  "protectedPaths": ["important-data/", "config/production.json"],
213
- "dockerMode": true,
236
+ "dockerMode": false,
214
237
  "rebuild": true,
215
238
  "logfile": true
216
239
  }
@@ -218,7 +241,7 @@ For project-level customization, create a local `torchrc.json` file in your proj
218
241
 
219
242
  - `customPaths`: Array of additional directories and files to remove during cleanup. Supports both directories and files. torch-it will remove these in the same cleanup pass as the built-in targets.
220
243
  - `protectedPaths`: Array of directories and files to skip during cleanup. These paths will be preserved even if they match built-in or custom cleanup targets.
221
- - `dockerMode`: Boolean flag to enable/disable Docker operations. Set to `false` to skip all Docker cleanup, rebuild, and launch steps. Defaults to `true`.
244
+ - `dockerMode`: Boolean flag to enable/disable Docker operations. Set to `true` to run Docker cleanup, rebuild, and launch when compose/Dockerfile files exist. Defaults to `false`.
222
245
  - `rebuild`: Boolean flag to enable/disable rebuild operations. Set to `false` to skip both **package manager dependency installation** and **Docker rebuild/launch** while still performing cleanup. Defaults to `true`.
223
246
  - `logfile`: Boolean flag to enable or disable writing runtime output to `torch-it.log`. Set to `true` to enable file logging. Defaults to `false`.
224
247
 
@@ -229,7 +252,7 @@ For project-level customization, create a local `torchrc.json` file in your proj
229
252
  You can override `torchrc.json` settings directly from the command line using flags. This is useful for one-off runs or CI/CD pipelines.
230
253
 
231
254
  ```bash
232
- torch-it --dockerMode=false --rebuild=false --customPaths=["temp/","logs/"]
255
+ torch-it --yes --rebuild=false --customPaths=["temp/","logs/"]
233
256
  ```
234
257
 
235
258
  All configuration options can be overridden using `--optionName=value` syntax. For arrays and objects, use JSON syntax:
@@ -238,8 +261,9 @@ All configuration options can be overridden using `--optionName=value` syntax. F
238
261
  - `--version, -v` - Show version information and exit
239
262
  - `--config` - Show current configuration and exit
240
263
  - `--test` - Run in dry-run mode (preview changes without executing)
264
+ - `--yes`, `-y` - Skip the interactive confirmation prompt (auto-confirm)
241
265
  - `--customPaths=["path1","path2"]`
242
- - `--dockerMode=false`
266
+ - `--dockerMode=true` - Enable Docker steps when Docker files are present (`false` is the default)
243
267
  - `--rebuild=false`
244
268
  - `--logfile=true`
245
269
 
@@ -262,10 +286,7 @@ This file should be ignored by git to avoid accidental commits. Add this to your
262
286
 
263
287
  ## Troubleshooting
264
288
 
265
- - If you see errors related to Docker, check:
266
- 1. Is Docker installed and running?
267
- 2. Does your project have Docker configuration files?
268
- 3. Are your Docker configuration files valid?
289
+ - **Docker:** From the project root, does **`docker compose ps`** work? Is the **`docker-compose`** (hyphen) CLI on your PATH for rebuilds? Is the daemon up (`docker info`)?
269
290
  - If you see errors about missing `package.json`, initialize your project with `npm init -y` or add your project files.
270
291
  - For detailed information about any failures, check the `torch-it.log` file.
271
292
 
package/dist/torch-it.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var De=Object.create;var Y=Object.defineProperty;var Ee=Object.getOwnPropertyDescriptor;var Te=Object.getOwnPropertyNames;var _e=Object.getPrototypeOf,Se=Object.prototype.hasOwnProperty;var Oe=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var xe=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of Te(t))!Se.call(e,r)&&r!==n&&Y(e,r,{get:()=>t[r],enumerable:!(s=Ee(t,r))||s.enumerable});return e};var g=(e,t,n)=>(n=e!=null?De(_e(e)):{},xe(t||!e||!e.__esModule?Y(n,"default",{value:e,enumerable:!0}):n,e));var le=Oe((lo,Ae)=>{Ae.exports={name:"torch-it",version:"2.5.4",description:"CLI to reset, clean, and rebuild Node.js project environments.",keywords:["cleanup","cli","docker","node"],homepage:"https://github.com/piyook/torch-it#readme",bugs:{url:"https://github.com/piyook/torch-it/issues"},license:"ISC",author:"",repository:{type:"git",url:"git+https://github.com/piyook/torch-it.git"},bin:{"torch-it":"dist/torch-it.js"},files:["dist","README.md"],type:"commonjs",main:"dist/torch-it.js",scripts:{build:'esbuild src/torch.ts --bundle --outfile=dist/torch-it.js --platform=node --format=cjs --minify --banner:js="#!/usr/bin/env node"',"torch-it":"npm run build && node dist/torch-it.js","torch-it:ts":"ts-node src/torch.ts",lint:"oxlint .","lint:fix":"oxlint . --fix",format:"prettier --check src/**/*.{ts,js,json} tests/**/*.{ts,js,json} package.json package-lock.json .commitlintrc.json","format:write":"prettier --write src/**/*.{ts,js,json} tests/**/*.{ts,js,json} package.json package-lock.json .commitlintrc.json",quality:"npm run lint && npm run format && npm test","validate-branch-name":"validate-branch-name",prepare:"husky",prepublishOnly:"npm run build",test:"tsc --noEmit && vitest run","test:watch":"vitest"},dependencies:{},devDependencies:{"@commitlint/cli":"^20.5.0","@commitlint/config-conventional":"^20.5.0","@types/node":"^25.6.0",esbuild:"^0.28.0",husky:"^9.1.7","lint-staged":"^16.4.0",oxlint:"^1.61.0",prettier:"^3.8.3","ts-node":"^10.9.2",typescript:"^6.0.3","validate-branch-name":"^1.3.2",vitest:"^4.1.5"},"lint-staged":{"*.{ts,tsx,js,jsx,mjs,cjs,json}":["oxlint --fix","prettier --write"]},"validate-branch-name":{pattern:"^(main|dev){1}$|^(feat|fix|hotfix|release|chore)/.+$",errorMsg:"INVALID BRANCH NAME: use format 'feat|fix|hotfix|release|core/your-branch-name'"}}});var D=(e,t)=>n=>`\x1B[${e}m${n}\x1B[${t}m`,l={BOLD:D("1","22"),CYAN:D("36","39"),GREEN:D("32","39"),RED:D("31","39"),YELLOW:D("33","39"),PURPLE:D("35","39"),RESET:e=>`\x1B[0m${e}`},a={INFO:"\u{1F525}",SUCCESS:"\u2705",FAIL:"\u274C",EXCLAMATION:"\u2757",WARN:"\u26A0\uFE0F",ROCKET:"\u{1F525}",CLEAN:"\u{1F525}",PHOENIX:"\u{1F525}",BUILD:"\u{1F528}",TARGET:"\u{1F525}",CELEBRATE:"\u{1F525}",STARS:"\u2728",BOX:"\u{1F4E6}",CLIPBOARD:"\u{1F4CB}",DOCKER:"\u{1F433}"};var j=g(require("fs")),U=!0;function $e(e){let t=new RegExp("\x1B\\[[0-9;]*m","g");return e.replace(t,"")}var E=e=>{U=e},q=()=>{U&&j.default.writeFileSync("torch-it.log","")},$=e=>{if(!U)return;let t=$e(e).replace(/^\n/,""),n=new Date().toISOString();j.default.appendFileSync("torch-it.log",`[${n}] ${t}
3
- `)};function o(e,t){let n;switch(t){case"info":n=`${l.CYAN(a.INFO)} ${l.BOLD(e)}${l.RESET("")}`;break;case"success":n=`${l.GREEN(a.SUCCESS)} ${e}${l.RESET("")}`;break;case"warn":n=`${l.YELLOW(a.WARN)} ${e}${l.RESET("")}`;break;case"fail":n=`${l.RED(a.FAIL)} ${e}${l.RESET("")}`;break;case"step":n=`
4
- ${l.PURPLE("\u25B6")} ${l.BOLD(e)}${l.RESET("")}`;break;default:n=e}console.log(n),$(n)}function V(){v([` ${a.TARGET} TORCH LIT ${a.ROCKET}`],l.PURPLE);let e=`
2
+ "use strict";var Se=Object.create;var q=Object.defineProperty;var Oe=Object.getOwnPropertyDescriptor;var xe=Object.getOwnPropertyNames;var ve=Object.getPrototypeOf,Pe=Object.prototype.hasOwnProperty;var $e=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var Ae=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of xe(t))!Pe.call(e,s)&&s!==n&&q(e,s,{get:()=>t[s],enumerable:!(r=Oe(t,s))||r.enumerable});return e};var m=(e,t,n)=>(n=e!=null?Se(ve(e)):{},Ae(t||!e||!e.__esModule?q(n,"default",{value:e,enumerable:!0}):n,e));var pe=$e((ho,Me)=>{Me.exports={name:"torch-it",version:"2.6.0",description:"CLI to reset, clean, and rebuild Node.js project environments.",keywords:["cleanup","cli","docker","node"],homepage:"https://github.com/piyook/torch-it#readme",bugs:{url:"https://github.com/piyook/torch-it/issues"},license:"ISC",author:"",repository:{type:"git",url:"git+https://github.com/piyook/torch-it.git"},bin:{"torch-it":"dist/torch-it.js"},files:["dist","README.md"],type:"commonjs",main:"dist/torch-it.js",scripts:{build:'esbuild src/torch.ts --bundle --outfile=dist/torch-it.js --platform=node --format=cjs --minify --banner:js="#!/usr/bin/env node"',"torch-it":"npm run build && node dist/torch-it.js","torch-it:ts":"ts-node src/torch.ts",lint:"oxlint .","lint:fix":"oxlint . --fix",format:"prettier --check src/**/*.{ts,js,json} tests/**/*.{ts,js,json} package.json package-lock.json .commitlintrc.json","format:write":"prettier --write src/**/*.{ts,js,json} tests/**/*.{ts,js,json} package.json package-lock.json .commitlintrc.json",quality:"npm run lint && npm run format && npm test","validate-branch-name":"validate-branch-name",prepare:"husky",prepublishOnly:"npm run build",test:"tsc --noEmit && vitest run","test:watch":"vitest"},dependencies:{},devDependencies:{"@commitlint/cli":"^20.5.0","@commitlint/config-conventional":"^20.5.0","@types/node":"^25.6.0",esbuild:"^0.28.0",husky:"^9.1.7","lint-staged":"^16.4.0",oxlint:"^1.61.0",prettier:"^3.8.3","ts-node":"^10.9.2",typescript:"^6.0.3","validate-branch-name":"^1.3.2",vitest:"^4.1.5"},"lint-staged":{"*.{ts,tsx,js,jsx,mjs,cjs,json}":["oxlint --fix","prettier --write"]},"validate-branch-name":{pattern:"^(main|dev){1}$|^(feat|fix|hotfix|release|chore)/.+$",errorMsg:"INVALID BRANCH NAME: use format 'feat|fix|hotfix|release|core/your-branch-name'"}}});var T=(e,t)=>n=>`\x1B[${e}m${n}\x1B[${t}m`,f={BOLD:T("1","22"),CYAN:T("36","39"),GREEN:T("32","39"),RED:T("31","39"),YELLOW:T("33","39"),PURPLE:T("35","39"),RESET:e=>`\x1B[0m${e}`},a={INFO:"\u{1F525}",SUCCESS:"\u2705",FAIL:"\u274C",EXCLAMATION:"\u2757",WARN:"\u26A0\uFE0F",ROCKET:"\u{1F525}",CLEAN:"\u{1F525}",PHOENIX:"\u{1F525}",BUILD:"\u{1F528}",TARGET:"\u{1F525}",CELEBRATE:"\u{1F525}",STARS:"\u2728",BOX:"\u{1F4E6}",CLIPBOARD:"\u{1F4CB}",DOCKER:"\u{1F433}"};var H=m(require("fs")),B=!0;function Ie(e){let t=new RegExp("\x1B\\[[0-9;]*m","g");return e.replace(t,"")}var E=e=>{B=e},X=()=>{B&&H.default.writeFileSync("torch-it.log","")},P=e=>{if(!B)return;let t=Ie(e).replace(/^\n/,""),n=new Date().toISOString();H.default.appendFileSync("torch-it.log",`[${n}] ${t}
3
+ `)};function o(e,t){let n;switch(t){case"info":n=`${f.CYAN(a.INFO)} ${f.BOLD(e)}${f.RESET("")}`;break;case"success":n=`${f.GREEN(a.SUCCESS)} ${e}${f.RESET("")}`;break;case"warn":n=`${f.YELLOW(a.WARN)} ${e}${f.RESET("")}`;break;case"fail":n=`${f.RED(a.FAIL)} ${e}${f.RESET("")}`;break;case"step":n=`
4
+ ${f.PURPLE("\u25B6")} ${f.BOLD(e)}${f.RESET("")}`;break;default:n=e}console.log(n),P(n)}function J(){$([` ${a.TARGET} TORCH LIT ${a.ROCKET}`],f.PURPLE);let e=`
5
5
  ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) )
6
6
  (( (( (( (( (( (( (( (( (( (( (( (( (( ((
7
7
  ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) )
@@ -12,7 +12,7 @@ ${l.PURPLE("\u25B6")} ${l.BOLD(e)}${l.RESET("")}`;break;default:n=e}console.log(
12
12
  | _ \\| | | | |_) | \\| || || \\| | | _
13
13
  | |_) | |_| | _ <| |\\ || || |\\ | |_| |
14
14
  |____/ \\___/|_| \\_\\_| \\_|___|_| \\_|\\____|
15
- `;console.log(e),$(e)}function J(){console.log(""),v([` ${a.PHOENIX} RISING FROM THE ASHES ${a.PHOENIX}`],l.PURPLE)}function X(e){let t=new RegExp("\x1B\\[[0-9;]*m","g");return e.replace(t,"").length}function v(e,t=l.GREEN){let n=Math.max(56,...e.map(r=>X(r))),s=t("\u2550".repeat(n));console.log(t("\u2554"+s+"\u2557")),e.forEach(r=>{if($(r),r.trim()==="")console.log(t("\u2551"+" ".repeat(n)+"\u2551"));else{let f=n-X(r);console.log(t("\u2551"+r+" ".repeat(f)+"\u2551"))}}),console.log(t("\u255A"+s+"\u255D"))}var w=g(require("fs"));var P=["node_modules","dist","build",".svelte-kit",".svelte",".next",".nuxt","out",".output",".vercel",".netlify",".astro",".angular",".angular/cache",".solid",".docusaurus",".vite",".cache",".parcel-cache",".webpack",".rollup.cache",".rpt2_cache",".swc",".eslintcache",".stylelintcache",".sass-cache",".tmp","tmp","temp","coverage",".nyc_output","storybook-static",".storybook-out",".turbo",".rush",".firebase",".serverless","android/.gradle","android/build","android/app/build","ios/Pods","ios/build",".expo",".expo-shared","lib","es","cjs","umd",".remix",".qwik",".nitro",".wrangler",".amplify",".sst",".babel-cache",".cache-loader","jspm_packages",".typings"],A=["*.log","*.tgz","*.tar.gz","tsconfig.tsbuildinfo"],I=[".pnpm-store",".pnpm-debug.log",".yarn/cache",".yarn/unplugged",".yarn/install-state.gz",".yarn/build-state.yml",".npm","node_modules/.cache",".yalc",".lerna",".nx/cache",".vite/deps",".turbo","tsconfig.tsbuildinfo",".hardhat",".foundry",".anchor"],L=[];var Q=g(require("fs"));var N=require("child_process"),z=g(require("os"));function h(e,t={}){try{return(0,N.execSync)(e,{stdio:t.silent?"pipe":"inherit"}),!0}catch{return t.silent||o(`Command failed: ${e}`,"fail"),!1}}function u(e){try{return z.platform()==="win32"?(0,N.execSync)(`where ${e}`,{stdio:"ignore"}):(0,N.execSync)(`command -v ${e}`,{stdio:"ignore"}),!0}catch{return!1}}var F={npm:{name:"npm",lockFile:"package-lock.json",installCommand:"npm install",cacheCleanCommand:"npm cache clean --force"},yarn:{name:"yarn",lockFile:"yarn.lock",installCommand:"yarn install",cacheCleanCommand:"yarn cache clean"},pnpm:{name:"pnpm",lockFile:"pnpm-lock.yaml",installCommand:"pnpm install",cacheCleanCommand:"pnpm store prune"}};function H(){for(let e of["pnpm","yarn","npm"])if(Q.existsSync(F[e].lockFile)&&u(e))return e;for(let e of["npm","yarn","pnpm"])if(u(e))return e;return null}function Z(e){let t=process.env.TORCH_DRY_RUN==="1",n=F[e],s=e===H()?`Using ${e} (detected ${n.lockFile})...`:`Using ${e} (fallback)...`;return o(s,"step"),t||h(n.installCommand)?(o(`Dependencies ${t?"would be installed":"installed successfully"} with ${e}`,"success"),!0):(o(`${e} install failed`,"fail"),!1)}function ee(e){let t=process.env.TORCH_DRY_RUN==="1",n=F[e];return t||h(n.cacheCleanCommand)?(o(t?`Dry-run: would clean ${e} cache`:`${e} cache cleaned`,"success"),!0):!1}function oe(){return Object.keys(F).filter(u)}var R={customPaths:[],customDirs:[],customFiles:[],protectedPaths:[],dockerMode:!0,logfile:!1,rebuild:!0};var m=g(require("fs")),te=g(require("path"));function ne(e){let{isDryRun:t,protectedPaths:n}=e,s=0;return{removedCount:()=>s,cleanupTarget:r=>{if(m.existsSync(r)){o(`${t?"Would remove":"Removing"} ${r}...`,"step");try{t||m.rmSync(r,{recursive:!0,force:!0}),o(`${r} ${t?"marked for removal (dry-run)":"removed"}`,"success"),s++}catch{o(`Failed to remove ${r}`,"fail")}}},cleanupFile:r=>{if(m.existsSync(r)&&m.statSync(r).isFile()&&!n.some(d=>r===d||r.startsWith(d+"/"))){o(`${t?"Would remove":"Removing"} ${r}...`,"step");try{t||m.unlinkSync(r),o(`${r} ${t?"marked for removal (dry-run)":"removed"}`,"success"),s++}catch{o(`Failed to remove ${r}`,"fail")}}},isPathProtected:r=>n.some(f=>r===f||r.startsWith(f+"/"))}}function B(e,t){return e.filter(n=>!t.some(s=>n===s||n.startsWith(s+"/")))}function re(e,t){try{let n=m.readdirSync(".",{withFileTypes:!0}).filter(s=>s.name.match(e.replace("*",".*"))).map(s=>s.name);for(let s of n){let r=te.join(".",s);t.cleanupFile(r)}}catch(n){o(`Failed to process pattern ${e}: ${n}`,"warn")}}var ve=e=>{let t={};for(let n of e){if(!n.startsWith("--"))continue;let[s,r]=n.slice(2).split("=",2);if(!(!s||!r))try{let f=JSON.parse(r);t[s]=f}catch{r==="true"?t[s]=!0:r==="false"?t[s]=!1:t[s]=r}}return t},Pe=()=>{let e="torchrc.json";if(!w.existsSync(e))return{};try{return JSON.parse(w.readFileSync(e,"utf8"))}catch{return o("Invalid torchrc.json (must be valid JSON) - skipping custom config","warn"),{}}},O=()=>{let e=Pe();return{customPaths:e.customPaths??R.customPaths,customDirs:e.customDirs??R.customDirs,customFiles:e.customFiles??R.customFiles,protectedPaths:e.protectedPaths??R.protectedPaths,dockerMode:e.dockerMode??R.dockerMode,logfile:e.logfile??R.logfile,rebuild:e.rebuild??R.rebuild}};var T=(e=[])=>{let t=O(),n=ve(e);return{...t,...n}},K=()=>{let e=O();return[...e.customPaths,...e.customDirs,...e.customFiles].filter(n=>typeof n=="string").map(n=>n.trim()).filter(n=>n.length>0)},se=()=>{let e=process.env.TORCH_DRY_RUN==="1",t=O(),n=K(),s=t.protectedPaths,r=[...new Set([...P,...I,...L])],f=[...new Set(n)],d=[...A],_=B(r,s),S=B(f,s),C=ne({isDryRun:e,protectedPaths:s});o("Scanning for build artifacts and cache directories...","step"),_.forEach(C.cleanupTarget),o("Scanning for log files and temporary files...","step");for(let i of d)i.includes("*")?re(i,C):C.cleanupTarget(i);S.length>0&&(o("Deleting user defined custom directories and files","step"),S.forEach(C.cleanupTarget));let b=r.length-_.length+(f.length-S.length);b>0&&o(`Skipped ${b} protected path(s) from torchrc.json`,"info");let y=C.removedCount();return y===0?(o("No build artifacts or cache directories found (project already clean)","info"),!1):(o(`Removed ${y} build/cache directories`,"success"),!0)},ie=()=>{let e=oe(),t=!1;for(let n of e)ee(n)&&(t=!0);return t||o("No package manager caches cleaned (tools not available)","info"),t};var ae=()=>{o(`
15
+ `;console.log(e),P(e)}function z(){console.log(""),$([` ${a.PHOENIX} RISING FROM THE ASHES ${a.PHOENIX}`],f.PURPLE)}function V(e){let t=new RegExp("\x1B\\[[0-9;]*m","g");return e.replace(t,"").length}function $(e,t=f.GREEN){let n=Math.max(56,...e.map(s=>V(s))),r=t("\u2550".repeat(n));console.log(t("\u2554"+r+"\u2557")),e.forEach(s=>{if(P(s),s.trim()==="")console.log(t("\u2551"+" ".repeat(n)+"\u2551"));else{let c=n-V(s);console.log(t("\u2551"+s+" ".repeat(c)+"\u2551"))}}),console.log(t("\u255A"+r+"\u255D"))}var M=m(require("fs"));var A=["node_modules","dist","build",".svelte-kit",".svelte",".next",".nuxt","out",".output",".vercel",".netlify",".astro",".angular",".angular/cache",".solid",".docusaurus",".vite",".cache",".parcel-cache",".webpack",".rollup.cache",".rpt2_cache",".swc",".eslintcache",".stylelintcache",".sass-cache",".tmp","tmp","temp","coverage",".nyc_output","storybook-static",".storybook-out",".turbo",".rush",".firebase",".serverless","android/.gradle","android/build","android/app/build","ios/Pods","ios/build",".expo",".expo-shared","lib","es","cjs","umd",".remix",".qwik",".nitro",".wrangler",".amplify",".sst",".babel-cache",".cache-loader","jspm_packages",".typings"],I=["*.log","*.tgz","*.tar.gz","tsconfig.tsbuildinfo"],N=[".pnpm-store",".pnpm-debug.log",".yarn/cache",".yarn/unplugged",".yarn/install-state.gz",".yarn/build-state.yml",".npm","node_modules/.cache",".yalc",".lerna",".nx/cache",".vite/deps",".turbo","tsconfig.tsbuildinfo",".hardhat",".foundry",".anchor"],L=[];var Z=m(require("fs"));var w=require("child_process"),Q=m(require("os"));function h(e,t={}){try{return(0,w.execSync)(e,{stdio:t.silent?"pipe":"inherit"}),!0}catch{return t.silent||o(`Command failed: ${e}`,"fail"),!1}}function u(e){try{return Q.platform()==="win32"?(0,w.execSync)(`where ${e}`,{stdio:"ignore"}):(0,w.execSync)(`command -v ${e}`,{stdio:"ignore"}),!0}catch{return!1}}var F={npm:{name:"npm",lockFile:"package-lock.json",installCommand:"npm install",cacheCleanCommand:"npm cache clean --force"},yarn:{name:"yarn",lockFile:"yarn.lock",installCommand:"yarn install",cacheCleanCommand:"yarn cache clean"},pnpm:{name:"pnpm",lockFile:"pnpm-lock.yaml",installCommand:"pnpm install",cacheCleanCommand:"pnpm store prune"}};function K(){for(let e of["pnpm","yarn","npm"])if(Z.existsSync(F[e].lockFile)&&u(e))return e;for(let e of["npm","yarn","pnpm"])if(u(e))return e;return null}function ee(e){let t=process.env.TORCH_DRY_RUN==="1",n=F[e],r=e===K()?`Using ${e} (detected ${n.lockFile})...`:`Using ${e} (fallback)...`;return o(r,"step"),t||h(n.installCommand)?(o(`Dependencies ${t?"would be installed":"installed successfully"} with ${e}`,"success"),!0):(o(`${e} install failed`,"fail"),!1)}function oe(e){let t=process.env.TORCH_DRY_RUN==="1",n=F[e];return t||h(n.cacheCleanCommand)?(o(t?`Dry-run: would clean ${e} cache`:`${e} cache cleaned`,"success"),!0):!1}function te(){return Object.keys(F).filter(u)}var y={customPaths:[],customDirs:[],customFiles:[],protectedPaths:[],dockerMode:!1,logfile:!1,rebuild:!0};var g=m(require("fs")),ne=m(require("path"));function re(e){let{isDryRun:t,protectedPaths:n}=e,r=0;return{removedCount:()=>r,cleanupTarget:s=>{if(g.existsSync(s)){o(`${t?"Would remove":"Removing"} ${s}...`,"step");try{t||g.rmSync(s,{recursive:!0,force:!0}),o(`${s} ${t?"marked for removal (dry-run)":"removed"}`,"success"),r++}catch{o(`Failed to remove ${s}`,"fail")}}},cleanupFile:s=>{if(g.existsSync(s)&&g.statSync(s).isFile()&&!n.some(R=>s===R||s.startsWith(R+"/"))){o(`${t?"Would remove":"Removing"} ${s}...`,"step");try{t||g.unlinkSync(s),o(`${s} ${t?"marked for removal (dry-run)":"removed"}`,"success"),r++}catch{o(`Failed to remove ${s}`,"fail")}}},isPathProtected:s=>n.some(c=>s===c||s.startsWith(c+"/"))}}function Y(e,t){return e.filter(n=>!t.some(r=>n===r||n.startsWith(r+"/")))}function se(e,t){try{let n=g.readdirSync(".",{withFileTypes:!0}).filter(r=>r.name.match(e.replace("*",".*"))).map(r=>r.name);for(let r of n){let s=ne.join(".",r);t.cleanupFile(s)}}catch(n){o(`Failed to process pattern ${e}: ${n}`,"warn")}}var Ne=e=>{let t={};for(let n of e){if(!n.startsWith("--"))continue;let[r,s]=n.slice(2).split("=",2);if(!(!r||!s))try{let c=JSON.parse(s);t[r]=c}catch{s==="true"?t[r]=!0:s==="false"?t[r]=!1:t[r]=s}}return t},Le=()=>{let e="torchrc.json";if(!M.existsSync(e))return{};try{return JSON.parse(M.readFileSync(e,"utf8"))}catch{return o("Invalid torchrc.json (must be valid JSON) - skipping custom config","warn"),{}}},_=()=>{let e=Le();return{customPaths:e.customPaths??y.customPaths,customDirs:e.customDirs??y.customDirs,customFiles:e.customFiles??y.customFiles,protectedPaths:e.protectedPaths??y.protectedPaths,dockerMode:e.dockerMode??y.dockerMode,logfile:e.logfile??y.logfile,rebuild:e.rebuild??y.rebuild}};var ie=(e=[])=>{let t=_(),n=Ne(e);return{...t,...n}},we=()=>{let e=_();return[...e.customPaths,...e.customDirs,...e.customFiles].filter(n=>typeof n=="string").map(n=>n.trim()).filter(n=>n.length>0)},ae=()=>{let e=process.env.TORCH_DRY_RUN==="1",t=_(),n=we(),r=t.protectedPaths,s=[...new Set([...A,...N,...L])],c=[...new Set(n)],R=[...I],d=Y(s,r),S=Y(c,r),k=re({isDryRun:e,protectedPaths:r});o("Scanning for build artifacts and cache directories...","step"),d.forEach(k.cleanupTarget),o("Scanning for log files and temporary files...","step");for(let b of R)b.includes("*")?se(b,k):k.cleanupTarget(b);S.length>0&&(o("Deleting user defined custom directories and files","step"),S.forEach(k.cleanupTarget));let O=s.length-d.length+(c.length-S.length);O>0&&o(`Skipped ${O} protected path(s) from torchrc.json`,"info");let D=k.removedCount();return D===0?(o("No build artifacts or cache directories found (project already clean)","info"),!1):(o(`Removed ${D} build/cache directories`,"success"),!0)},ce=()=>{let e=te(),t=!1;for(let n of e)oe(n)&&(t=!0);return t||o("No package manager caches cleaned (tools not available)","info"),t};var le=()=>{o(`
16
16
  \u{1F525} Torch It - Project Environment Reset Tool
17
17
 
18
18
  USAGE:
@@ -23,7 +23,8 @@ OPTIONS:
23
23
  --version, -v Show version information and exit
24
24
  --config Show current configuration and exit
25
25
  --test Run in dry-run mode (preview changes without executing)
26
- --dockerMode=<bool> Enable/disable Docker operations (default: true)
26
+ --yes, -y Skip the confirmation prompt (same as answering yes)
27
+ --dockerMode=<bool> Enable/disable Docker operations (default: false)
27
28
  --rebuild=<bool> Enable/disable rebuild operations (default: true)
28
29
  --logfile=<bool> Enable/disable file logging (default: false)
29
30
  --customPaths=<array> Additional paths to remove during cleanup
@@ -34,8 +35,9 @@ EXAMPLES:
34
35
  torch-it --version # Show version information
35
36
  torch-it --config # Show current configuration
36
37
  torch-it --test # Preview what would be done
38
+ torch-it --yes # No confirmation prompt (same as -y)
37
39
  torch-it --rebuild=false # Clean only, don't rebuild
38
- torch-it --dockerMode=false # Skip Docker operations
40
+ torch-it --dockerMode=true # Enable Docker cleanup/rebuild when configured
39
41
  torch-it --logfile=true # Enable file logging
40
42
  torch-it --customPaths=["temp/","logs/"] # Clean additional paths
41
43
 
@@ -45,18 +47,20 @@ CONFIGURATION:
45
47
  {
46
48
  "customPaths": ["apps/web/.next", "coverage-final.json"],
47
49
  "protectedPaths": ["important-data/"],
48
- "dockerMode": true,
50
+ "dockerMode": false,
49
51
  "rebuild": true,
50
52
  "logfile": false
51
53
  }
52
54
 
53
55
  For more information, visit: https://github.com/piyook/torch-it
54
- `.trim(),"info")};var p=g(require("fs"));var ce=()=>{let e=O(),t=K(),n=e.protectedPaths;o("=".repeat(60),"info"),o("TORCH-IT CONFIGURATION","info"),o("=".repeat(60),"info"),o(`
56
+ `.trim(),"info")};var p=m(require("fs"));function Fe(e){return[...e.customPaths,...e.customDirs,...e.customFiles].filter(t=>typeof t=="string").map(t=>t.trim()).filter(t=>t.length>0)}function G(e,t){let n=t?.includeHelpFooter!==!1,r=Fe(e),s=e.protectedPaths;o("=".repeat(60),"info"),o("TORCH-IT CONFIGURATION","info"),o("=".repeat(60),"info"),o(`
55
57
  BASIC SETTINGS:`,"info"),o(` Docker Mode: ${e.dockerMode}`,"info"),o(` Rebuild: ${e.rebuild}`,"info"),o(` Logfile: ${e.logfile}`,"info"),o(`
56
- PACKAGE MANAGER DETECTION:`,"info");let s=[];p.existsSync("package-lock.json")&&u("npm")?s.push("npm (package-lock.json)"):u("npm")&&s.push("npm (fallback)"),p.existsSync("yarn.lock")&&u("yarn")?s.push("yarn (yarn.lock)"):u("yarn")&&s.push("yarn (fallback)"),p.existsSync("pnpm-lock.yaml")&&u("pnpm")?s.push("pnpm (pnpm-lock.yaml)"):u("pnpm")&&s.push("pnpm (fallback)"),s.length>0?s.forEach(i=>o(` ${i}`,"info")):o(" No package manager detected","warn"),o(`
57
- DOCKER DETECTION:`,"info");let f=["Dockerfile","docker-compose.yml","docker-compose.yaml"].filter(i=>p.existsSync(i));f.length>0?f.forEach(i=>o(` ${i}`,"info")):o(" No Docker configuration found","info"),o(`
58
- FILES/DIRECTORIES THAT WILL BE DELETED:`,"info");let _=[...new Set([...P,...I,...L,...A])].filter(i=>!n.some(c=>i===c||i.startsWith(c+"/"))),S=t.filter(i=>!n.some(c=>i===c||i.startsWith(c+"/"))),C=_.filter(i=>!i.includes("*")&&p.existsSync(i)),b=_.filter(i=>i.includes("*")),y=S.filter(i=>p.existsSync(i));C.length>0&&(o(" Default targets:","info"),C.forEach(i=>{let c=p.statSync(i).isDirectory()?"DIR":"FILE";o(` ${i} (${c})`,"info")})),b.length>0&&(o(" Glob patterns:","info"),b.forEach(i=>{try{let c=p.readdirSync(".",{withFileTypes:!0}).filter(k=>k.name.match(i.replace("*",".*"))).map(k=>k.name);c.length>0?(o(` ${i} (matches ${c.length} file${c.length===1?"":"s"}):`,"info"),c.forEach(k=>{o(` ${k} (FILE)`,"info")})):o(` ${i} (no matches)`,"info")}catch(c){o(` ${i} (error: ${c})`,"warn")}})),y.length>0&&(o(" Custom targets:","info"),y.forEach(i=>{let c=p.statSync(i).isDirectory()?"DIR":"FILE";o(` ${i} (${c})`,"info")})),C.length===0&&b.length===0&&y.length===0&&o(" No targets found (nothing to delete)","info"),n.length>0?(o(`
59
- PROTECTED PATHS (will NOT be deleted):`,"info"),n.forEach(i=>{let c=p.existsSync(i),k=c&&p.statSync(i).isDirectory()?"DIR":"FILE",x=c?`(${k})`:"(not found)";o(` ${i} ${x}`,"info")})):o(`
60
- PROTECTED PATHS: None`,"info"),t.length>0&&(o(`
61
- CUSTOM PATHS FROM torchrc.json:`,"info"),t.forEach(i=>{let c=p.existsSync(i),k=c&&p.statSync(i).isDirectory()?"DIR":"FILE",x=c?`(${k})`:"(not found)";o(` ${i} ${x}`,"info")})),o(`
62
- `+"=".repeat(60),"info"),o("Use 'torch-it --help' for available options","info"),o("=".repeat(60),"info")};function fe(e){let t=e.includes("--help"),n=e.includes("--version")||e.includes("-v"),s=e.includes("--config"),r=e.includes("--test"),f=e.filter(d=>d!=="--test"&&d!=="--help"&&d!=="--version"&&d!=="-v"&&d!=="--config");return{isHelp:t,isVersion:n,isConfig:s,isDryRun:r,filteredArgs:f}}function pe(e){if(e.isHelp&&(E(!1),ae(),process.exit(0)),e.isVersion){E(!1);let t=le();o(`torch-it v${t.version}`,"info"),process.exit(0)}e.isConfig&&(E(!1),ce(),process.exit(0)),e.isDryRun&&(process.env.TORCH_DRY_RUN="1")}var M=g(require("fs"));function ue(){return M.existsSync("Dockerfile")||M.existsSync("docker-compose.yml")||M.existsSync("docker-compose.yaml")}function de(){if(T().dockerMode===!1)return o("Docker mode disabled in torchrc.json - skipping Docker operations","info"),"NO_DOCKER";let t=process.env.TORCH_DRY_RUN==="1";return ue()?(o("Stopping Docker services and removing all resources...","info"),u("docker")?h("docker info",{silent:!0})?h("docker compose ps",{silent:!0})?t?(o("Dry-run: would run 'docker compose down --rmi all --volumes'","info"),"OK"):h("docker compose down --rmi all --volumes")?(o("Docker services stopped and resources cleaned","success"),"OK"):(o("Docker cleanup encountered issues","warn"),o("Continuing with the rest of the script...","info"),"DOCKER_FAIL"):(o("No Docker Compose services found - skipping Docker cleanup","warn"),o("This is normal if no services were previously running","info"),"DOCKER_FAIL"):(o("Docker daemon is not running - skipping Docker cleanup","warn"),o("You may need to start Docker manually and run cleanup later","info"),"NO_DOCKER"):(o("Docker is not installed - skipping Docker cleanup","warn"),"NO_DOCKER")):(o("No Docker configuration found - skipping Docker operations","info"),"NO_DOCKER")}function me(){let e=T();if(e.dockerMode===!1)return!1;if(e.rebuild===!1)return o("Rebuild disabled in torchrc.json - skipping Docker rebuild","info"),!1;let t=process.env.TORCH_DRY_RUN==="1";return ue()?u("docker")?h("docker info",{silent:!0})?(o("Building Docker resources (this may take a while...)...","step"),console.log(` ${l.YELLOW("\u23F3 Please be patient - pulling fresh images and building...")}`),t?(o("Dry-run: would run 'docker-compose build --pull --no-cache'","info"),!0):h("docker-compose build --pull --no-cache")?!0:(o("Docker build encountered issues - check torch-it.log for details","fail"),!1)):(o("Docker daemon is not running - skipping Docker rebuild","warn"),o("Start Docker manually and run 'docker-compose build --pull --no-cache' later","info"),!1):(o("Docker is not installed - skipping Docker rebuild","warn"),!1):!1}function ge(){if(T().dockerMode===!1)return!1;let t=process.env.TORCH_DRY_RUN==="1";return o("Starting Docker services in detached mode...","step"),t?(o("Dry-run: would run 'docker compose up -d'","info"),!0):h("docker compose up -d")?!0:(o("Failed to start Docker services - check torch-it.log for details","fail"),!1)}var he=()=>{o("Detecting package manager and installing dependencies...","step");let e=H();return e?Z(e):(o("No package manager found (npm/yarn/pnpm). Please install dependencies manually.","fail"),!1)};var Ce=e=>{let t="",n="",s="";e.dockerClean==="NO_DOCKER"?t=`${a.DOCKER} No Docker containers found`:e.dockerClean==="DOCKER_FAIL"&&(t=`${a.FAIL} Failed to remove Docker containers`),e.dockerClean==="OK"&&(e.dockerRebuild?n=`${a.DOCKER} Docker containers rebuilt from scratch`:n=`${a.FAIL} Failed to rebuild Docker containers`,e.dockerLaunch&&e.dockerRebuild?s=`${a.ROCKET} Services running in detached mode`:s=`${a.FAIL} Failed to start Docker containers`);let r=e.buildAndCacheClean&&e.packageManagerClean?`${a.CLEAN} All build artifacts & caches removed`:`${a.FAIL} Build artifacts or cache directories not found`,f=e.dependencyInstall?`${a.BOX} Dependencies freshly installed`:`${a.FAIL} Failed to install dependencies`;console.log(""),v(["\u{1F525} PROJECT SUCCESSFULLY TORCHED! \u{1F525}","",`${r}`,`${f}`,`${t}`,`${n}`,`${s}`,"",e.logfile===!1?`${a.CLIPBOARD} Logging to torch-it.log is disabled; set "logfile": true in torchrc.json to enable it`:`${a.CLIPBOARD} Check torch-it.log for detailed logs`])};function ke(e){let t={dockerClean:"NO_DOCKER",buildAndCacheClean:!1,packageManagerClean:!1,dependencyInstall:!1,dockerRebuild:!1,dockerLaunch:!1,logfile:e.logfile};return o(`${a.CLEAN} DOCKER CLEANUP`,"step"),t.dockerClean=de(),o(`${a.CLEAN} BUILD ARTIFACTS & CACHE CLEANUP`,"step"),t.buildAndCacheClean=se(),o("Cleaning package manager caches...","step"),t.packageManagerClean=ie(),e.rebuild!==!1?(J(),o(`${a.BUILD} DEPENDENCY INSTALLATION`,"step"),t.dependencyInstall=he()):(o("Rebuild disabled - skipping dependency installation","info"),t.dependencyInstall=!1),t.dockerClean!=="NO_DOCKER"&&e.rebuild!==!1?(o(`${a.BUILD} DOCKER REBUILD`,"step"),t.dockerRebuild=me()):t.dockerClean!=="NO_DOCKER"&&e.rebuild===!1&&(o("Rebuild disabled - skipping Docker rebuild","info"),t.dockerRebuild=!1),t.dockerRebuild&&(t.dockerLaunch=ge(),o(`${a.ROCKET} LAUNCH`,"step")),Ce(t),t}var Re=g(require("fs")),be=g(require("path"));function Ie(){return["package.json","yarn.lock","pnpm-lock.yaml","npm-shrinkwrap.json"].some(t=>Re.existsSync(be.join(process.cwd(),t)))}function ye(){Ie()||(o("This directory does not contain a Node.js project.","fail"),o("Please create a Node.js project (with package.json) before using torch-it.","info"),process.exit(1))}var Le=process.argv.slice(2),G=fe(Le);pe(G);var W=T(G.filteredArgs);E(W.logfile);W.logfile&&q();V();ye();G.isDryRun&&o("Running in --test dry-run mode (no files or services will be changed)","warn");ke(W);
58
+ PACKAGE MANAGER DETECTION:`,"info");let c=[];p.existsSync("package-lock.json")&&u("npm")?c.push("npm (package-lock.json)"):u("npm")&&c.push("npm (fallback)"),p.existsSync("yarn.lock")&&u("yarn")?c.push("yarn (yarn.lock)"):u("yarn")&&c.push("yarn (fallback)"),p.existsSync("pnpm-lock.yaml")&&u("pnpm")?c.push("pnpm (pnpm-lock.yaml)"):u("pnpm")&&c.push("pnpm (fallback)"),c.length>0?c.forEach(i=>o(` ${i}`,"info")):o(" No package manager detected","warn"),o(`
59
+ DOCKER DETECTION:`,"info");let d=["Dockerfile","docker-compose.yml","docker-compose.yaml"].filter(i=>p.existsSync(i));d.length>0?d.forEach(i=>o(` ${i}`,"info")):o(" No Docker configuration found","info"),o(`
60
+ FILES/DIRECTORIES THAT WILL BE DELETED:`,"info");let k=[...new Set([...A,...N,...L,...I])].filter(i=>!s.some(l=>i===l||i.startsWith(l+"/"))),O=r.filter(i=>!s.some(l=>i===l||i.startsWith(l+"/"))),D=k.filter(i=>!i.includes("*")&&p.existsSync(i)),b=k.filter(i=>i.includes("*")),x=O.filter(i=>p.existsSync(i));D.length>0&&(o(" Default targets:","info"),D.forEach(i=>{let l=p.statSync(i).isDirectory()?"DIR":"FILE";o(` ${i} (${l})`,"info")})),b.length>0&&(o(" Glob patterns:","info"),b.forEach(i=>{try{let l=p.readdirSync(".",{withFileTypes:!0}).filter(C=>C.name.match(i.replace("*",".*"))).map(C=>C.name);l.length>0?(o(` ${i} (matches ${l.length} file${l.length===1?"":"s"}):`,"info"),l.forEach(C=>{o(` ${C} (FILE)`,"info")})):o(` ${i} (no matches)`,"info")}catch(l){o(` ${i} (error: ${l})`,"warn")}})),x.length>0&&(o(" Custom targets:","info"),x.forEach(i=>{let l=p.statSync(i).isDirectory()?"DIR":"FILE";o(` ${i} (${l})`,"info")})),D.length===0&&b.length===0&&x.length===0&&o(" No targets found (nothing to delete)","info"),s.length>0?(o(`
61
+ PROTECTED PATHS (will NOT be deleted):`,"info"),s.forEach(i=>{let l=p.existsSync(i),C=l&&p.statSync(i).isDirectory()?"DIR":"FILE",v=l?`(${C})`:"(not found)";o(` ${i} ${v}`,"info")})):o(`
62
+ PROTECTED PATHS: None`,"info"),r.length>0&&(o(`
63
+ CUSTOM PATHS:`,"info"),r.forEach(i=>{let l=p.existsSync(i),C=l&&p.statSync(i).isDirectory()?"DIR":"FILE",v=l?`(${C})`:"(not found)";o(` ${i} ${v}`,"info")})),o(`
64
+ `+"=".repeat(60),"info"),n&&(o("Use 'torch-it --help' for available options","info"),o("=".repeat(60),"info"))}var fe=()=>{G(_())};function ue(e){let t=e.includes("--help"),n=e.includes("--version")||e.includes("-v"),r=e.includes("--config"),s=e.includes("--test"),c=e.includes("--yes")||e.includes("-y"),R=e.filter(d=>d!=="--test"&&d!=="--help"&&d!=="--version"&&d!=="-v"&&d!=="--config"&&d!=="--yes"&&d!=="-y");return{isHelp:t,isVersion:n,isConfig:r,isDryRun:s,assumeYes:c,filteredArgs:R}}function de(e){if(e.isHelp&&(E(!1),le(),process.exit(0)),e.isVersion){E(!1);let t=pe();o(`torch-it v${t.version}`,"info"),process.exit(0)}e.isConfig&&(E(!1),fe(),process.exit(0)),e.isDryRun&&(process.env.TORCH_DRY_RUN="1")}var j=m(require("fs"));function me(){return j.existsSync("Dockerfile")||j.existsSync("docker-compose.yml")||j.existsSync("docker-compose.yaml")}function ge(e){if(e.dockerMode===!1)return o("Docker mode disabled - skipping Docker operations","info"),"NO_DOCKER";let t=process.env.TORCH_DRY_RUN==="1";return me()?(o("Stopping Docker services and removing all resources...","info"),u("docker")?h("docker info",{silent:!0})?h("docker compose ps",{silent:!0})?t?(o("Dry-run: would run 'docker compose down --rmi all --volumes'","info"),"OK"):h("docker compose down --rmi all --volumes")?(o("Docker services stopped and resources cleaned","success"),"OK"):(o("Docker cleanup encountered issues","warn"),o("Continuing with the rest of the script...","info"),"DOCKER_FAIL"):(o("No Docker Compose services found - skipping Docker cleanup","warn"),o("This is normal if no services were previously running","info"),"DOCKER_FAIL"):(o("Docker daemon is not running - skipping Docker cleanup","warn"),o("You may need to start Docker manually and run cleanup later","info"),"NO_DOCKER"):(o("Docker is not installed - skipping Docker cleanup","warn"),"NO_DOCKER")):(o("No Docker configuration found - skipping Docker operations","info"),"NO_DOCKER")}function he(e){if(e.dockerMode===!1)return!1;if(e.rebuild===!1)return o("Rebuild disabled - skipping Docker rebuild","info"),!1;let t=process.env.TORCH_DRY_RUN==="1";return me()?u("docker")?h("docker info",{silent:!0})?(o("Building Docker resources (this may take a while...)...","step"),console.log(` ${f.YELLOW("\u23F3 Please be patient - pulling fresh images and building...")}`),t?(o("Dry-run: would run 'docker-compose build --pull --no-cache'","info"),!0):h("docker-compose build --pull --no-cache")?!0:(o("Docker build encountered issues - check torch-it.log for details","fail"),!1)):(o("Docker daemon is not running - skipping Docker rebuild","warn"),o("Start Docker manually and run 'docker-compose build --pull --no-cache' later","info"),!1):(o("Docker is not installed - skipping Docker rebuild","warn"),!1):!1}function Ce(e){if(e.dockerMode===!1)return!1;let t=process.env.TORCH_DRY_RUN==="1";return o("Starting Docker services in detached mode...","step"),t?(o("Dry-run: would run 'docker compose up -d'","info"),!0):h("docker compose up -d")?!0:(o("Failed to start Docker services - check torch-it.log for details","fail"),!1)}var ke=()=>{o("Detecting package manager and installing dependencies...","step");let e=K();return e?ee(e):(o("No package manager found (npm/yarn/pnpm). Please install dependencies manually.","fail"),!1)};var ye=e=>{let t="",n="",r="";e.dockerClean==="NO_DOCKER"?t=`${a.DOCKER} No Docker containers found`:e.dockerClean==="DOCKER_FAIL"&&(t=`${a.FAIL} Failed to remove Docker containers`),e.dockerClean==="OK"&&(e.dockerRebuild?n=`${a.DOCKER} Docker containers rebuilt from scratch`:n=`${a.FAIL} Failed to rebuild Docker containers`,e.dockerLaunch&&e.dockerRebuild?r=`${a.ROCKET} Services running in detached mode`:r=`${a.FAIL} Failed to start Docker containers`);let s=e.buildAndCacheClean&&e.packageManagerClean?`${a.CLEAN} All build artifacts & caches removed`:`${a.FAIL} Build artifacts or cache directories not found`,c=e.dependencyInstall?`${a.BOX} Dependencies freshly installed`:`${a.FAIL} Failed to install dependencies`;console.log(""),$(["\u{1F525} PROJECT SUCCESSFULLY TORCHED! \u{1F525}","",`${s}`,`${c}`,`${t}`,`${n}`,`${r}`,"",e.logfile===!1?`${a.CLIPBOARD} Logging to torch-it.log is disabled; set "logfile": true in torchrc.json to enable it`:`${a.CLIPBOARD} Check torch-it.log for detailed logs`])};var Re=m(require("readline"));function be(e){let t=Re.createInterface({input:process.stdin,output:process.stdout});return new Promise(n=>{t.question(e,r=>{t.close();let s=r.trim().toLowerCase();n(s==="y"||s==="yes")})})}async function De(e,t={}){t.assumeYes===!0||process.env.TORCH_DRY_RUN==="1"||process.stdin.isTTY!==!0||(o(`
65
+ Review the cleanup below. Matching paths and Docker actions (if enabled) will run next.`,"warn"),G(e,{includeHelpFooter:!1}),o(`
66
+ These targets will be removed where they exist. Package caches may be cleared and dependencies reinstalled per your settings.`,"warn"),await be("Continue? Type Yes or No (y/n): ")||(o("Aborted.","info"),process.exit(0)));let r={dockerClean:"NO_DOCKER",buildAndCacheClean:!1,packageManagerClean:!1,dependencyInstall:!1,dockerRebuild:!1,dockerLaunch:!1,logfile:e.logfile};return o(`${a.CLEAN} DOCKER CLEANUP`,"step"),r.dockerClean=ge(e),o(`${a.CLEAN} BUILD ARTIFACTS & CACHE CLEANUP`,"step"),r.buildAndCacheClean=ae(),o("Cleaning package manager caches...","step"),r.packageManagerClean=ce(),e.rebuild!==!1?(z(),o(`${a.BUILD} DEPENDENCY INSTALLATION`,"step"),r.dependencyInstall=ke()):(o("Rebuild disabled - skipping dependency installation","info"),r.dependencyInstall=!1),r.dockerClean!=="NO_DOCKER"&&e.rebuild!==!1?(o(`${a.BUILD} DOCKER REBUILD`,"step"),r.dockerRebuild=he(e)):r.dockerClean!=="NO_DOCKER"&&e.rebuild===!1&&(o("Rebuild disabled - skipping Docker rebuild","info"),r.dockerRebuild=!1),r.dockerRebuild&&(r.dockerLaunch=Ce(e),o(`${a.ROCKET} LAUNCH`,"step")),ye(r),r}var Te=m(require("fs")),Ee=m(require("path"));function je(){return["package.json","yarn.lock","pnpm-lock.yaml","npm-shrinkwrap.json"].some(t=>Te.existsSync(Ee.join(process.cwd(),t)))}function _e(){je()||(o("This directory does not contain a Node.js project.","fail"),o("Please create a Node.js project (with package.json) before using torch-it.","info"),process.exit(1))}var Ue=process.argv.slice(2),U=ue(Ue);de(U);var W=ie(U.filteredArgs);E(W.logfile);W.logfile&&X();J();_e();U.isDryRun&&o("Running in --test dry-run mode (no files or services will be changed)","warn");(async()=>{await De(W,{assumeYes:U.assumeYes})})().catch(e=>{console.error(e),process.exit(1)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "torch-it",
3
- "version": "2.5.4",
3
+ "version": "2.6.0",
4
4
  "description": "CLI to reset, clean, and rebuild Node.js project environments.",
5
5
  "keywords": [
6
6
  "cleanup",