commit-pack 1.1.5 → 1.1.7

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/bin/index.mjs CHANGED
@@ -24,6 +24,26 @@ const printBanner = () => {
24
24
  const __filename = fileURLToPath(import.meta.url)
25
25
  const __dirname = path.dirname(__filename)
26
26
 
27
+ // 解析命令行参数
28
+ const args = process.argv.slice(2)
29
+ const workspaceArgIndex = args.findIndex(
30
+ (arg) => arg.startsWith('--workspace=') || arg.startsWith('-w=')
31
+ )
32
+ let workspaceName = ''
33
+ if (workspaceArgIndex !== -1) {
34
+ const arg = args[workspaceArgIndex]
35
+ workspaceName = arg.split('=')[1]
36
+ } else {
37
+ // 查找是否有单独的 -w 或 --workspace 参数
38
+ const wIndex = args.findIndex((arg) => arg === '-w')
39
+ const workspaceIndex = args.findIndex((arg) => arg === '--workspace')
40
+ if (wIndex !== -1 && wIndex + 1 < args.length) {
41
+ workspaceName = args[wIndex + 1]
42
+ } else if (workspaceIndex !== -1 && workspaceIndex + 1 < args.length) {
43
+ workspaceName = args[workspaceIndex + 1]
44
+ }
45
+ }
46
+
27
47
  // 向上查找带锁文件的根目录
28
48
  function findProjectRootWithLockFile() {
29
49
  let dir = __dirname
@@ -56,22 +76,99 @@ function detectPackageManager() {
56
76
  }
57
77
 
58
78
  const packageManager = detectPackageManager()
79
+
80
+ // 计算实际的工作目录
81
+ let actualProjectRoot = projectRoot
82
+ if (workspaceName) {
83
+ const packageJsonContent = JSON.parse(
84
+ fs.readFileSync(path.join(projectRoot, 'package.json'), 'utf8')
85
+ )
86
+
87
+ // 根据包管理器确定工作spaces路径
88
+ let workspaces = []
89
+ if (packageJsonContent.workspaces) {
90
+ if (Array.isArray(packageJsonContent.workspaces)) {
91
+ workspaces = packageJsonContent.workspaces
92
+ } else if (packageJsonContent.workspaces.packages) {
93
+ workspaces = packageJsonContent.workspaces.packages
94
+ }
95
+ }
96
+
97
+ // 查找workspace包的路径
98
+ if (workspaces.length > 0) {
99
+ for (const workspacePattern of workspaces) {
100
+ // 处理通配符模式,例如 'packages/*'
101
+ if (workspacePattern.includes('*')) {
102
+ const basePath = workspacePattern.replace('/*', '')
103
+ const packagesDir = path.join(projectRoot, basePath)
104
+ if (fs.existsSync(packagesDir)) {
105
+ const packageDirs = fs.readdirSync(packagesDir)
106
+ for (const dir of packageDirs) {
107
+ const dirPath = path.join(packagesDir, dir)
108
+ if (fs.statSync(dirPath).isDirectory()) {
109
+ try {
110
+ const pkgPath = path.join(dirPath, 'package.json')
111
+ if (fs.existsSync(pkgPath)) {
112
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'))
113
+ if (pkg.name === workspaceName || dir === workspaceName) {
114
+ actualProjectRoot = dirPath
115
+ break
116
+ }
117
+ }
118
+ } catch (e) {
119
+ console.log(e)
120
+ }
121
+ }
122
+ }
123
+ }
124
+ } else {
125
+ // 直接路径匹配
126
+ const dirPath = path.join(projectRoot, workspacePattern)
127
+ if (fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory()) {
128
+ try {
129
+ const pkgPath = path.join(dirPath, 'package.json')
130
+ if (fs.existsSync(pkgPath)) {
131
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'))
132
+ if (
133
+ pkg.name === workspaceName ||
134
+ path.basename(dirPath) === workspaceName
135
+ ) {
136
+ actualProjectRoot = dirPath
137
+ break
138
+ }
139
+ }
140
+ } catch (e) {
141
+ console.log(e)
142
+ }
143
+ }
144
+ }
145
+ }
146
+ }
147
+ }
148
+
59
149
  console.log('')
60
150
  printBanner()
61
151
  console.log('')
62
152
  console.log('')
63
153
  console.log(`🍀 包管理器:${packageManager}`)
64
- console.log(`📁 根目录:${projectRoot}`)
154
+ console.log(`📁 根目录:${actualProjectRoot}`)
155
+ if (workspaceName) {
156
+ console.log(`📦 工作空间: ${workspaceName}`)
157
+ }
65
158
 
66
- const packageJsonPath = path.join(projectRoot, 'package.json')
159
+ const packageJsonPath = path.join(actualProjectRoot, 'package.json')
67
160
  const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'))
68
161
 
69
162
  // 检查是否已经初始化过
70
- const initFlagPath = path.join(projectRoot, '.commit-pack-init')
163
+ const initFlagPath = path.join(actualProjectRoot, '.commit-pack-init')
71
164
  if (fs.existsSync(initFlagPath)) {
165
+ console.log(log.warn('⚠️ 该工作空间/项目已被初始化,跳过初始化'))
72
166
  process.exit(0)
73
167
  }
74
168
 
169
+ // 回滚机制:记录初始状态
170
+ const initialPackageJson = JSON.stringify(packageJson, null, 2)
171
+
75
172
  // 确保 devDependencies 存在
76
173
  if (!packageJson.devDependencies) {
77
174
  packageJson.devDependencies = {}
@@ -113,55 +210,57 @@ for (const [dep, version] of Object.entries(devDependenciesWithVersion)) {
113
210
  }
114
211
  }
115
212
 
116
- installWithProgress(dependenciesToInstall, packageManager, projectRoot)
117
-
118
- let isGitRepo = false
119
-
120
213
  try {
121
- // 获取 Git 仓库的顶级目录
122
- const gitTopLevel = execSync('git rev-parse --show-toplevel', { cwd: projectRoot })
123
- .toString()
124
- .trim()
125
- // 比较顶级目录与当前项目目录
126
- if (path.resolve(gitTopLevel) === path.resolve(projectRoot)) {
127
- isGitRepo = true
128
- } else {
214
+ installWithProgress(dependenciesToInstall, packageManager, actualProjectRoot)
215
+
216
+ let isGitRepo = false
217
+
218
+ try {
219
+ // 获取 Git 仓库的顶级目录
220
+ const gitTopLevel = execSync('git rev-parse --show-toplevel', {
221
+ cwd: actualProjectRoot
222
+ })
223
+ .toString()
224
+ .trim()
225
+ // 比较顶级目录与当前项目目录
226
+ if (path.resolve(gitTopLevel) === path.resolve(actualProjectRoot)) {
227
+ isGitRepo = true
228
+ } else {
229
+ isGitRepo = false
230
+ }
231
+ } catch {
129
232
  isGitRepo = false
130
233
  }
131
- } catch {
132
- isGitRepo = false
133
- }
134
234
 
135
- if (isGitRepo) {
136
- console.log(log.success('👍 Git仓库已存在'))
137
- } else {
138
- console.log(log.warn('👌 Git仓库初始化...'))
139
- execSync('git init', { stdio: 'inherit', cwd: projectRoot })
140
- }
235
+ if (isGitRepo) {
236
+ console.log(log.success('👍 Git仓库已存在'))
237
+ } else {
238
+ console.log(log.warn('👌 Git仓库初始化...'))
239
+ execSync('git init', { stdio: 'inherit', cwd: actualProjectRoot })
240
+ }
141
241
 
142
- // 根据包管理器,执行对应的 Husky 初始化命令
143
- let huskyInitCommand = ''
144
- switch (packageManager) {
145
- case 'pnpm':
146
- huskyInitCommand = 'pnpm exec husky init'
147
- break
148
- case 'yarn':
149
- huskyInitCommand = 'yarn dlx husky init'
150
- break
151
- case 'bun':
152
- huskyInitCommand = 'bunx husky init'
153
- break
154
- default:
155
- huskyInitCommand = 'npx husky init'
156
- break
157
- }
242
+ // 根据包管理器,执行对应的 Husky 初始化命令
243
+ let huskyInitCommand = ''
244
+ switch (packageManager) {
245
+ case 'pnpm':
246
+ huskyInitCommand = 'pnpm exec husky init'
247
+ break
248
+ case 'yarn':
249
+ huskyInitCommand = 'yarn dlx husky init'
250
+ break
251
+ case 'bun':
252
+ huskyInitCommand = 'bunx husky init'
253
+ break
254
+ default:
255
+ huskyInitCommand = 'npx husky init'
256
+ break
257
+ }
158
258
 
159
- console.log(chalk.green(`🐶 Husky初始化...`))
160
- execSync(huskyInitCommand, { stdio: 'inherit', cwd: projectRoot })
259
+ console.log(chalk.green(`🐶 Husky初始化...`))
260
+ execSync(huskyInitCommand, { stdio: 'inherit', cwd: actualProjectRoot })
161
261
 
162
- // 执行 setup-script 中的所有文件
163
- console.log('🚀 创建配置文件...')
164
- try {
262
+ // 执行 setup-script 中的所有文件
263
+ console.log('🚀 创建配置文件...')
165
264
  const setupScripts = [
166
265
  'prettier.sh',
167
266
  'lintstagedrc.sh',
@@ -174,61 +273,153 @@ try {
174
273
 
175
274
  for (const script of setupScripts) {
176
275
  const scriptPath = path.join(__dirname, '..', 'setup-script', script)
177
- execSync(`sh ${scriptPath}`, { stdio: 'inherit', cwd: projectRoot })
276
+ execSync(`sh ${scriptPath}`, { stdio: 'inherit', cwd: actualProjectRoot })
178
277
  }
179
- } catch (error) {
180
- console.error(log.warn('❌ 文件创建出错'), error)
181
- }
182
278
 
183
- // 创建或更新脚本
184
- if (!packageJson.scripts) {
185
- packageJson.scripts = {}
186
- console.log('🔥 创建或更新脚本...')
187
- }
279
+ // 创建或更新脚本
280
+ if (!packageJson.scripts) {
281
+ packageJson.scripts = {}
282
+ console.log('🔥 创建或更新脚本...')
283
+ }
284
+
285
+ let modified = false
286
+
287
+ if (!packageJson.scripts.lint) {
288
+ if (workspaceName) {
289
+ // 为workspace项目使用工作空间命令
290
+ if (packageManager === 'pnpm') {
291
+ packageJson.scripts.lint = `pnpm -F ${workspaceName} exec eslint ./ --ext .ts,.tsx,.json --max-warnings=0`
292
+ } else if (packageManager === 'yarn') {
293
+ packageJson.scripts.lint = `yarn workspace ${workspaceName} exec eslint ./ --ext .ts,.tsx,.json --max-warnings=0`
294
+ } else {
295
+ packageJson.scripts.lint = 'eslint ./ --ext .ts,.tsx,.json --max-warnings=0'
296
+ }
297
+ } else {
298
+ packageJson.scripts.lint = 'eslint ./ --ext .ts,.tsx,.json --max-warnings=0'
299
+ }
300
+ console.log(log.success('✅ 已添加 "lint" 至 package.json'))
301
+ modified = true
302
+ } else {
303
+ console.log(log.warn('⚠️ package.json 中已存在 "lint" 未作修改'))
304
+ }
188
305
 
189
- let modified = false
306
+ if (!packageJson.scripts.format) {
307
+ if (workspaceName) {
308
+ // 为workspace项目使用工作空间命令
309
+ if (packageManager === 'pnpm') {
310
+ packageJson.scripts.format = `pnpm -F ${workspaceName} exec prettier --config .prettierrc '.' --write`
311
+ } else if (packageManager === 'yarn') {
312
+ packageJson.scripts.format = `yarn workspace ${workspaceName} exec prettier --config .prettierrc '.' --write`
313
+ } else {
314
+ packageJson.scripts.format = "prettier --config .prettierrc '.' --write"
315
+ }
316
+ } else {
317
+ packageJson.scripts.format = "prettier --config .prettierrc '.' --write"
318
+ }
319
+ console.log(log.success('✅ 已添加 "format" 至 package.json'))
320
+ modified = true
321
+ } else {
322
+ console.log(log.warn('⚠️ package.json 中已存在 "format" 未作修改'))
323
+ }
190
324
 
191
- if (!packageJson.scripts.lint) {
192
- packageJson.scripts.lint = 'eslint ./ --ext .ts,.tsx,.json --max-warnings=0'
193
- console.log(log.success('✅ 已添加 "lint" 至 package.json'))
325
+ // 添加或更新 "commit" 脚本
326
+ if (workspaceName) {
327
+ // 为workspace项目使用工作空间命令
328
+ if (packageManager === 'pnpm') {
329
+ packageJson.scripts.commit = `pnpm -F ${workspaceName} exec cz`
330
+ } else if (packageManager === 'yarn') {
331
+ packageJson.scripts.commit = `yarn workspace ${workspaceName} exec cz`
332
+ } else {
333
+ packageJson.scripts.commit = 'cz'
334
+ }
335
+ } else {
336
+ packageJson.scripts.commit = 'cz'
337
+ }
338
+ console.log(log.success('✅ 已添加 "commit" 至 package.json'))
194
339
  modified = true
195
- } else {
196
- console.log(log.warn('⚠️ package.json 中已存在 "lint" 未作修改'))
197
- }
198
340
 
199
- if (!packageJson.scripts.format) {
200
- packageJson.scripts.format = "prettier --config .prettierrc '.' --write"
201
- console.log(log.success('✅ 已添加 "format" 至 package.json'))
341
+ // 添加或更新 "config.commitizen" 配置
342
+ if (!packageJson.config) {
343
+ packageJson.config = {}
344
+ }
345
+
346
+ packageJson.config.commitizen = {
347
+ path: 'node_modules/cz-customizable'
348
+ }
202
349
  modified = true
203
- } else {
204
- console.log(log.warn('⚠️ package.json 中已存在 "format" 未作修改'))
205
- }
206
350
 
207
- // 添加或更新 "commit" 脚本
208
- packageJson.scripts.commit = 'cz'
209
- console.log(log.success('✅ 已添加 "commit" 至 package.json'))
210
- modified = true
351
+ // 写入修改后的 package.json
352
+ if (modified) {
353
+ fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2), 'utf8')
354
+ console.log(chalk.green('✅ 已更新 package.json'))
355
+ console.log('')
356
+ console.log('')
357
+ }
358
+
359
+ // 创建初始化标志文件
360
+ fs.writeFileSync(initFlagPath, 'initialized', 'utf8')
361
+ console.log(log.success(' 🎉🎉🎉 完成啦!'))
362
+ console.log('')
363
+ if (workspaceName) {
364
+ console.log(
365
+ ` 在 ${workspaceName} 工作空间中,运行: git add . && ${packageManager} run commit`
366
+ )
367
+ } else {
368
+ console.log(` 运行 git add 后 | 运行 ${packageManager} run commit 即可`)
369
+ }
370
+ } catch (error) {
371
+ console.error(log.error('❌ 初始化过程中发生错误,正在执行回滚...'))
372
+ console.error('错误详情:', error.message)
373
+ console.error('错误堆栈:', error.stack)
374
+ if (error.stdout) console.error('标准输出:', error.stdout.toString())
375
+ if (error.stderr) console.error('错误输出:', error.stderr.toString())
376
+
377
+ try {
378
+ // 回滚:恢复原始的package.json
379
+ fs.writeFileSync(packageJsonPath, initialPackageJson, 'utf8')
380
+ console.log(log.warn('✅ 已恢复原始 package.json'))
381
+
382
+ // 删除可能创建的配置文件
383
+ const configFiles = [
384
+ '.prettierrc',
385
+ '.eslintrc',
386
+ '.commitlintrc.json',
387
+ '.cz-config.js',
388
+ '.czrc',
389
+ '.lintstagedrc',
390
+ '.prettierignore',
391
+ '.eslintignore'
392
+ ]
393
+ for (const configFile of configFiles) {
394
+ const configPath = path.join(actualProjectRoot, configFile)
395
+ if (fs.existsSync(configPath)) {
396
+ fs.unlinkSync(configPath)
397
+ console.log(log.warn(`✅ 已删除临时配置文件: ${configFile}`))
398
+ }
399
+ }
211
400
 
212
- // 添加或更新 "config.commitizen" 配置
213
- if (!packageJson.config) {
214
- packageJson.config = {}
215
- }
401
+ // 删除可能创建的.husky目录
402
+ const huskyDir = path.join(actualProjectRoot, '.husky')
403
+ if (fs.existsSync(huskyDir)) {
404
+ fs.rmSync(huskyDir, { recursive: true, force: true })
405
+ console.log(log.warn('✅ 已删除临时 .husky 目录'))
406
+ }
216
407
 
217
- packageJson.config.commitizen = {
218
- path: 'node_modules/cz-customizable'
219
- }
220
- modified = true
408
+ // 删除初始化标志文件
409
+ if (fs.existsSync(initFlagPath)) {
410
+ fs.unlinkSync(initFlagPath)
411
+ }
221
412
 
222
- // 写入修改后的 package.json
223
- if (modified) {
224
- fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2), 'utf8')
225
- console.log(chalk.green(' 已更新 package.json'))
226
- console.log('')
227
- console.log('')
228
- }
413
+ console.log(log.success(' 🔄 回滚完成'))
414
+ } catch (rollbackError) {
415
+ console.error(log.error('❌ 回滚过程中也发生了错误,请手动检查项目状态'))
416
+ console.error('回滚错误详情:', rollbackError.message)
417
+ console.error('回滚错误堆栈:', rollbackError.stack)
418
+ if (rollbackError.stdout)
419
+ console.error('回滚标准输出:', rollbackError.stdout.toString())
420
+ if (rollbackError.stderr)
421
+ console.error('回滚错误输出:', rollbackError.stderr.toString())
422
+ }
229
423
 
230
- // 创建初始化标志文件
231
- // fs.writeFileSync(initFlagPath, 'initialized', 'utf8')
232
- console.log(log.success(' 🎉🎉🎉 完成啦!'))
233
- console.log('')
234
- console.log(` 运行 git add 后 | 运行 ${packageManager} run commit 即可`)
424
+ process.exit(1) // 确保进程以错误码退出
425
+ }
@@ -1,6 +1,8 @@
1
1
  /* eslint-env node */
