@dimensional-innovations/tool-config 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +646 -0
- package/bin/setup-tool-config.js +675 -0
- package/package.json +168 -0
- package/src/detectors.js +261 -0
- package/src/index.js +64 -0
- package/src/tools/eslint/index.js +287 -0
- package/src/tools/eslint/presets/base.js +82 -0
- package/src/tools/eslint/presets/environments/browser.js +16 -0
- package/src/tools/eslint/presets/environments/node.js +21 -0
- package/src/tools/eslint/presets/environments/universal.js +18 -0
- package/src/tools/eslint/presets/frameworks/angular.js +74 -0
- package/src/tools/eslint/presets/frameworks/astro.js +38 -0
- package/src/tools/eslint/presets/frameworks/node.js +57 -0
- package/src/tools/eslint/presets/frameworks/react.js +76 -0
- package/src/tools/eslint/presets/frameworks/solid.js +45 -0
- package/src/tools/eslint/presets/frameworks/svelte.js +78 -0
- package/src/tools/eslint/presets/frameworks/vanilla.js +16 -0
- package/src/tools/eslint/presets/frameworks/vue.js +125 -0
- package/src/tools/eslint/presets/imports.js +41 -0
- package/src/tools/eslint/presets/typescript.js +131 -0
- package/src/tools/prettier/README.md +398 -0
- package/src/tools/prettier/index.js +114 -0
- package/src/tools/prettier/presets/base.js +36 -0
- package/src/tools/prettier/presets/frameworks/astro.js +15 -0
- package/src/tools/prettier/presets/frameworks/react.js +15 -0
- package/src/tools/prettier/presets/frameworks/svelte.js +22 -0
- package/src/tools/prettier/presets/frameworks/vanilla.js +13 -0
- package/src/tools/prettier/presets/frameworks/vue.js +20 -0
- package/src/tools/prettier/presets/prettierignore.js +56 -0
- package/src/tools/semantic-release/CI_SETUP.md +66 -0
- package/src/tools/semantic-release/README.md +533 -0
- package/src/tools/semantic-release/index.js +130 -0
- package/src/tools/semantic-release/presets/default.js +37 -0
- package/src/tools/semantic-release/presets/library.js +58 -0
- package/src/tools/semantic-release/presets/monorepo.js +48 -0
- package/src/tools/semantic-release/templates/.gitlab-ci.yml +85 -0
- package/src/tools/semantic-release/templates/bitbucket-pipelines.yml +100 -0
- package/src/tools/semantic-release/templates/github-workflow.yml +107 -0
- package/src/tools/stylelint/README.md +425 -0
- package/src/tools/stylelint/index.js +191 -0
- package/src/tools/stylelint/presets/base.js +50 -0
- package/src/tools/stylelint/presets/css-modules.js +43 -0
- package/src/tools/stylelint/presets/frameworks/react.js +18 -0
- package/src/tools/stylelint/presets/frameworks/svelte.js +28 -0
- package/src/tools/stylelint/presets/frameworks/vanilla.js +14 -0
- package/src/tools/stylelint/presets/frameworks/vue.js +38 -0
- package/src/tools/stylelint/presets/scss.js +83 -0
- package/src/tools/stylelint/presets/tailwind.js +49 -0
- package/src/utils/package-reader.js +42 -0
|
@@ -0,0 +1,675 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @dimensional-innovations/tool-config CLI Setup Tool
|
|
5
|
+
*
|
|
6
|
+
* Interactive configuration generator for ESLint, Prettier, Stylelint, and semantic-release
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { writeFileSync, existsSync, readFileSync, mkdirSync, copyFileSync } from 'fs'
|
|
10
|
+
import { join, dirname } from 'path'
|
|
11
|
+
import { fileURLToPath } from 'url'
|
|
12
|
+
|
|
13
|
+
import prompts from 'prompts'
|
|
14
|
+
|
|
15
|
+
import { autoDetect } from '../src/detectors.js'
|
|
16
|
+
import { prettierIgnoreContent } from '../src/tools/prettier/index.js'
|
|
17
|
+
|
|
18
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
19
|
+
const __dirname = dirname(__filename)
|
|
20
|
+
|
|
21
|
+
const VERSION = '0.0.0-development'
|
|
22
|
+
|
|
23
|
+
// Parse CLI arguments
|
|
24
|
+
const args = process.argv.slice(2)
|
|
25
|
+
const flags = {
|
|
26
|
+
help: args.includes('--help') || args.includes('-h'),
|
|
27
|
+
version: args.includes('--version') || args.includes('-v'),
|
|
28
|
+
dryRun: args.includes('--dry-run') || args.includes('-d'),
|
|
29
|
+
all: args.includes('--all') || args.includes('-a'),
|
|
30
|
+
setupCI: args.includes('--setup-ci')
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Check for --ci flag with optional provider
|
|
34
|
+
const ciIndex = args.indexOf('--ci')
|
|
35
|
+
const ciProvider =
|
|
36
|
+
ciIndex !== -1 && args[ciIndex + 1] && !args[ciIndex + 1].startsWith('-')
|
|
37
|
+
? args[ciIndex + 1]
|
|
38
|
+
: null
|
|
39
|
+
const hasCI = args.includes('--ci')
|
|
40
|
+
|
|
41
|
+
// Single tool mode: setup-tool-config eslint (but not --ci provider value)
|
|
42
|
+
const singleTool = args.find(arg => !arg.startsWith('-') && arg !== ciProvider)
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Show help message
|
|
46
|
+
*/
|
|
47
|
+
function showHelp() {
|
|
48
|
+
console.log(`
|
|
49
|
+
đĻ @dimensional-innovations/tool-config Setup Tool
|
|
50
|
+
|
|
51
|
+
Usage:
|
|
52
|
+
setup-tool-config [tool] [options]
|
|
53
|
+
|
|
54
|
+
Tools:
|
|
55
|
+
eslint Setup ESLint only
|
|
56
|
+
prettier Setup Prettier only
|
|
57
|
+
stylelint Setup Stylelint only
|
|
58
|
+
semantic-release Setup semantic-release only
|
|
59
|
+
|
|
60
|
+
Options:
|
|
61
|
+
--all, -a Setup all tools (non-interactive)
|
|
62
|
+
--ci [provider] Setup CI/CD pipeline (gitlab, github, bitbucket)
|
|
63
|
+
--setup-ci Interactive CI/CD setup
|
|
64
|
+
--dry-run, -d Preview changes without writing files
|
|
65
|
+
--help, -h Show this help message
|
|
66
|
+
--version, -v Show version number
|
|
67
|
+
|
|
68
|
+
Examples:
|
|
69
|
+
setup-tool-config # Interactive mode
|
|
70
|
+
setup-tool-config eslint # Setup ESLint only
|
|
71
|
+
setup-tool-config --all # Setup all tools
|
|
72
|
+
setup-tool-config --dry-run # Preview without changes
|
|
73
|
+
setup-tool-config --ci gitlab # Setup GitLab CI/CD
|
|
74
|
+
setup-tool-config --ci github # Setup GitHub Actions
|
|
75
|
+
setup-tool-config --setup-ci # Interactive CI setup
|
|
76
|
+
setup-tool-config semantic-release --ci # Setup release + CI
|
|
77
|
+
|
|
78
|
+
For more information, visit:
|
|
79
|
+
https://gitlab.com/dimensional-innovations/tool-config
|
|
80
|
+
`)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Show version
|
|
85
|
+
*/
|
|
86
|
+
function showVersion() {
|
|
87
|
+
console.log(`@dimensional-innovations/tool-config v${VERSION}`)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Generate config file content for a tool
|
|
92
|
+
*/
|
|
93
|
+
function generateConfigContent(tool) {
|
|
94
|
+
const configs = {
|
|
95
|
+
eslint: `import { createConfig } from '@dimensional-innovations/tool-config'
|
|
96
|
+
|
|
97
|
+
export default await createConfig('eslint')
|
|
98
|
+
`,
|
|
99
|
+
prettier: `import { createConfig } from '@dimensional-innovations/tool-config'
|
|
100
|
+
|
|
101
|
+
export default createConfig('prettier')
|
|
102
|
+
`,
|
|
103
|
+
stylelint: `import { createConfig } from '@dimensional-innovations/tool-config'
|
|
104
|
+
|
|
105
|
+
export default createConfig('stylelint')
|
|
106
|
+
`,
|
|
107
|
+
'semantic-release': `import { createConfig } from '@dimensional-innovations/tool-config'
|
|
108
|
+
|
|
109
|
+
export default createConfig('semantic-release')
|
|
110
|
+
`
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return configs[tool] || ''
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Get config filename for a tool
|
|
118
|
+
*/
|
|
119
|
+
function getConfigFilename(tool) {
|
|
120
|
+
const filenames = {
|
|
121
|
+
eslint: 'eslint.config.js',
|
|
122
|
+
prettier: 'prettier.config.js',
|
|
123
|
+
stylelint: 'stylelint.config.js',
|
|
124
|
+
'semantic-release': 'release.config.js'
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return filenames[tool] || `${tool}.config.js`
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Get npm scripts for a tool
|
|
132
|
+
*/
|
|
133
|
+
function getToolScripts(tool) {
|
|
134
|
+
const scripts = {
|
|
135
|
+
eslint: {
|
|
136
|
+
lint: 'eslint .',
|
|
137
|
+
'lint:fix': 'eslint --fix .'
|
|
138
|
+
},
|
|
139
|
+
prettier: {
|
|
140
|
+
'prettier:fix': 'prettier --write .',
|
|
141
|
+
prettier: 'prettier --check .'
|
|
142
|
+
},
|
|
143
|
+
stylelint: {
|
|
144
|
+
style: 'stylelint "**/*.css"',
|
|
145
|
+
'style:fix': 'stylelint "**/*.css" --fix'
|
|
146
|
+
},
|
|
147
|
+
'semantic-release': {
|
|
148
|
+
release: 'semantic-release'
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return scripts[tool] || {}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Write config file
|
|
157
|
+
*/
|
|
158
|
+
function writeConfigFile(tool, cwd, dryRun = false) {
|
|
159
|
+
const filename = getConfigFilename(tool)
|
|
160
|
+
const filepath = join(cwd, filename)
|
|
161
|
+
const content = generateConfigContent(tool)
|
|
162
|
+
|
|
163
|
+
if (existsSync(filepath)) {
|
|
164
|
+
console.log(` â ī¸ ${filename} already exists - skipping`)
|
|
165
|
+
return false
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (dryRun) {
|
|
169
|
+
console.log(` đ Would create: ${filename}`)
|
|
170
|
+
|
|
171
|
+
// Prettier also creates .prettierignore
|
|
172
|
+
if (tool === 'prettier') {
|
|
173
|
+
const ignoreFile = '.prettierignore'
|
|
174
|
+
const ignoreExists = existsSync(join(cwd, ignoreFile))
|
|
175
|
+
if (!ignoreExists) {
|
|
176
|
+
console.log(` đ Would create: ${ignoreFile}`)
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return true
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
writeFileSync(filepath, content, 'utf8')
|
|
185
|
+
console.log(` â
Created: ${filename}`)
|
|
186
|
+
|
|
187
|
+
// Prettier also creates .prettierignore
|
|
188
|
+
if (tool === 'prettier') {
|
|
189
|
+
const ignoreFile = '.prettierignore'
|
|
190
|
+
const ignorePath = join(cwd, ignoreFile)
|
|
191
|
+
|
|
192
|
+
if (!existsSync(ignorePath)) {
|
|
193
|
+
writeFileSync(ignorePath, prettierIgnoreContent, 'utf8')
|
|
194
|
+
console.log(` â
Created: ${ignoreFile}`)
|
|
195
|
+
} else {
|
|
196
|
+
console.log(` â ī¸ ${ignoreFile} already exists - skipping`)
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return true
|
|
201
|
+
} catch (error) {
|
|
202
|
+
console.error(` â Failed to create ${filename}:`, error.message)
|
|
203
|
+
return false
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Update package.json with scripts
|
|
209
|
+
*/
|
|
210
|
+
function updatePackageJsonScripts(tools, cwd, dryRun = false) {
|
|
211
|
+
const packageJsonPath = join(cwd, 'package.json')
|
|
212
|
+
|
|
213
|
+
if (!existsSync(packageJsonPath)) {
|
|
214
|
+
console.log(' â ī¸ No package.json found - skipping script injection')
|
|
215
|
+
return
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
try {
|
|
219
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8'))
|
|
220
|
+
|
|
221
|
+
if (!packageJson.scripts) {
|
|
222
|
+
packageJson.scripts = {}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const scriptsToAdd = {}
|
|
226
|
+
for (const tool of tools) {
|
|
227
|
+
const toolScripts = getToolScripts(tool)
|
|
228
|
+
for (const [name, command] of Object.entries(toolScripts)) {
|
|
229
|
+
if (!packageJson.scripts[name]) {
|
|
230
|
+
scriptsToAdd[name] = command
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (Object.keys(scriptsToAdd).length === 0) {
|
|
236
|
+
console.log(' âšī¸ All scripts already exist in package.json')
|
|
237
|
+
return
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (dryRun) {
|
|
241
|
+
console.log(' đ Would add scripts to package.json:')
|
|
242
|
+
for (const [name, command] of Object.entries(scriptsToAdd)) {
|
|
243
|
+
console.log(` "${name}": "${command}"`)
|
|
244
|
+
}
|
|
245
|
+
return
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
Object.assign(packageJson.scripts, scriptsToAdd)
|
|
249
|
+
|
|
250
|
+
writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\n`, 'utf8')
|
|
251
|
+
|
|
252
|
+
console.log(' â
Updated package.json with scripts:')
|
|
253
|
+
for (const name of Object.keys(scriptsToAdd)) {
|
|
254
|
+
console.log(` - ${name}`)
|
|
255
|
+
}
|
|
256
|
+
} catch (error) {
|
|
257
|
+
console.error(' â Failed to update package.json:', error.message)
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Get CI filename and path for a git provider
|
|
263
|
+
*/
|
|
264
|
+
function getCIFileInfo(provider) {
|
|
265
|
+
const ciFiles = {
|
|
266
|
+
gitlab: {
|
|
267
|
+
filename: '.gitlab-ci.yml',
|
|
268
|
+
destination: '.gitlab-ci.yml',
|
|
269
|
+
template: '.gitlab-ci.yml'
|
|
270
|
+
},
|
|
271
|
+
github: {
|
|
272
|
+
filename: 'ci.yml',
|
|
273
|
+
destination: '.github/workflows/ci.yml',
|
|
274
|
+
template: 'github-workflow.yml',
|
|
275
|
+
needsDir: true
|
|
276
|
+
},
|
|
277
|
+
bitbucket: {
|
|
278
|
+
filename: 'bitbucket-pipelines.yml',
|
|
279
|
+
destination: 'bitbucket-pipelines.yml',
|
|
280
|
+
template: 'bitbucket-pipelines.yml'
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
return ciFiles[provider] || null
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Get environment variable instructions for a git provider
|
|
289
|
+
*/
|
|
290
|
+
function getCIInstructions(provider) {
|
|
291
|
+
const instructions = {
|
|
292
|
+
gitlab: `
|
|
293
|
+
â ī¸ Configuration Required:
|
|
294
|
+
Add these CI/CD variables in GitLab Settings > CI/CD > Variables:
|
|
295
|
+
- GL_TOKEN: GitLab Personal Access Token (with api scope)
|
|
296
|
+
- NPM_TOKEN: npm authentication token
|
|
297
|
+
|
|
298
|
+
Then push to main branch to trigger automated releases.`,
|
|
299
|
+
github: `
|
|
300
|
+
â ī¸ Configuration Required:
|
|
301
|
+
Add these secrets in GitHub Settings > Secrets and variables > Actions:
|
|
302
|
+
- GITHUB_TOKEN: Automatically provided by GitHub Actions
|
|
303
|
+
- NPM_TOKEN: npm authentication token
|
|
304
|
+
|
|
305
|
+
Then push to main branch to trigger automated releases.`,
|
|
306
|
+
bitbucket: `
|
|
307
|
+
â ī¸ Configuration Required:
|
|
308
|
+
Add this repository variable in Bitbucket Settings > Pipelines > Repository variables:
|
|
309
|
+
- NPM_TOKEN: npm authentication token
|
|
310
|
+
|
|
311
|
+
Then push to main branch to trigger automated releases.`
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return instructions[provider] || ''
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Copy CI/CD template
|
|
319
|
+
*/
|
|
320
|
+
function copyCITemplate(provider, cwd, dryRun = false) {
|
|
321
|
+
if (!provider || provider === 'unknown') {
|
|
322
|
+
console.log(' â ī¸ Could not detect git provider - skipping CI setup')
|
|
323
|
+
console.log(' đĄ You can manually copy templates from:')
|
|
324
|
+
console.log(
|
|
325
|
+
' node_modules/@dimensional-innovations/tool-config/src/tools/semantic-release/templates/'
|
|
326
|
+
)
|
|
327
|
+
return false
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const ciInfo = getCIFileInfo(provider)
|
|
331
|
+
|
|
332
|
+
if (!ciInfo) {
|
|
333
|
+
console.log(` â ī¸ Unsupported git provider: ${provider}`)
|
|
334
|
+
return false
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
const destPath = join(cwd, ciInfo.destination)
|
|
338
|
+
const destDir = dirname(destPath)
|
|
339
|
+
|
|
340
|
+
// Check if CI file already exists
|
|
341
|
+
if (existsSync(destPath)) {
|
|
342
|
+
console.log(` â ī¸ ${ciInfo.destination} already exists - skipping`)
|
|
343
|
+
return false
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
if (dryRun) {
|
|
347
|
+
console.log(` đ Would create: ${ciInfo.destination}`)
|
|
348
|
+
if (ciInfo.needsDir && !existsSync(destDir)) {
|
|
349
|
+
console.log(` đ Would create directory: ${dirname(ciInfo.destination)}`)
|
|
350
|
+
}
|
|
351
|
+
return true
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
try {
|
|
355
|
+
// Create directory if needed
|
|
356
|
+
if (ciInfo.needsDir && !existsSync(destDir)) {
|
|
357
|
+
mkdirSync(destDir, { recursive: true })
|
|
358
|
+
console.log(` â
Created directory: ${dirname(ciInfo.destination)}`)
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// Copy template
|
|
362
|
+
const templatePath = join(
|
|
363
|
+
__dirname,
|
|
364
|
+
'..',
|
|
365
|
+
'src',
|
|
366
|
+
'tools',
|
|
367
|
+
'semantic-release',
|
|
368
|
+
'templates',
|
|
369
|
+
ciInfo.template
|
|
370
|
+
)
|
|
371
|
+
copyFileSync(templatePath, destPath)
|
|
372
|
+
console.log(` â
Created: ${ciInfo.destination}`)
|
|
373
|
+
|
|
374
|
+
// Show configuration instructions
|
|
375
|
+
console.log(getCIInstructions(provider))
|
|
376
|
+
|
|
377
|
+
console.log('\n đ For more details, see:')
|
|
378
|
+
console.log(
|
|
379
|
+
' node_modules/@dimensional-innovations/tool-config/src/tools/semantic-release/CI_SETUP.md'
|
|
380
|
+
)
|
|
381
|
+
|
|
382
|
+
return true
|
|
383
|
+
} catch (error) {
|
|
384
|
+
console.error(` â Failed to copy CI template:`, error.message)
|
|
385
|
+
return false
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Setup tools
|
|
391
|
+
*/
|
|
392
|
+
function setupTools(tools, cwd, dryRun = false) {
|
|
393
|
+
console.log('')
|
|
394
|
+
console.log('đ Generating configuration files...')
|
|
395
|
+
console.log('')
|
|
396
|
+
|
|
397
|
+
for (const tool of tools) {
|
|
398
|
+
console.log(`${tool}:`)
|
|
399
|
+
writeConfigFile(tool, cwd, dryRun)
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
console.log('')
|
|
403
|
+
console.log('đĻ Updating package.json scripts...')
|
|
404
|
+
console.log('')
|
|
405
|
+
updatePackageJsonScripts(tools, cwd, dryRun)
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Main CLI function
|
|
410
|
+
*/
|
|
411
|
+
async function main() {
|
|
412
|
+
// Handle flags
|
|
413
|
+
if (flags.help) {
|
|
414
|
+
showHelp()
|
|
415
|
+
process.exit(0)
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
if (flags.version) {
|
|
419
|
+
showVersion()
|
|
420
|
+
process.exit(0)
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
const cwd = process.cwd()
|
|
424
|
+
|
|
425
|
+
// Show banner
|
|
426
|
+
console.log('')
|
|
427
|
+
console.log('đĻ @dimensional-innovations/tool-config Setup')
|
|
428
|
+
console.log('â'.repeat(50))
|
|
429
|
+
console.log('')
|
|
430
|
+
|
|
431
|
+
// Auto-detect project
|
|
432
|
+
const detected = autoDetect(cwd)
|
|
433
|
+
console.log('đ Detected project configuration:')
|
|
434
|
+
console.log(` Framework: ${detected.framework}`)
|
|
435
|
+
console.log(` Environment: ${detected.environment}`)
|
|
436
|
+
console.log(` TypeScript: ${detected.typescript ? 'Yes' : 'No'}`)
|
|
437
|
+
console.log(` Git Provider: ${detected.gitProvider || 'Unknown'}`)
|
|
438
|
+
console.log('')
|
|
439
|
+
|
|
440
|
+
// Handle standalone --setup-ci flag
|
|
441
|
+
if (flags.setupCI) {
|
|
442
|
+
console.log('đ CI/CD Pipeline Setup')
|
|
443
|
+
console.log('')
|
|
444
|
+
|
|
445
|
+
let provider = detected.gitProvider
|
|
446
|
+
|
|
447
|
+
// If provider not detected or unknown, prompt for it
|
|
448
|
+
if (!provider || provider === 'unknown') {
|
|
449
|
+
const providerResponse = await prompts({
|
|
450
|
+
type: 'select',
|
|
451
|
+
name: 'provider',
|
|
452
|
+
message: 'Which CI/CD platform would you like to use?',
|
|
453
|
+
choices: [
|
|
454
|
+
{ title: 'GitLab CI', value: 'gitlab' },
|
|
455
|
+
{ title: 'GitHub Actions', value: 'github' },
|
|
456
|
+
{ title: 'Bitbucket Pipelines', value: 'bitbucket' }
|
|
457
|
+
]
|
|
458
|
+
})
|
|
459
|
+
|
|
460
|
+
if (!providerResponse.provider) {
|
|
461
|
+
console.log('â No provider selected. Exiting.')
|
|
462
|
+
process.exit(0)
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
provider = providerResponse.provider
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
console.log('đ Setting up CI/CD...')
|
|
469
|
+
console.log('')
|
|
470
|
+
copyCITemplate(provider, cwd, flags.dryRun)
|
|
471
|
+
|
|
472
|
+
console.log('')
|
|
473
|
+
if (flags.dryRun) {
|
|
474
|
+
console.log('âšī¸ Dry run mode - no files were modified')
|
|
475
|
+
} else {
|
|
476
|
+
console.log('â
CI/CD setup complete!')
|
|
477
|
+
}
|
|
478
|
+
console.log('')
|
|
479
|
+
process.exit(0)
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
// Handle --ci flag with provider
|
|
483
|
+
if (hasCI && ciProvider) {
|
|
484
|
+
const validProviders = ['gitlab', 'github', 'bitbucket']
|
|
485
|
+
|
|
486
|
+
if (!validProviders.includes(ciProvider)) {
|
|
487
|
+
console.error(`â Unknown provider: ${ciProvider}`)
|
|
488
|
+
console.error(`Valid providers: ${validProviders.join(', ')}`)
|
|
489
|
+
process.exit(1)
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
console.log('đ CI/CD Pipeline Setup')
|
|
493
|
+
console.log('')
|
|
494
|
+
console.log('đ Setting up CI/CD...')
|
|
495
|
+
console.log('')
|
|
496
|
+
copyCITemplate(ciProvider, cwd, flags.dryRun)
|
|
497
|
+
|
|
498
|
+
console.log('')
|
|
499
|
+
if (flags.dryRun) {
|
|
500
|
+
console.log('âšī¸ Dry run mode - no files were modified')
|
|
501
|
+
} else {
|
|
502
|
+
console.log('â
CI/CD setup complete!')
|
|
503
|
+
}
|
|
504
|
+
console.log('')
|
|
505
|
+
process.exit(0)
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// Handle --all flag
|
|
509
|
+
if (flags.all) {
|
|
510
|
+
const tools = ['eslint', 'prettier', 'stylelint', 'semantic-release']
|
|
511
|
+
setupTools(tools, cwd, flags.dryRun)
|
|
512
|
+
console.log('')
|
|
513
|
+
if (flags.dryRun) {
|
|
514
|
+
console.log('âšī¸ Dry run mode - no files were modified')
|
|
515
|
+
console.log('Run without --dry-run to apply changes')
|
|
516
|
+
} else {
|
|
517
|
+
console.log('â
Setup complete!')
|
|
518
|
+
}
|
|
519
|
+
console.log('')
|
|
520
|
+
process.exit(0)
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// Handle single tool mode
|
|
524
|
+
if (singleTool) {
|
|
525
|
+
const validTools = ['eslint', 'prettier', 'stylelint', 'semantic-release']
|
|
526
|
+
|
|
527
|
+
if (!validTools.includes(singleTool)) {
|
|
528
|
+
console.error(`â Unknown tool: ${singleTool}`)
|
|
529
|
+
console.error(`Valid tools: ${validTools.join(', ')}`)
|
|
530
|
+
process.exit(1)
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
setupTools([singleTool], cwd, flags.dryRun)
|
|
534
|
+
|
|
535
|
+
// If semantic-release + --ci flag, setup CI
|
|
536
|
+
if (singleTool === 'semantic-release' && hasCI) {
|
|
537
|
+
console.log('')
|
|
538
|
+
console.log('đ CI/CD Pipeline Setup')
|
|
539
|
+
console.log('')
|
|
540
|
+
|
|
541
|
+
let provider = ciProvider || detected.gitProvider
|
|
542
|
+
|
|
543
|
+
// If no provider specified and can't detect, prompt
|
|
544
|
+
if (!provider || provider === 'unknown') {
|
|
545
|
+
const providerResponse = await prompts({
|
|
546
|
+
type: 'select',
|
|
547
|
+
name: 'provider',
|
|
548
|
+
message: 'Which CI/CD platform would you like to use?',
|
|
549
|
+
choices: [
|
|
550
|
+
{ title: 'GitLab CI', value: 'gitlab' },
|
|
551
|
+
{ title: 'GitHub Actions', value: 'github' },
|
|
552
|
+
{ title: 'Bitbucket Pipelines', value: 'bitbucket' }
|
|
553
|
+
]
|
|
554
|
+
})
|
|
555
|
+
|
|
556
|
+
if (!providerResponse.provider) {
|
|
557
|
+
console.log('â ī¸ Skipping CI/CD setup.')
|
|
558
|
+
console.log('')
|
|
559
|
+
process.exit(0)
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
provider = providerResponse.provider
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
console.log('đ Setting up CI/CD...')
|
|
566
|
+
console.log('')
|
|
567
|
+
copyCITemplate(provider, cwd, flags.dryRun)
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
console.log('')
|
|
571
|
+
if (flags.dryRun) {
|
|
572
|
+
console.log('âšī¸ Dry run mode - no files were modified')
|
|
573
|
+
console.log('Run without --dry-run to apply changes')
|
|
574
|
+
} else {
|
|
575
|
+
console.log('â
Setup complete!')
|
|
576
|
+
}
|
|
577
|
+
console.log('')
|
|
578
|
+
process.exit(0)
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// Interactive mode
|
|
582
|
+
const response = await prompts([
|
|
583
|
+
{
|
|
584
|
+
type: 'multiselect',
|
|
585
|
+
name: 'tools',
|
|
586
|
+
message: 'Which tools would you like to setup?',
|
|
587
|
+
choices: [
|
|
588
|
+
{ title: 'ESLint (JavaScript/TypeScript linting)', value: 'eslint', selected: true },
|
|
589
|
+
{ title: 'Prettier (Code formatting)', value: 'prettier', selected: true },
|
|
590
|
+
{ title: 'Stylelint (CSS/style linting)', value: 'stylelint', selected: false },
|
|
591
|
+
{
|
|
592
|
+
title: 'semantic-release (Automated versioning)',
|
|
593
|
+
value: 'semantic-release',
|
|
594
|
+
selected: false
|
|
595
|
+
}
|
|
596
|
+
],
|
|
597
|
+
hint: '- Space to select. Return to submit'
|
|
598
|
+
}
|
|
599
|
+
])
|
|
600
|
+
|
|
601
|
+
if (!response.tools || response.tools.length === 0) {
|
|
602
|
+
console.log('')
|
|
603
|
+
console.log('â No tools selected. Exiting.')
|
|
604
|
+
process.exit(0)
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
setupTools(response.tools, cwd, flags.dryRun)
|
|
608
|
+
|
|
609
|
+
// If semantic-release selected, prompt for CI setup
|
|
610
|
+
if (response.tools.includes('semantic-release')) {
|
|
611
|
+
console.log('')
|
|
612
|
+
console.log('đ CI/CD Pipeline Setup')
|
|
613
|
+
console.log('')
|
|
614
|
+
|
|
615
|
+
const ciResponse = await prompts({
|
|
616
|
+
type: 'confirm',
|
|
617
|
+
name: 'setupCI',
|
|
618
|
+
message: 'Setup CI/CD pipeline for automated releases?',
|
|
619
|
+
initial: true
|
|
620
|
+
})
|
|
621
|
+
|
|
622
|
+
if (ciResponse.setupCI) {
|
|
623
|
+
let provider = detected.gitProvider
|
|
624
|
+
|
|
625
|
+
// If provider not detected or unknown, prompt for it
|
|
626
|
+
if (!provider || provider === 'unknown') {
|
|
627
|
+
const providerResponse = await prompts({
|
|
628
|
+
type: 'select',
|
|
629
|
+
name: 'provider',
|
|
630
|
+
message: 'Which CI/CD platform would you like to use?',
|
|
631
|
+
choices: [
|
|
632
|
+
{ title: 'GitLab CI', value: 'gitlab' },
|
|
633
|
+
{ title: 'GitHub Actions', value: 'github' },
|
|
634
|
+
{ title: 'Bitbucket Pipelines', value: 'bitbucket' }
|
|
635
|
+
]
|
|
636
|
+
})
|
|
637
|
+
|
|
638
|
+
if (!providerResponse.provider) {
|
|
639
|
+
console.log('â ī¸ Skipping CI/CD setup.')
|
|
640
|
+
} else {
|
|
641
|
+
provider = providerResponse.provider
|
|
642
|
+
console.log('đ Setting up CI/CD...')
|
|
643
|
+
console.log('')
|
|
644
|
+
copyCITemplate(provider, cwd, flags.dryRun)
|
|
645
|
+
}
|
|
646
|
+
} else {
|
|
647
|
+
console.log('đ Setting up CI/CD...')
|
|
648
|
+
console.log('')
|
|
649
|
+
copyCITemplate(provider, cwd, flags.dryRun)
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
console.log('')
|
|
655
|
+
if (flags.dryRun) {
|
|
656
|
+
console.log('âšī¸ Dry run mode - no files were modified')
|
|
657
|
+
console.log('Run without --dry-run to apply changes')
|
|
658
|
+
} else {
|
|
659
|
+
console.log('â
Setup complete!')
|
|
660
|
+
console.log('')
|
|
661
|
+
console.log('Next steps:')
|
|
662
|
+
console.log(' 1. Review the generated config files')
|
|
663
|
+
console.log(' 2. Install peer dependencies if needed')
|
|
664
|
+
console.log(' 3. Run: npm run lint (or other added scripts)')
|
|
665
|
+
}
|
|
666
|
+
console.log('')
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
// Run CLI
|
|
670
|
+
main().catch(error => {
|
|
671
|
+
console.error('')
|
|
672
|
+
console.error('â Error:', error.message)
|
|
673
|
+
console.error('')
|
|
674
|
+
process.exit(1)
|
|
675
|
+
})
|