@dimensional-innovations/tool-config 1.4.1 → 3.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/README.md +128 -23
- package/bin/lib/ci-setup.js +142 -0
- package/bin/lib/formatting.js +103 -0
- package/bin/lib/handlers/eslint.js +61 -0
- package/bin/lib/handlers/prettier.js +83 -0
- package/bin/lib/handlers/semantic-release.js +60 -0
- package/bin/lib/handlers/stylelint.js +85 -0
- package/bin/lib/handlers/typescript.js +156 -0
- package/bin/lib/package-manager.js +201 -0
- package/bin/lib/ui.js +239 -0
- package/bin/lib/uninstall.js +199 -0
- package/bin/lib/validators.js +28 -0
- package/bin/setup-tool-config.js +270 -576
- package/package.json +17 -4
- package/src/detectors.js +27 -2
- package/src/index.js +8 -3
- package/src/tools/typescript/README.md +665 -0
- package/src/tools/typescript/checker-detection.js +113 -0
- package/src/tools/typescript/index.js +202 -0
- package/src/tools/typescript/presets/base.js +58 -0
- package/src/tools/typescript/presets/environments/browser.js +10 -0
- package/src/tools/typescript/presets/environments/node.js +11 -0
- package/src/tools/typescript/presets/environments/universal.js +11 -0
- package/src/tools/typescript/presets/frameworks/angular.js +11 -0
- package/src/tools/typescript/presets/frameworks/astro.js +11 -0
- package/src/tools/typescript/presets/frameworks/electron.js +100 -0
- package/src/tools/typescript/presets/frameworks/node.js +12 -0
- package/src/tools/typescript/presets/frameworks/react.js +10 -0
- package/src/tools/typescript/presets/frameworks/solid.js +11 -0
- package/src/tools/typescript/presets/frameworks/svelte.js +10 -0
- package/src/tools/typescript/presets/frameworks/vanilla.js +9 -0
- package/src/tools/typescript/presets/frameworks/vue.js +17 -0
package/README.md
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# @dimensional-innovations/tool-config
|
|
2
2
|
|
|
3
|
-
> Universal configuration package for ESLint, Prettier, Stylelint, and semantic-release with automatic framework detection.
|
|
3
|
+
> Universal configuration package for ESLint, Prettier, Stylelint, TypeScript, and semantic-release with automatic framework detection.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@dimensional-innovations/tool-config)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
[](https://nodejs.org/)
|
|
8
8
|
[](./tests/)
|
|
9
9
|
|
|
10
|
-
**One package.
|
|
10
|
+
**One package. Five tools. Zero configuration.**
|
|
11
11
|
|
|
12
|
-
Stop juggling multiple config packages. This single package provides battle-tested configurations for ESLint, Prettier, Stylelint, and semantic-release that automatically detect your project's framework, environment, and TypeScript setup.
|
|
12
|
+
Stop juggling multiple config packages. This single package provides battle-tested configurations for ESLint, Prettier, Stylelint, TypeScript, and semantic-release that automatically detect your project's framework, environment, and TypeScript setup.
|
|
13
13
|
|
|
14
14
|
## Why This Package?
|
|
15
15
|
|
|
@@ -34,12 +34,14 @@ npm install --save-dev @dimensional-innovations/tool-config
|
|
|
34
34
|
## Features
|
|
35
35
|
|
|
36
36
|
- 🎯 **Zero Configuration** - Auto-detects your framework, environment, and TypeScript
|
|
37
|
-
- 🧰 **Multi-Tool Support** - ESLint, Prettier, Stylelint, semantic-release in one package
|
|
37
|
+
- 🧰 **Multi-Tool Support** - ESLint, Prettier, Stylelint, TypeScript, semantic-release in one package
|
|
38
38
|
- ⚛️ **8+ Frameworks** - React, Vue, Svelte, Solid, Astro, Angular, Vanilla JS, Node.js
|
|
39
39
|
- 📦 **All-In-One** - All plugins and parsers included as dependencies
|
|
40
40
|
- 🔧 **Customizable** - Override any setting while keeping smart defaults
|
|
41
|
-
- 🚀 **Modern** - ESLint 9+ flat config,
|
|
42
|
-
-
|
|
41
|
+
- 🚀 **Modern** - ESLint 9+ flat config, TypeScript with tsgo support (10x faster)
|
|
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 100% coverage
|
|
43
45
|
|
|
44
46
|
## Quick Start
|
|
45
47
|
|
|
@@ -83,6 +85,22 @@ import { createConfig } from '@dimensional-innovations/tool-config'
|
|
|
83
85
|
export default createConfig('stylelint')
|
|
84
86
|
```
|
|
85
87
|
|
|
88
|
+
**TypeScript** (`tsconfig.json`):
|
|
89
|
+
|
|
90
|
+
```json
|
|
91
|
+
{
|
|
92
|
+
"$schema": "https://json.schemastore.org/tsconfig",
|
|
93
|
+
"compilerOptions": {
|
|
94
|
+
"strict": true,
|
|
95
|
+
"skipLibCheck": true
|
|
96
|
+
},
|
|
97
|
+
"include": ["src/**/*"],
|
|
98
|
+
"exclude": ["node_modules"]
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Or use the factory function to generate framework-specific TypeScript configs programmatically.
|
|
103
|
+
|
|
86
104
|
**semantic-release** (`release.config.js`):
|
|
87
105
|
|
|
88
106
|
```javascript
|
|
@@ -103,23 +121,28 @@ That's it! The configs will automatically detect your framework and TypeScript s
|
|
|
103
121
|
"prettier": "prettier --check .",
|
|
104
122
|
"prettier:fix": "prettier --write .",
|
|
105
123
|
"style": "stylelint '**/*.css'",
|
|
106
|
-
"style:fix": "stylelint '**/*.css' --fix"
|
|
124
|
+
"style:fix": "stylelint '**/*.css' --fix",
|
|
125
|
+
"typecheck": "tsc --noEmit",
|
|
126
|
+
"typecheck:watch": "tsc --noEmit --watch",
|
|
127
|
+
"check-all": "npm run prettier && npm run style && npm run lint && npm run typecheck"
|
|
107
128
|
}
|
|
108
129
|
}
|
|
109
130
|
```
|
|
110
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
|
+
|
|
111
134
|
## Supported Frameworks
|
|
112
135
|
|
|
113
|
-
| Framework | ESLint | Prettier | Stylelint | Auto-Detect |
|
|
114
|
-
| --------- | ------ | -------- | ------------------- | ----------- |
|
|
115
|
-
| React | ✅ | ✅ | ✅ CSS Modules | ✅ |
|
|
116
|
-
| Vue | ✅ | ✅ | ✅ Scoped Styles | ✅ |
|
|
117
|
-
| Svelte | ✅ | ✅ | ✅ Component Styles | ✅ |
|
|
118
|
-
| Solid | ✅ | ✅ | ✅ CSS Modules | ✅ |
|
|
119
|
-
| Astro | ✅ | ✅ | ✅ | ✅ |
|
|
120
|
-
| Angular | ✅ | ✅ | ✅ | ✅ |
|
|
121
|
-
| Vanilla | ✅ | ✅ | ✅ | ✅ |
|
|
122
|
-
| Node.js | ✅ | ✅ | N/A | ✅ |
|
|
136
|
+
| Framework | ESLint | Prettier | Stylelint | TypeScript | Auto-Detect |
|
|
137
|
+
| --------- | ------ | -------- | ------------------- | --------------- | ----------- |
|
|
138
|
+
| React | ✅ | ✅ | ✅ CSS Modules | ✅ react-jsx | ✅ |
|
|
139
|
+
| Vue | ✅ | ✅ | ✅ Scoped Styles | ✅ vue-tsc | ✅ |
|
|
140
|
+
| Svelte | ✅ | ✅ | ✅ Component Styles | ✅ svelte types | ✅ |
|
|
141
|
+
| Solid | ✅ | ✅ | ✅ CSS Modules | ✅ solid-js | ✅ |
|
|
142
|
+
| Astro | ✅ | ✅ | ✅ | ✅ astro/client | ✅ |
|
|
143
|
+
| Angular | ✅ | ✅ | ✅ | ✅ decorators | ✅ |
|
|
144
|
+
| Vanilla | ✅ | ✅ | ✅ | ✅ browser | ✅ |
|
|
145
|
+
| Node.js | ✅ | ✅ | N/A | ✅ NodeNext | ✅ |
|
|
123
146
|
|
|
124
147
|
**Meta-frameworks**: Next.js (→ React), Nuxt (→ Vue), SvelteKit (→ Svelte)
|
|
125
148
|
|
|
@@ -131,7 +154,7 @@ The main factory function that creates configurations for any supported tool.
|
|
|
131
154
|
|
|
132
155
|
**Parameters:**
|
|
133
156
|
|
|
134
|
-
- `tool` (string, required): Tool name - `'eslint'`, `'prettier'`, `'stylelint'`, or `'semantic-release'`
|
|
157
|
+
- `tool` (string, required): Tool name - `'eslint'`, `'prettier'`, `'stylelint'`, `'typescript'`, or `'semantic-release'`
|
|
135
158
|
- `options` (object, optional): Configuration options
|
|
136
159
|
|
|
137
160
|
**Common Options:**
|
|
@@ -219,6 +242,42 @@ export default createConfig('stylelint', {
|
|
|
219
242
|
})
|
|
220
243
|
```
|
|
221
244
|
|
|
245
|
+
### TypeScript Options
|
|
246
|
+
|
|
247
|
+
```javascript
|
|
248
|
+
await createConfig('typescript', {
|
|
249
|
+
framework: 'auto', // Auto-detect or specify framework
|
|
250
|
+
environment: 'auto', // 'auto' | 'browser' | 'node' | 'universal'
|
|
251
|
+
checker: 'auto', // 'auto' | 'modern' (tsgo) | 'legacy' (tsc/vue-tsc)
|
|
252
|
+
strict: true, // Enable strict type checking
|
|
253
|
+
compilerOptions: {} // Custom TypeScript compiler options
|
|
254
|
+
})
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
**Example - React with Custom Options:**
|
|
258
|
+
|
|
259
|
+
```javascript
|
|
260
|
+
export default await createConfig('typescript', {
|
|
261
|
+
framework: 'react',
|
|
262
|
+
compilerOptions: {
|
|
263
|
+
baseUrl: '.',
|
|
264
|
+
paths: {
|
|
265
|
+
'@/*': ['src/*']
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
})
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**Example - Use tsgo for 10x Faster Type Checking:**
|
|
272
|
+
|
|
273
|
+
```javascript
|
|
274
|
+
export default await createConfig('typescript', {
|
|
275
|
+
checker: 'modern' // Forces tsgo when installed
|
|
276
|
+
})
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
**tsgo Support:** Install `@typescript/native-preview` for 10x faster type checking. The package automatically detects and uses tsgo when available.
|
|
280
|
+
|
|
222
281
|
### semantic-release Options
|
|
223
282
|
|
|
224
283
|
```javascript
|
|
@@ -365,22 +424,68 @@ npx @dimensional-innovations/tool-config
|
|
|
365
424
|
- Choose which tools to configure
|
|
366
425
|
- Auto-detects framework and TypeScript
|
|
367
426
|
- Creates config files automatically
|
|
368
|
-
- Adds npm scripts to package.json
|
|
369
|
-
-
|
|
427
|
+
- Adds npm scripts to package.json (including `check-all` for multiple tools)
|
|
428
|
+
- Automated CI/CD pipeline setup
|
|
429
|
+
- **Uninstall support** - Clean removal of configs and scripts
|
|
370
430
|
- Supports dry-run mode
|
|
371
431
|
|
|
372
|
-
**Options:**
|
|
432
|
+
**Setup Options:**
|
|
373
433
|
|
|
374
434
|
```bash
|
|
435
|
+
# Interactive mode
|
|
436
|
+
npx @dimensional-innovations/tool-config # Choose tools interactively
|
|
437
|
+
|
|
438
|
+
# Single tool setup
|
|
375
439
|
npx @dimensional-innovations/tool-config eslint # Setup ESLint only
|
|
376
|
-
npx @dimensional-innovations/tool-config
|
|
377
|
-
npx @dimensional-innovations/tool-config
|
|
440
|
+
npx @dimensional-innovations/tool-config prettier # Setup Prettier only
|
|
441
|
+
npx @dimensional-innovations/tool-config stylelint # Setup Stylelint only
|
|
442
|
+
|
|
443
|
+
# Setup all tools
|
|
444
|
+
npx @dimensional-innovations/tool-config --all # Setup all tools at once
|
|
445
|
+
|
|
446
|
+
# CI/CD setup
|
|
378
447
|
npx @dimensional-innovations/tool-config --ci gitlab # Setup GitLab CI/CD
|
|
379
448
|
npx @dimensional-innovations/tool-config --ci github # Setup GitHub Actions
|
|
380
449
|
npx @dimensional-innovations/tool-config --setup-ci # Interactive CI setup
|
|
450
|
+
|
|
451
|
+
# Preview mode
|
|
452
|
+
npx @dimensional-innovations/tool-config --dry-run # Preview without creating files
|
|
453
|
+
|
|
454
|
+
# Help
|
|
381
455
|
npx @dimensional-innovations/tool-config --help # Show all options
|
|
382
456
|
```
|
|
383
457
|
|
|
458
|
+
**Uninstall Options:**
|
|
459
|
+
|
|
460
|
+
```bash
|
|
461
|
+
# Interactive uninstall
|
|
462
|
+
npx @dimensional-innovations/tool-config --uninstall # Choose which tools to remove
|
|
463
|
+
|
|
464
|
+
# Uninstall specific tool
|
|
465
|
+
npx @dimensional-innovations/tool-config --uninstall eslint
|
|
466
|
+
|
|
467
|
+
# Uninstall all detected tools
|
|
468
|
+
npx @dimensional-innovations/tool-config --uninstall --all
|
|
469
|
+
|
|
470
|
+
# Remove CI/CD configuration
|
|
471
|
+
npx @dimensional-innovations/tool-config --uninstall --ci
|
|
472
|
+
|
|
473
|
+
# Preview uninstall
|
|
474
|
+
npx @dimensional-innovations/tool-config --uninstall --dry-run
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
**Safety Features:**
|
|
478
|
+
|
|
479
|
+
The uninstall command includes safety features to protect your customizations:
|
|
480
|
+
|
|
481
|
+
- Only removes files that match the original generated templates
|
|
482
|
+
- Skips modified configuration files (warns you instead)
|
|
483
|
+
- Only removes auto-generated package.json scripts
|
|
484
|
+
- Preserves custom scripts with the same names
|
|
485
|
+
- Supports dry-run to preview what will be removed
|
|
486
|
+
- Cleans up empty directories (e.g., `.github/workflows`)
|
|
487
|
+
- Idempotent - safe to run multiple times
|
|
488
|
+
|
|
384
489
|
**CI/CD Integration:**
|
|
385
490
|
|
|
386
491
|
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:
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CI/CD setup utilities for setup-tool-config CLI
|
|
3
|
+
* Handles CI template copying and configuration
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { copyFileSync, existsSync, mkdirSync } from 'fs'
|
|
7
|
+
import { dirname, join } from 'path'
|
|
8
|
+
import { fileURLToPath } from 'url'
|
|
9
|
+
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
13
|
+
const __dirname = dirname(__filename)
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Get CI filename and path for a git provider
|
|
17
|
+
*/
|
|
18
|
+
function getCIFileInfo(provider) {
|
|
19
|
+
const ciFiles = {
|
|
20
|
+
gitlab: {
|
|
21
|
+
filename: '.gitlab-ci.yml',
|
|
22
|
+
destination: '.gitlab-ci.yml',
|
|
23
|
+
template: '.gitlab-ci.yml'
|
|
24
|
+
},
|
|
25
|
+
github: {
|
|
26
|
+
filename: 'ci.yml',
|
|
27
|
+
destination: '.github/workflows/ci.yml',
|
|
28
|
+
template: 'github-workflow.yml',
|
|
29
|
+
needsDir: true
|
|
30
|
+
},
|
|
31
|
+
bitbucket: {
|
|
32
|
+
filename: 'bitbucket-pipelines.yml',
|
|
33
|
+
destination: 'bitbucket-pipelines.yml',
|
|
34
|
+
template: 'bitbucket-pipelines.yml'
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return ciFiles[provider] || null
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Get environment variable instructions for a git provider
|
|
43
|
+
*/
|
|
44
|
+
function getCIInstructions(provider) {
|
|
45
|
+
const instructions = {
|
|
46
|
+
gitlab: `
|
|
47
|
+
⚠️ Configuration Required:
|
|
48
|
+
Add these CI/CD variables in GitLab Settings > CI/CD > Variables:
|
|
49
|
+
- GL_TOKEN: GitLab Personal Access Token (with api scope)
|
|
50
|
+
- NPM_TOKEN: npm authentication token
|
|
51
|
+
|
|
52
|
+
Then push to main branch to trigger automated releases.`,
|
|
53
|
+
github: `
|
|
54
|
+
⚠️ Configuration Required:
|
|
55
|
+
Add these secrets in GitHub Settings > Secrets and variables > Actions:
|
|
56
|
+
- GITHUB_TOKEN: Automatically provided by GitHub Actions
|
|
57
|
+
- NPM_TOKEN: npm authentication token
|
|
58
|
+
|
|
59
|
+
Then push to main branch to trigger automated releases.`,
|
|
60
|
+
bitbucket: `
|
|
61
|
+
⚠️ Configuration Required:
|
|
62
|
+
Add this repository variable in Bitbucket Settings > Pipelines > Repository variables:
|
|
63
|
+
- NPM_TOKEN: npm authentication token
|
|
64
|
+
|
|
65
|
+
Then push to main branch to trigger automated releases.`
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return instructions[provider] || ''
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Copy CI/CD template
|
|
73
|
+
*/
|
|
74
|
+
export function copyCITemplate(provider, cwd, dryRun = false) {
|
|
75
|
+
if (!provider || provider === 'unknown') {
|
|
76
|
+
console.log(' ⚠️ Could not detect git provider - skipping CI setup')
|
|
77
|
+
console.log(' 💡 You can manually copy templates from:')
|
|
78
|
+
console.log(
|
|
79
|
+
' node_modules/@dimensional-innovations/tool-config/src/tools/semantic-release/templates/'
|
|
80
|
+
)
|
|
81
|
+
return false
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const ciInfo = getCIFileInfo(provider)
|
|
85
|
+
|
|
86
|
+
if (!ciInfo) {
|
|
87
|
+
console.log(` ⚠️ Unsupported git provider: ${provider}`)
|
|
88
|
+
return false
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const destPath = join(cwd, ciInfo.destination)
|
|
92
|
+
const destDir = dirname(destPath)
|
|
93
|
+
|
|
94
|
+
// Check if CI file already exists
|
|
95
|
+
if (existsSync(destPath)) {
|
|
96
|
+
console.log(` ⚠️ ${ciInfo.destination} already exists - skipping`)
|
|
97
|
+
return false
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (dryRun) {
|
|
101
|
+
console.log(` 📄 Would create: ${ciInfo.destination}`)
|
|
102
|
+
if (ciInfo.needsDir && !existsSync(destDir)) {
|
|
103
|
+
console.log(` 📁 Would create directory: ${dirname(ciInfo.destination)}`)
|
|
104
|
+
}
|
|
105
|
+
return true
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
// Create directory if needed
|
|
110
|
+
if (ciInfo.needsDir && !existsSync(destDir)) {
|
|
111
|
+
mkdirSync(destDir, { recursive: true })
|
|
112
|
+
console.log(` ✅ Created directory: ${dirname(ciInfo.destination)}`)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Copy template
|
|
116
|
+
const templatePath = join(
|
|
117
|
+
__dirname,
|
|
118
|
+
'..',
|
|
119
|
+
'..',
|
|
120
|
+
'src',
|
|
121
|
+
'tools',
|
|
122
|
+
'semantic-release',
|
|
123
|
+
'templates',
|
|
124
|
+
ciInfo.template
|
|
125
|
+
)
|
|
126
|
+
copyFileSync(templatePath, destPath)
|
|
127
|
+
console.log(` ✅ Created: ${ciInfo.destination}`)
|
|
128
|
+
|
|
129
|
+
// Show configuration instructions
|
|
130
|
+
console.log(getCIInstructions(provider))
|
|
131
|
+
|
|
132
|
+
console.log('\n 📖 For more details, see:')
|
|
133
|
+
console.log(
|
|
134
|
+
' node_modules/@dimensional-innovations/tool-config/src/tools/semantic-release/CI_SETUP.md'
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
return true
|
|
138
|
+
} catch (error) {
|
|
139
|
+
console.error(` ❌ Failed to copy CI template:`, error.message)
|
|
140
|
+
return false
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ESLint handler for setup-tool-config CLI
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { existsSync, writeFileSync } from 'fs'
|
|
6
|
+
import { join } from 'path'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Get config filename
|
|
10
|
+
*/
|
|
11
|
+
export function getConfigFilename() {
|
|
12
|
+
return 'eslint.config.js'
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Generate config file content
|
|
17
|
+
*/
|
|
18
|
+
export function generateConfigContent() {
|
|
19
|
+
return `import { createConfig } from '@dimensional-innovations/tool-config'
|
|
20
|
+
|
|
21
|
+
export default await createConfig('eslint')
|
|
22
|
+
`
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Get npm scripts
|
|
27
|
+
*/
|
|
28
|
+
export function getScripts() {
|
|
29
|
+
return {
|
|
30
|
+
lint: 'eslint .',
|
|
31
|
+
'lint:fix': 'eslint --fix .'
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Write config file
|
|
37
|
+
*/
|
|
38
|
+
export function writeConfig(cwd, _detected, dryRun = false) {
|
|
39
|
+
const filename = getConfigFilename()
|
|
40
|
+
const filepath = join(cwd, filename)
|
|
41
|
+
const content = generateConfigContent()
|
|
42
|
+
|
|
43
|
+
if (existsSync(filepath)) {
|
|
44
|
+
console.log(` ⚠️ ${filename} already exists - skipping`)
|
|
45
|
+
return false
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (dryRun) {
|
|
49
|
+
console.log(` 📄 Would create: ${filename}`)
|
|
50
|
+
return true
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
writeFileSync(filepath, content, 'utf8')
|
|
55
|
+
console.log(` ✅ Created: ${filename}`)
|
|
56
|
+
return true
|
|
57
|
+
} catch (error) {
|
|
58
|
+
console.error(` ❌ Failed to create ${filename}:`, error.message)
|
|
59
|
+
return false
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prettier handler for setup-tool-config CLI
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { existsSync, writeFileSync } from 'fs'
|
|
6
|
+
import { join } from 'path'
|
|
7
|
+
|
|
8
|
+
import { prettierIgnoreContent } from '../../../src/tools/prettier/index.js'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Get config filename
|
|
12
|
+
*/
|
|
13
|
+
export function getConfigFilename() {
|
|
14
|
+
return 'prettier.config.js'
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Generate config file content
|
|
19
|
+
*/
|
|
20
|
+
export function generateConfigContent() {
|
|
21
|
+
return `import { createConfig } from '@dimensional-innovations/tool-config'
|
|
22
|
+
|
|
23
|
+
export default createConfig('prettier')
|
|
24
|
+
`
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Get npm scripts
|
|
29
|
+
*/
|
|
30
|
+
export function getScripts() {
|
|
31
|
+
return {
|
|
32
|
+
'prettier:fix': 'prettier --write .',
|
|
33
|
+
prettier: 'prettier --check .'
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Write config file
|
|
39
|
+
*/
|
|
40
|
+
export function writeConfig(cwd, _detected, dryRun = false) {
|
|
41
|
+
const filename = getConfigFilename()
|
|
42
|
+
const filepath = join(cwd, filename)
|
|
43
|
+
const content = generateConfigContent()
|
|
44
|
+
|
|
45
|
+
if (existsSync(filepath)) {
|
|
46
|
+
console.log(` ⚠️ ${filename} already exists - skipping`)
|
|
47
|
+
return false
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (dryRun) {
|
|
51
|
+
console.log(` 📄 Would create: ${filename}`)
|
|
52
|
+
|
|
53
|
+
// Prettier also creates .prettierignore
|
|
54
|
+
const ignoreFile = '.prettierignore'
|
|
55
|
+
const ignoreExists = existsSync(join(cwd, ignoreFile))
|
|
56
|
+
if (!ignoreExists) {
|
|
57
|
+
console.log(` 📄 Would create: ${ignoreFile}`)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return true
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
writeFileSync(filepath, content, 'utf8')
|
|
65
|
+
console.log(` ✅ Created: ${filename}`)
|
|
66
|
+
|
|
67
|
+
// Prettier also creates .prettierignore
|
|
68
|
+
const ignoreFile = '.prettierignore'
|
|
69
|
+
const ignorePath = join(cwd, ignoreFile)
|
|
70
|
+
|
|
71
|
+
if (!existsSync(ignorePath)) {
|
|
72
|
+
writeFileSync(ignorePath, prettierIgnoreContent, 'utf8')
|
|
73
|
+
console.log(` ✅ Created: ${ignoreFile}`)
|
|
74
|
+
} else {
|
|
75
|
+
console.log(` ⚠️ ${ignoreFile} already exists - skipping`)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return true
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.error(` ❌ Failed to create ${filename}:`, error.message)
|
|
81
|
+
return false
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* semantic-release handler for setup-tool-config CLI
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { existsSync, writeFileSync } from 'fs'
|
|
6
|
+
import { join } from 'path'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Get config filename
|
|
10
|
+
*/
|
|
11
|
+
export function getConfigFilename() {
|
|
12
|
+
return 'release.config.js'
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Generate config file content
|
|
17
|
+
*/
|
|
18
|
+
export function generateConfigContent() {
|
|
19
|
+
return `import { createConfig } from '@dimensional-innovations/tool-config'
|
|
20
|
+
|
|
21
|
+
export default createConfig('semantic-release')
|
|
22
|
+
`
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Get npm scripts
|
|
27
|
+
*/
|
|
28
|
+
export function getScripts() {
|
|
29
|
+
return {
|
|
30
|
+
release: 'semantic-release'
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Write config file
|
|
36
|
+
*/
|
|
37
|
+
export function writeConfig(cwd, _detected, dryRun = false) {
|
|
38
|
+
const filename = getConfigFilename()
|
|
39
|
+
const filepath = join(cwd, filename)
|
|
40
|
+
const content = generateConfigContent()
|
|
41
|
+
|
|
42
|
+
if (existsSync(filepath)) {
|
|
43
|
+
console.log(` ⚠️ ${filename} already exists - skipping`)
|
|
44
|
+
return false
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (dryRun) {
|
|
48
|
+
console.log(` 📄 Would create: ${filename}`)
|
|
49
|
+
return true
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
writeFileSync(filepath, content, 'utf8')
|
|
54
|
+
console.log(` ✅ Created: ${filename}`)
|
|
55
|
+
return true
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error(` ❌ Failed to create ${filename}:`, error.message)
|
|
58
|
+
return false
|
|
59
|
+
}
|
|
60
|
+
}
|