@dimensional-innovations/tool-config 2.0.0 → 3.0.1

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/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  [![npm version](https://img.shields.io/npm/v/@dimensional-innovations/tool-config.svg)](https://www.npmjs.com/package/@dimensional-innovations/tool-config)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
7
  [![Node Version](https://img.shields.io/badge/node-%3E%3D22.12.0-brightgreen.svg)](https://nodejs.org/)
8
- [![Test Coverage](https://img.shields.io/badge/coverage-100%25-brightgreen.svg)](./tests/)
8
+ [![Test Coverage](https://img.shields.io/badge/coverage-96%25-brightgreen.svg)](./tests/)
9
9
 
10
10
  **One package. Five tools. Zero configuration.**
11
11
 
@@ -35,11 +35,13 @@ npm install --save-dev @dimensional-innovations/tool-config
35
35
 
36
36
  - đŸŽ¯ **Zero Configuration** - Auto-detects your framework, environment, and TypeScript
37
37
  - 🧰 **Multi-Tool Support** - ESLint, Prettier, Stylelint, TypeScript, semantic-release in one package
38
- - âš›ī¸ **8+ Frameworks** - React, Vue, Svelte, Solid, Astro, Angular, Vanilla JS, Node.js
38
+ - âš›ī¸ **9 Frameworks** - React, Vue, Svelte, Solid, Astro, Angular, Vanilla JS, Node.js, Electron
39
39
  - đŸ“Ļ **All-In-One** - All plugins and parsers included as dependencies
40
40
  - 🔧 **Customizable** - Override any setting while keeping smart defaults
41
41
  - 🚀 **Modern** - ESLint 9+ flat config, TypeScript with tsgo support (10x faster)
42
- - ✅ **Battle-Tested** - 535 tests with 100% coverage
42
+ - 🔄 **Uninstall Support** - Clean removal with safety checks for modified files
43
+ - đŸŽŦ **Smart Scripts** - Auto-generated `check-all` script runs tools in optimal order
44
+ - ✅ **Battle-Tested** - 556 tests with 96% coverage
43
45
 
44
46
  ## Quick Start
45
47
 
@@ -118,14 +120,17 @@ That's it! The configs will automatically detect your framework and TypeScript s
118
120
  "lint:fix": "eslint --fix .",
119
121
  "prettier": "prettier --check .",
120
122
  "prettier:fix": "prettier --write .",
121
- "style": "stylelint '**/*.css'",
122
- "style:fix": "stylelint '**/*.css' --fix",
123
+ "style": "stylelint '**/*.css' --allow-empty-input",
124
+ "style:fix": "stylelint '**/*.css' --fix --allow-empty-input",
123
125
  "typecheck": "tsc --noEmit",
124
- "typecheck:watch": "tsc --noEmit --watch"
126
+ "typecheck:watch": "tsc --noEmit --watch",
127
+ "check-all": "npm run prettier && npm run style && npm run lint && npm run typecheck"
125
128
  }
126
129
  }
127
130
  ```
128
131
 
132
+ **Tip:** The CLI automatically adds a `check-all` script when you setup multiple tools. This runs all validation tools in the optimal order: formatting → styles → linting → type checking.
133
+
129
134
  ## Supported Frameworks
130
135
 
131
136
  | Framework | ESLint | Prettier | Stylelint | TypeScript | Auto-Detect |
@@ -138,6 +143,7 @@ That's it! The configs will automatically detect your framework and TypeScript s
138
143
  | Angular | ✅ | ✅ | ✅ | ✅ decorators | ✅ |
139
144
  | Vanilla | ✅ | ✅ | ✅ | ✅ browser | ✅ |
140
145
  | Node.js | ✅ | ✅ | N/A | ✅ NodeNext | ✅ |
146
+ | Electron | ✅ | ✅ | N/A | ✅ multi-config | ✅ |
141
147
 
142
148
  **Meta-frameworks**: Next.js (→ React), Nuxt (→ Vue), SvelteKit (→ Svelte)
143
149
 
@@ -174,23 +180,11 @@ await createConfig('eslint', {
174
180
  })
175
181
  ```
176
182
 
177
- **Example - Custom Rules:**
183
+ **Custom rules:**
178
184
 
179
185
  ```javascript
180
186
  export default await createConfig('eslint', {
181
- rules: {
182
- 'no-console': 'off',
183
- 'react/prop-types': 'warn'
184
- }
185
- })
186
- ```
187
-
188
- **Example - Explicit Framework:**
189
-
190
- ```javascript
191
- export default await createConfig('eslint', {
192
- framework: 'vue',
193
- typescript: true
187
+ rules: { 'no-console': 'off' }
194
188
  })
195
189
  ```
196
190
 
@@ -199,20 +193,9 @@ export default await createConfig('eslint', {
199
193
  ```javascript
200
194
  createConfig('prettier', {
201
195
  framework: 'auto',
202
- // Override any Prettier option
196
+ printWidth: 100, // Override any Prettier option
203
197
  semi: false,
204
- singleQuote: true,
205
- printWidth: 100
206
- })
207
- ```
208
-
209
- **Example - Custom Settings:**
210
-
211
- ```javascript
212
- export default createConfig('prettier', {
213
- printWidth: 120,
214
- tabWidth: 4,
215
- trailingComma: 'all'
198
+ singleQuote: true
216
199
  })
217
200
  ```
218
201
 
@@ -221,57 +204,29 @@ export default createConfig('prettier', {
221
204
  ```javascript
222
205
  createConfig('stylelint', {
223
206
  framework: 'auto',
224
- cssType: 'auto', // 'auto' | 'scss' | 'css' | { preprocessor, tailwind, modules }
207
+ cssType: 'auto', // 'auto' | 'scss' | 'css'
208
+ cssType: { preprocessor: 'scss', tailwind: true }, // Or object
225
209
  rules: {} // Custom rule overrides
226
210
  })
227
211
  ```
228
212
 
229
- **Example - SCSS + Tailwind:**
230
-
231
- ```javascript
232
- export default createConfig('stylelint', {
233
- cssType: {
234
- preprocessor: 'scss',
235
- tailwind: true
236
- }
237
- })
238
- ```
239
-
240
213
  ### TypeScript Options
241
214
 
242
215
  ```javascript
243
216
  await createConfig('typescript', {
244
217
  framework: 'auto', // Auto-detect or specify framework
245
218
  environment: 'auto', // 'auto' | 'browser' | 'node' | 'universal'
246
- checker: 'auto', // 'auto' | 'modern' (tsgo) | 'legacy' (tsc/vue-tsc)
219
+ checker: 'auto', // 'auto' | 'modern' (tsgo) | 'legacy' (tsc)
247
220
  strict: true, // Enable strict type checking
248
- compilerOptions: {} // Custom TypeScript compiler options
249
- })
250
- ```
251
-
252
- **Example - React with Custom Options:**
253
-
254
- ```javascript
255
- export default await createConfig('typescript', {
256
- framework: 'react',
257
221
  compilerOptions: {
222
+ // Custom compiler options
258
223
  baseUrl: '.',
259
- paths: {
260
- '@/*': ['src/*']
261
- }
224
+ paths: { '@/*': ['src/*'] }
262
225
  }
263
226
  })
264
227
  ```
265
228
 
266
- **Example - Use tsgo for 10x Faster Type Checking:**
267
-
268
- ```javascript
269
- export default await createConfig('typescript', {
270
- checker: 'modern' // Forces tsgo when installed
271
- })
272
- ```
273
-
274
- **tsgo Support:** Install `@typescript/native-preview` for 10x faster type checking. The package automatically detects and uses tsgo when available.
229
+ **tsgo Support:** Install `@typescript/native-preview` for 10x faster type checking. Auto-detected or set `checker: 'modern'` to force it.
275
230
 
276
231
  ### semantic-release Options
277
232
 
@@ -282,15 +237,6 @@ createConfig('semantic-release', {
282
237
  })
283
238
  ```
284
239
 
285
- **Example - Library Release:**
286
-
287
- ```javascript
288
- export default createConfig('semantic-release', {
289
- preset: 'library',
290
- gitProvider: 'github'
291
- })
292
- ```
293
-
294
240
  ## Framework-Specific Guides
295
241
 
296
242
  ### React
@@ -419,22 +365,68 @@ npx @dimensional-innovations/tool-config
419
365
  - Choose which tools to configure
420
366
  - Auto-detects framework and TypeScript
421
367
  - Creates config files automatically
422
- - Adds npm scripts to package.json
423
- - **NEW:** Automated CI/CD pipeline setup
368
+ - Adds npm scripts to package.json (including `check-all` for multiple tools)
369
+ - Automated CI/CD pipeline setup
370
+ - **Uninstall support** - Clean removal of configs and scripts
424
371
  - Supports dry-run mode
425
372
 
426
- **Options:**
373
+ **Setup Options:**
427
374
 
428
375
  ```bash
376
+ # Interactive mode
377
+ npx @dimensional-innovations/tool-config # Choose tools interactively
378
+
379
+ # Single tool setup
429
380
  npx @dimensional-innovations/tool-config eslint # Setup ESLint only
430
- npx @dimensional-innovations/tool-config --all # Setup all tools
431
- npx @dimensional-innovations/tool-config --dry-run # Preview without creating files
381
+ npx @dimensional-innovations/tool-config prettier # Setup Prettier only
382
+ npx @dimensional-innovations/tool-config stylelint # Setup Stylelint only
383
+
384
+ # Setup all tools
385
+ npx @dimensional-innovations/tool-config --all # Setup all tools at once
386
+
387
+ # CI/CD setup
432
388
  npx @dimensional-innovations/tool-config --ci gitlab # Setup GitLab CI/CD
433
389
  npx @dimensional-innovations/tool-config --ci github # Setup GitHub Actions
434
390
  npx @dimensional-innovations/tool-config --setup-ci # Interactive CI setup
391
+
392
+ # Preview mode
393
+ npx @dimensional-innovations/tool-config --dry-run # Preview without creating files
394
+
395
+ # Help
435
396
  npx @dimensional-innovations/tool-config --help # Show all options
436
397
  ```
437
398
 
399
+ **Uninstall Options:**
400
+
401
+ ```bash
402
+ # Interactive uninstall
403
+ npx @dimensional-innovations/tool-config --uninstall # Choose which tools to remove
404
+
405
+ # Uninstall specific tool
406
+ npx @dimensional-innovations/tool-config --uninstall eslint
407
+
408
+ # Uninstall all detected tools
409
+ npx @dimensional-innovations/tool-config --uninstall --all
410
+
411
+ # Remove CI/CD configuration
412
+ npx @dimensional-innovations/tool-config --uninstall --ci
413
+
414
+ # Preview uninstall
415
+ npx @dimensional-innovations/tool-config --uninstall --dry-run
416
+ ```
417
+
418
+ **Safety Features:**
419
+
420
+ The uninstall command includes safety features to protect your customizations:
421
+
422
+ - Only removes files that match the original generated templates
423
+ - Skips modified configuration files (warns you instead)
424
+ - Only removes auto-generated package.json scripts
425
+ - Preserves custom scripts with the same names
426
+ - Supports dry-run to preview what will be removed
427
+ - Cleans up empty directories (e.g., `.github/workflows`)
428
+ - Idempotent - safe to run multiple times
429
+
438
430
  **CI/CD Integration:**
439
431
 
440
432
  When you select `semantic-release` in interactive mode, the CLI will automatically prompt you to setup CI/CD for automated releases. Or use the `--ci` flag to setup CI/CD directly:
@@ -535,64 +527,43 @@ See the [`examples/`](./examples/) directory for complete working examples:
535
527
  - [Node Backend](./examples/node-backend/) - Express, TypeScript
536
528
  - [Vanilla JS](./examples/vanilla-js/) - Pure JavaScript, no framework
537
529
 
538
- Each example includes all 4 tool configurations and npm scripts.
530
+ Each example includes all 5 tool configurations and npm scripts.
539
531
 
540
532
  ## Advanced Usage
541
533
 
542
- ### Monorepo Support
543
-
544
- Use different configs per workspace:
534
+ **Monorepo Support:**
545
535
 
546
536
  ```javascript
547
537
  // apps/frontend/eslint.config.js
548
- export default await createConfig('eslint', {
549
- framework: 'react',
550
- typescript: true
551
- })
538
+ export default await createConfig('eslint', { framework: 'react' })
552
539
 
553
540
  // apps/backend/eslint.config.js
554
- export default await createConfig('eslint', {
555
- framework: 'node',
556
- environment: 'node'
557
- })
541
+ export default await createConfig('eslint', { framework: 'node' })
558
542
  ```
559
543
 
560
- ### Custom Ignore Patterns
544
+ **Custom Ignore Patterns:**
561
545
 
562
546
  ```javascript
563
547
  export default await createConfig('eslint', {
564
- ignore: ['dist/**', 'build/**', '**/*.generated.ts']
548
+ ignore: ['dist/**', '**/*.generated.ts']
565
549
  })
566
550
  ```
567
551
 
568
- ### Environment-Specific Rules
552
+ **Environment-Specific Rules:**
569
553
 
570
554
  ```javascript
571
- const isDev = process.env.NODE_ENV === 'development'
572
-
573
555
  export default await createConfig('eslint', {
574
556
  rules: {
575
- 'no-console': isDev ? 'off' : 'error',
576
- 'no-debugger': isDev ? 'warn' : 'error'
557
+ 'no-console': process.env.NODE_ENV === 'development' ? 'off' : 'error'
577
558
  }
578
559
  })
579
560
  ```
580
561
 
581
- ### Combining with Other Configs
562
+ **Combining with Other Configs:**
582
563
 
583
564
  ```javascript
584
- import { createConfig } from '@dimensional-innovations/tool-config'
585
- import customRules from './custom-rules.js'
586
-
587
565
  const baseConfig = await createConfig('eslint')
588
-
589
- export default [
590
- ...baseConfig,
591
- {
592
- files: ['**/*.js'],
593
- rules: customRules
594
- }
595
- ]
566
+ export default [...baseConfig, { files: ['**/*.js'], rules: customRules }]
596
567
  ```
597
568
 
598
569
  ## Ignoring Files
@@ -647,8 +618,7 @@ export default createConfig('stylelint', {
647
618
 
648
619
  **Prettier** - Edit `.prettierignore` file:
649
620
 
650
- ```
651
- # Custom ignores
621
+ ```text
652
622
  generated/
653
623
  legacy/
654
624
  ```
@@ -670,77 +640,20 @@ npx prettier --check . --debug-check
670
640
 
671
641
  ## Troubleshooting
672
642
 
673
- ### Tools Processing Build Outputs
643
+ **ESLint not detecting framework:** Ensure framework is in `package.json` dependencies, or explicitly set `framework: 'react'`.
674
644
 
675
- If you see errors about linting/formatting files in `dist/`, `coverage/`, or `out/`:
645
+ **TypeScript parsing errors:** Install TypeScript: `npm install --save-dev typescript`
676
646
 
677
- 1. **ESLint**: Ignore patterns are applied automatically ✅
678
- 2. **Stylelint**: Ignore patterns are applied automatically ✅
679
- 3. **Prettier**: Check that `.prettierignore` was created. If not, re-run config creation or manually create the file.
680
-
681
- **Solution**: If `.prettierignore` is missing, it will be auto-created next time you use the config. Or create it manually:
647
+ **Prettier plugin not found:** Install required peer dependency:
682
648
 
683
649
  ```bash
684
- # Let Prettier generate it
685
- node -e "import('@dimensional-innovations/tool-config').then(m => m.createConfig('prettier'))"
650
+ npm install --save-dev prettier-plugin-svelte # Svelte
651
+ npm install --save-dev prettier-plugin-astro # Astro
686
652
  ```
687
653
 
688
- ### ESLint Not Detecting Framework
689
-
690
- Ensure your `package.json` includes the framework dependency:
654
+ **Stylelint not linting .vue files:** Update script: `"style": "stylelint '**/*.css' '**/*.vue' --allow-empty-input"`
691
655
 
692
- ```json
693
- {
694
- "dependencies": {
695
- "react": "^18.0.0"
696
- }
697
- }
698
- ```
699
-
700
- Or explicitly specify:
701
-
702
- ```javascript
703
- export default await createConfig('eslint', {
704
- framework: 'react'
705
- })
706
- ```
707
-
708
- ### TypeScript Parsing Errors
709
-
710
- Make sure `typescript` is installed:
711
-
712
- ```bash
713
- npm install --save-dev typescript
714
- ```
715
-
716
- ### Prettier Plugin Not Found
717
-
718
- Install the required peer dependency:
719
-
720
- ```bash
721
- npm install --save-dev prettier-plugin-svelte # For Svelte
722
- npm install --save-dev prettier-plugin-astro # For Astro
723
- ```
724
-
725
- ### Stylelint Not Linting .vue Files
726
-
727
- Update your npm script to include `.vue` files:
728
-
729
- ```json
730
- {
731
- "scripts": {
732
- "style": "stylelint '**/*.css' '**/*.vue'"
733
- }
734
- }
735
- ```
736
-
737
- ### Config Not Updating After Framework Change
738
-
739
- Delete `node_modules/.cache` and restart your editor:
740
-
741
- ```bash
742
- rm -rf node_modules/.cache
743
- ```
656
+ **Config not updating:** Delete `node_modules/.cache` and restart editor.
744
657
 
745
658
  ## Requirements
746
659
 
@@ -757,20 +670,18 @@ This package follows these principles:
757
670
  - **Fail Loudly** - Errors for critical issues, warnings for quality improvements
758
671
  - **Framework Agnostic** - No opinions about which framework you use
759
672
  - **Modern Standards** - Uses latest tooling and ESLint flat config
760
- - **Comprehensive Coverage** - 100% test coverage, battle-tested in production
673
+ - **Comprehensive Coverage** - 96% test coverage, battle-tested in production
761
674
 
762
675
  ## Contributing
763
676
 
764
- Contributions welcome! This package is built to be extensible.
765
-
766
- **To add a new framework:**
677
+ Contributions welcome! To add a new framework:
767
678
 
768
679
  1. Add detection logic in `src/detectors.js`
769
680
  2. Create presets in `src/tools/{tool}/presets/frameworks/`
770
681
  3. Add tests with 100% coverage
771
682
  4. Update documentation
772
683
 
773
- See [IMPLEMENTATION_PLAN.md](./IMPLEMENTATION_PLAN.md) for architecture details.
684
+ See [CLAUDE.md](./CLAUDE.md) for architecture details.
774
685
 
775
686
  ## License
776
687
 
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Formatting utilities for CLI output
3
+ * Standardized box drawing with consistent width
4
+ */
5
+
6
+ import pc from 'picocolors'
7
+
8
+ const BOX_WIDTH = 70 // Standard width for all boxes
9
+
10
+ export const BOX = {
11
+ topLeft: '┌',
12
+ topRight: '┐',
13
+ bottomLeft: '└',
14
+ bottomRight: '┘',
15
+ vertical: '│',
16
+ horizontal: '─',
17
+ separator: '━',
18
+ width: BOX_WIDTH
19
+ }
20
+
21
+ /**
22
+ * Create a box with standard width (70 chars)
23
+ * @param {string[]} lines - Array of content lines
24
+ * @param {string} title - Optional title for top border
25
+ * @returns {string} Formatted box
26
+ */
27
+ export function createBox(lines, title = '') {
28
+ const width = BOX.width
29
+ const contentWidth = width - 4 // Remove: │ + space + space + │
30
+
31
+ // Create top border
32
+ let top
33
+ if (title) {
34
+ const titlePart = `─ ${title} `
35
+ const remaining = width - 2 - titlePart.length // -2 for corners
36
+ top = BOX.topLeft + titlePart + BOX.horizontal.repeat(remaining) + BOX.topRight
37
+ } else {
38
+ top = BOX.topLeft + BOX.horizontal.repeat(width - 2) + BOX.topRight
39
+ }
40
+
41
+ // Create content lines - pad each to exact width
42
+ const content = lines.map(line => {
43
+ const padded = line.slice(0, contentWidth).padEnd(contentWidth)
44
+ return `${BOX.vertical} ${padded} ${BOX.vertical}`
45
+ })
46
+
47
+ // Create bottom border
48
+ const bottom = BOX.bottomLeft + BOX.horizontal.repeat(width - 2) + BOX.bottomRight
49
+
50
+ return [top, ...content, bottom].join('\n')
51
+ }
52
+
53
+ /**
54
+ * Create a separator line
55
+ * @returns {string} Separator line
56
+ */
57
+ export function createSeparator() {
58
+ return BOX.separator.repeat(BOX.width)
59
+ }
60
+
61
+ /**
62
+ * Create a simple indented list
63
+ * @param {string[]} items - Array of items
64
+ * @param {string} bullet - Bullet character (default: 'â€ĸ')
65
+ * @returns {string} Formatted list
66
+ */
67
+ export function createList(items, bullet = 'â€ĸ') {
68
+ return items.map(item => ` ${bullet} ${item}`).join('\n')
69
+ }
70
+
71
+ /**
72
+ * Create a progress indicator
73
+ * @param {number} current - Current step
74
+ * @param {number} total - Total steps
75
+ * @param {string} label - Label for this step
76
+ * @returns {string} Progress line
77
+ */
78
+ export function createProgress(current, total, label) {
79
+ return ` [${current}/${total}] ${label}`
80
+ }
81
+
82
+ /**
83
+ * Color symbols for CLI output
84
+ */
85
+ export const SYMBOLS = {
86
+ success: pc.green('✓'),
87
+ warning: pc.yellow('⚠'),
88
+ error: pc.red('✗'),
89
+ info: pc.blue('ℹ')
90
+ }
91
+
92
+ /**
93
+ * Color helper functions
94
+ */
95
+ export const colors = {
96
+ success: pc.green,
97
+ warning: pc.yellow,
98
+ error: pc.red,
99
+ info: pc.blue,
100
+ dim: pc.dim,
101
+ bold: pc.bold,
102
+ cyan: pc.cyan
103
+ }
@@ -51,8 +51,8 @@ export function getScripts(detected) {
51
51
  extensions.length === 1 ? `**/*.${extensions[0]}` : `**/*.{${extensions.join(',')}}`
52
52
 
53
53
  return {
54
- style: `stylelint "${pattern}"`,
55
- 'style:fix': `stylelint "${pattern}" --fix`
54
+ style: `stylelint "${pattern}" --allow-empty-input`,
55
+ 'style:fix': `stylelint "${pattern}" --fix --allow-empty-input`
56
56
  }
57
57
  }
58
58
 
@@ -112,3 +112,90 @@ export function updatePackageJsonScripts(tools, getScriptsFn, context) {
112
112
  console.error(' ❌ Failed to update package.json:', error.message)
113
113
  }
114
114
  }
115
+
116
+ /**
117
+ * Remove scripts from package.json for tools
118
+ * @param {string[]} tools - Array of tool names to remove scripts for
119
+ * @param {Function} getScriptsFn - Function that returns scripts for a tool: (tool, detected) => object
120
+ * @param {Object} context - Context object with {detected, cwd, dryRun}
121
+ */
122
+ export function removePackageJsonScripts(tools, getScriptsFn, context) {
123
+ const { detected, cwd, dryRun = false } = context
124
+ const packageJsonPath = join(cwd, 'package.json')
125
+
126
+ if (!existsSync(packageJsonPath)) {
127
+ console.log(' â„šī¸ No package.json found - skipping script removal')
128
+ return
129
+ }
130
+
131
+ try {
132
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'))
133
+
134
+ if (!packageJson.scripts) {
135
+ console.log(' â„šī¸ No scripts section in package.json')
136
+ return
137
+ }
138
+
139
+ const scriptsToRemove = []
140
+
141
+ // Collect script names to remove based on tools
142
+ for (const tool of tools) {
143
+ const toolScripts = getScriptsFn(tool, detected)
144
+ for (const scriptName of Object.keys(toolScripts)) {
145
+ const expectedCommand = toolScripts[scriptName]
146
+ const actualCommand = packageJson.scripts[scriptName]
147
+
148
+ // Only remove if the script exists and matches our expected command
149
+ if (actualCommand === expectedCommand) {
150
+ scriptsToRemove.push(scriptName)
151
+ } else if (actualCommand) {
152
+ console.log(` âš ī¸ Script "${scriptName}" has been modified - skipping for safety`)
153
+ }
154
+ }
155
+ }
156
+
157
+ // Handle check-all script separately
158
+ const checkAllScript = packageJson.scripts['check-all']
159
+ if (checkAllScript) {
160
+ // Only remove if it's auto-generated (follows npm run X && npm run Y pattern)
161
+ const isAutoGenerated =
162
+ checkAllScript.startsWith('npm run') && checkAllScript.includes(' && npm run')
163
+
164
+ if (isAutoGenerated) {
165
+ scriptsToRemove.push('check-all')
166
+ }
167
+ }
168
+
169
+ if (scriptsToRemove.length === 0) {
170
+ console.log(' â„šī¸ No scripts to remove from package.json')
171
+ return
172
+ }
173
+
174
+ if (dryRun) {
175
+ console.log(' 📝 Would remove scripts from package.json:')
176
+ for (const name of scriptsToRemove) {
177
+ console.log(` - ${name}`)
178
+ }
179
+ return
180
+ }
181
+
182
+ // Remove scripts
183
+ for (const scriptName of scriptsToRemove) {
184
+ delete packageJson.scripts[scriptName]
185
+ }
186
+
187
+ // Remove scripts section if empty
188
+ if (Object.keys(packageJson.scripts).length === 0) {
189
+ delete packageJson.scripts
190
+ }
191
+
192
+ writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`, 'utf8')
193
+
194
+ console.log(' ✅ Removed scripts from package.json:')
195
+ for (const name of scriptsToRemove) {
196
+ console.log(` - ${name}`)
197
+ }
198
+ } catch (error) {
199
+ console.error(' ❌ Failed to update package.json:', error.message)
200
+ }
201
+ }