2
2
  import chalk from 'chalk'
3
3
  import { execSync } from 'child_process'
4
+ import fs from 'fs'
5
+ import path from 'path'
4
6
  import cliProgress from 'cli-progress'
5
7
 
6
8
  export function installWithProgress(dependencies, packageManager, projectRoot) {
@@ -12,6 +14,13 @@ export function installWithProgress(dependencies, packageManager, projectRoot) {
12
14
  console.log('')
13
15
  console.log(`⬇️ 开始安装依赖...`)
14
16
 
17
+ // 检查是否为 monorepo(检查是否有 pnpm-workspace.yaml 或 package.json 中的 workspaces 字段)
18
+ const isMonorepo =
19
+ fs.existsSync(path.join(projectRoot, 'pnpm-workspace.yaml')) ||
20
+ (fs.existsSync(path.join(projectRoot, 'package.json')) &&
21
+ JSON.parse(fs.readFileSync(path.join(projectRoot, 'package.json'), 'utf8'))
22
+ .workspaces)
23
+
15
24
  const bar = new cliProgress.SingleBar({
16
25
  format: ` [${chalk.cyan('{bar}')}]{percentage}% | 正在安装: {dep}`,
17
26
  barCompleteChar: '▰',
@@ -25,16 +34,21 @@ export function installWithProgress(dependencies, packageManager, projectRoot) {
25
34
  for (let i = 0; i < dependencies.length; i++) {
26
35
  const dep = dependencies[i]
27
36
 
28
- const installCommand = {
29
- pnpm: `pnpm add -D ${dep}`,
30
- yarn: `yarn add ${dep} --dev`,
31
- bun: `bun add -d ${dep}`,
32
- npm: `npm install ${dep} --save-dev`
33
- }[packageManager]
37
+ let installCommand
38
+ if (packageManager === 'pnpm' && isMonorepo) {
39
+ installCommand = `pnpm add -w -D ${dep}`
40
+ } else {
41
+ installCommand = {
42
+ pnpm: `pnpm add -D ${dep}`,
43
+ yarn: `yarn add ${dep} --dev`,
44
+ bun: `bun add -d ${dep}`,
45
+ npm: `npm install ${dep} --save-dev`
46
+ }[packageManager]
47
+ }
34
48
 
35
49
  bar.update(i, { dep })
36
50
 
37
- execSync(installCommand, { cwd: projectRoot, stdio: 'ignore' })
51
+ execSync(installCommand, { cwd: projectRoot, stdio: ['pipe', 'pipe', 'pipe'] })
38
52
 
39
53
  bar.update(i + 1, { dep })
40
54
  }
@@ -44,7 +58,11 @@ export function installWithProgress(dependencies, packageManager, projectRoot) {
44
58
  console.log('')
45
59
  } catch (err) {
46
60
  bar.stop()
47
- console.log(chalk.red('❌ 安装过程中出错'), err)
61
+ console.log(chalk.red('❌ 安装过程中出错'))
62
+ console.error('错误详情:', err.message)
63
+ console.error('错误堆栈:', err.stack)
64
+ if (err.stdout) console.error('标准输出:', err.stdout.toString())
65
+ if (err.stderr) console.error('错误输出:', err.stderr.toString())
48
66
  throw err
49
67
  }
50
68
  }