zen-gitsync 2.9.8 → 2.9.10

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.
@@ -0,0 +1,586 @@
1
+ import express from 'express';
2
+ import path from 'path';
3
+ import os from 'os';
4
+ import fs from 'fs/promises';
5
+ import open from 'open';
6
+
7
+ export function registerConfigRoutes({
8
+ app,
9
+ configManager
10
+ }) {
11
+ // 保存最近访问的目录
12
+ app.post('/api/save_recent_directory', async (req, res) => {
13
+ try {
14
+ const { path } = req.body;
15
+
16
+ if (!path) {
17
+ return res.status(400).json({
18
+ success: false,
19
+ error: '目录路径不能为空'
20
+ });
21
+ }
22
+
23
+ // 保存到配置
24
+ await configManager.saveRecentDirectory(path);
25
+
26
+ res.json({
27
+ success: true
28
+ });
29
+ } catch (error) {
30
+ res.status(500).json({
31
+ success: false,
32
+ error: error.message
33
+ });
34
+ }
35
+ });
36
+
37
+ // 获取配置
38
+ app.get('/api/config/getConfig', async (req, res) => {
39
+ try {
40
+ // console.log('获取配置中。。。')
41
+ const config = await configManager.loadConfig()
42
+
43
+ // 兼容旧数据:补齐自定义命令 id,避免前端编辑/删除/编排引用异常
44
+ if (Array.isArray(config.customCommands)) {
45
+ let changed = false
46
+ config.customCommands = config.customCommands.map((cmd) => {
47
+ if (cmd && typeof cmd === 'object' && !cmd.id) {
48
+ changed = true
49
+ return {
50
+ ...cmd,
51
+ id: `cmd_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
52
+ }
53
+ }
54
+ return cmd
55
+ })
56
+ if (changed) {
57
+ await configManager.saveConfig(config)
58
+ }
59
+ }
60
+
61
+ // console.log('获取配置成功')
62
+ res.json(config)
63
+ } catch (error) {
64
+ // console.log('获取配置失败')
65
+ res.status(500).json({ error: error.message })
66
+ }
67
+ })
68
+
69
+ // 保存默认提交信息
70
+ app.post('/api/config/saveDefaultMessage', express.json(), async (req, res) => {
71
+ try {
72
+ const { defaultCommitMessage } = req.body
73
+
74
+ if (!defaultCommitMessage) {
75
+ return res.status(400).json({ success: false, error: '缺少必要参数' })
76
+ }
77
+
78
+ const config = await configManager.loadConfig()
79
+
80
+ // 更新默认提交信息
81
+ config.defaultCommitMessage = defaultCommitMessage
82
+ await configManager.saveConfig(config)
83
+
84
+ res.json({ success: true })
85
+ } catch (error) {
86
+ res.status(500).json({ success: false, error: error.message })
87
+ }
88
+ })
89
+
90
+ // 保存所有配置
91
+ app.post('/api/config/saveAll', express.json(), async (req, res) => {
92
+ try {
93
+ const { config } = req.body
94
+
95
+ if (!config) {
96
+ return res.status(400).json({ success: false, error: '缺少必要参数' })
97
+ }
98
+
99
+ await configManager.saveConfig(config)
100
+
101
+ res.json({ success: true })
102
+ } catch (error) {
103
+ res.status(500).json({ success: false, error: error.message })
104
+ }
105
+ })
106
+
107
+ // 检查系统配置文件格式
108
+ app.get('/api/config/check-file-format', async (req, res) => {
109
+ try {
110
+ const configPath = path.join(os.homedir(), '.git-commit-tool.json');
111
+
112
+ try {
113
+ const data = await fs.readFile(configPath, 'utf-8');
114
+ try {
115
+ JSON.parse(data);
116
+ res.json({ success: true, isValidJson: true, exists: true });
117
+ } catch (parseError) {
118
+ res.json({
119
+ success: true,
120
+ isValidJson: false,
121
+ exists: true,
122
+ error: `JSON解析失败: ${parseError.message}`
123
+ });
124
+ }
125
+ } catch (fileError) {
126
+ if (fileError.code === 'ENOENT') {
127
+ res.json({ success: true, isValidJson: true, exists: false });
128
+ } else {
129
+ res.json({
130
+ success: true,
131
+ isValidJson: false,
132
+ exists: true,
133
+ error: `文件读取失败: ${fileError.message}`
134
+ });
135
+ }
136
+ }
137
+ } catch (error) {
138
+ res.status(500).json({ success: false, error: error.message });
139
+ }
140
+ })
141
+
142
+ // 使用系统默认程序打开配置文件 ~/.git-commit-tool.json
143
+ app.post('/api/config/open-file', async (req, res) => {
144
+ try {
145
+ const filePath = path.join(os.homedir(), '.git-commit-tool.json');
146
+ try {
147
+ // 检查文件是否存在,不存在也尝试让系统创建(可能会打开空文件)
148
+ await fs.access(filePath);
149
+ } catch (_) {
150
+ // 如果文件不存在,先创建一个最小结构,避免某些系统无法打开不存在的路径
151
+ try {
152
+ await fs.writeFile(filePath, '{}', 'utf-8');
153
+ } catch (e) {
154
+ // 创建失败不阻断打开尝试
155
+ console.warn('创建配置文件失败(可忽略):', e?.message || e);
156
+ }
157
+ }
158
+
159
+ await open(filePath, { wait: false });
160
+ res.json({ success: true })
161
+ } catch (error) {
162
+ res.status(400).json({ success: false, error: `无法打开配置文件: ${error.message}` })
163
+ }
164
+ })
165
+
166
+ // 保存模板
167
+ app.post('/api/config/save-template', express.json(), async (req, res) => {
168
+ try {
169
+ const { template, type } = req.body
170
+
171
+ if (!template || !type) {
172
+ return res.status(400).json({ success: false, error: '缺少必要参数' })
173
+ }
174
+
175
+ const config = await configManager.loadConfig()
176
+
177
+ if (type === 'description') {
178
+ // 确保描述模板数组存在
179
+ if (!config.descriptionTemplates) {
180
+ config.descriptionTemplates = []
181
+ }
182
+
183
+ // 检查是否已存在相同模板
184
+ if (!config.descriptionTemplates.includes(template)) {
185
+ config.descriptionTemplates.push(template)
186
+ await configManager.saveConfig(config)
187
+ }
188
+ } else if (type === 'scope') {
189
+ // 确保作用域模板数组存在
190
+ if (!config.scopeTemplates) {
191
+ config.scopeTemplates = []
192
+ }
193
+
194
+ // 检查是否已存在相同模板
195
+ if (!config.scopeTemplates.includes(template)) {
196
+ config.scopeTemplates.push(template)
197
+ await configManager.saveConfig(config)
198
+ }
199
+ } else if (type === 'message') {
200
+ // 确保提交信息模板数组存在
201
+ if (!config.messageTemplates) {
202
+ config.messageTemplates = []
203
+ }
204
+
205
+ // 检查是否已存在相同模板
206
+ if (!config.messageTemplates.includes(template)) {
207
+ config.messageTemplates.push(template)
208
+ await configManager.saveConfig(config)
209
+ }
210
+ } else {
211
+ return res.status(400).json({ success: false, error: '不支持的模板类型' })
212
+ }
213
+
214
+ res.json({ success: true })
215
+ } catch (error) {
216
+ res.status(500).json({ success: false, error: error.message })
217
+ }
218
+ })
219
+
220
+ // 删除模板
221
+ app.post('/api/config/delete-template', express.json(), async (req, res) => {
222
+ try {
223
+ const { template, type } = req.body
224
+
225
+ if (!template || !type) {
226
+ return res.status(400).json({ success: false, error: '缺少必要参数' })
227
+ }
228
+
229
+ const config = await configManager.loadConfig()
230
+
231
+ if (type === 'description') {
232
+ // 确保描述模板数组存在
233
+ if (config.descriptionTemplates) {
234
+ const index = config.descriptionTemplates.indexOf(template)
235
+ if (index !== -1) {
236
+ config.descriptionTemplates.splice(index, 1)
237
+ await configManager.saveConfig(config)
238
+ }
239
+ }
240
+ } else if (type === 'scope') {
241
+ // 确保作用域模板数组存在
242
+ if (config.scopeTemplates) {
243
+ const index = config.scopeTemplates.indexOf(template)
244
+ if (index !== -1) {
245
+ config.scopeTemplates.splice(index, 1)
246
+ await configManager.saveConfig(config)
247
+ }
248
+ }
249
+ } else if (type === 'message') {
250
+ // 确保提交信息模板数组存在
251
+ if (config.messageTemplates) {
252
+ const index = config.messageTemplates.indexOf(template)
253
+ if (index !== -1) {
254
+ config.messageTemplates.splice(index, 1)
255
+ await configManager.saveConfig(config)
256
+ }
257
+ }
258
+ } else {
259
+ return res.status(400).json({ success: false, error: '不支持的模板类型' })
260
+ }
261
+
262
+ res.json({ success: true })
263
+ } catch (error) {
264
+ res.status(500).json({ success: false, error: error.message })
265
+ }
266
+ })
267
+
268
+ // 更新模板
269
+ app.post('/api/config/update-template', express.json(), async (req, res) => {
270
+ try {
271
+ const { oldTemplate, newTemplate, type } = req.body
272
+
273
+ if (!oldTemplate || !newTemplate || !type) {
274
+ return res.status(400).json({ success: false, error: '缺少必要参数' })
275
+ }
276
+
277
+ const config = await configManager.loadConfig()
278
+
279
+ if (type === 'description') {
280
+ // 确保描述模板数组存在
281
+ if (config.descriptionTemplates) {
282
+ const index = config.descriptionTemplates.indexOf(oldTemplate)
283
+ if (index !== -1) {
284
+ config.descriptionTemplates[index] = newTemplate
285
+ await configManager.saveConfig(config)
286
+ } else {
287
+ return res.status(404).json({ success: false, error: '未找到原模板' })
288
+ }
289
+ } else {
290
+ return res.status(404).json({ success: false, error: '模板列表不存在' })
291
+ }
292
+ } else if (type === 'scope') {
293
+ // 确保作用域模板数组存在
294
+ if (config.scopeTemplates) {
295
+ const index = config.scopeTemplates.indexOf(oldTemplate)
296
+ if (index !== -1) {
297
+ config.scopeTemplates[index] = newTemplate
298
+ await configManager.saveConfig(config)
299
+ } else {
300
+ return res.status(404).json({ success: false, error: '未找到原模板' })
301
+ }
302
+ } else {
303
+ return res.status(404).json({ success: false, error: '模板列表不存在' })
304
+ }
305
+ } else if (type === 'message') {
306
+ // 确保提交信息模板数组存在
307
+ if (config.messageTemplates) {
308
+ const index = config.messageTemplates.indexOf(oldTemplate)
309
+ if (index !== -1) {
310
+ config.messageTemplates[index] = newTemplate
311
+ await configManager.saveConfig(config)
312
+ } else {
313
+ return res.status(404).json({ success: false, error: '未找到原模板' })
314
+ }
315
+ } else {
316
+ return res.status(404).json({ success: false, error: '模板列表不存在' })
317
+ }
318
+ } else {
319
+ return res.status(400).json({ success: false, error: '不支持的模板类型' })
320
+ }
321
+
322
+ res.json({ success: true })
323
+ } catch (error) {
324
+ res.status(500).json({ success: false, error: error.message })
325
+ }
326
+ })
327
+
328
+ // 置顶模板
329
+ app.post('/api/config/pin-template', express.json(), async (req, res) => {
330
+ try {
331
+ const { template, type } = req.body
332
+
333
+ if (!template || !type) {
334
+ return res.status(400).json({ success: false, error: '缺少必要参数' })
335
+ }
336
+
337
+ const config = await configManager.loadConfig()
338
+
339
+ if (type === 'description') {
340
+ if (config.descriptionTemplates) {
341
+ // 删除原位置的模板
342
+ config.descriptionTemplates = config.descriptionTemplates.filter(t => t !== template)
343
+ // 添加到第一位
344
+ config.descriptionTemplates.unshift(template)
345
+ await configManager.saveConfig(config)
346
+ } else {
347
+ return res.status(404).json({ success: false, error: '模板列表不存在' })
348
+ }
349
+ } else if (type === 'scope') {
350
+ if (config.scopeTemplates) {
351
+ config.scopeTemplates = config.scopeTemplates.filter(t => t !== template)
352
+ config.scopeTemplates.unshift(template)
353
+ await configManager.saveConfig(config)
354
+ } else {
355
+ return res.status(404).json({ success: false, error: '模板列表不存在' })
356
+ }
357
+ } else if (type === 'message') {
358
+ if (config.messageTemplates) {
359
+ config.messageTemplates = config.messageTemplates.filter(t => t !== template)
360
+ config.messageTemplates.unshift(template)
361
+ await configManager.saveConfig(config)
362
+ } else {
363
+ return res.status(404).json({ success: false, error: '模板列表不存在' })
364
+ }
365
+ } else {
366
+ return res.status(400).json({ success: false, error: '不支持的模板类型' })
367
+ }
368
+
369
+ res.json({ success: true })
370
+ } catch (error) {
371
+ res.status(500).json({ success: false, error: error.message })
372
+ }
373
+ })
374
+
375
+ // 保存自定义命令
376
+ app.post('/api/config/save-custom-command', express.json(), async (req, res) => {
377
+ try {
378
+ const { command } = req.body
379
+
380
+ if (!command || !command.name || !command.command) {
381
+ return res.status(400).json({ success: false, error: '缺少必要参数' })
382
+ }
383
+
384
+ const config = await configManager.loadConfig()
385
+
386
+ // 确保自定义命令数组存在
387
+ if (!Array.isArray(config.customCommands)) {
388
+ config.customCommands = []
389
+ }
390
+
391
+ // 生成唯一ID
392
+ const id = `cmd_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
393
+ const newCommand = {
394
+ id,
395
+ name: command.name,
396
+ description: command.description || '',
397
+ directory: command.directory || '',
398
+ command: command.command
399
+ }
400
+
401
+ config.customCommands.push(newCommand)
402
+ await configManager.saveConfig(config)
403
+
404
+ res.json({ success: true, command: newCommand })
405
+ } catch (error) {
406
+ res.status(500).json({ success: false, error: error.message })
407
+ }
408
+ })
409
+
410
+ // 删除自定义命令
411
+ app.post('/api/config/delete-custom-command', express.json(), async (req, res) => {
412
+ try {
413
+ const { id } = req.body
414
+
415
+ if (!id) {
416
+ return res.status(400).json({ success: false, error: '缺少命令ID参数' })
417
+ }
418
+
419
+ const config = await configManager.loadConfig()
420
+
421
+ if (Array.isArray(config.customCommands)) {
422
+ const index = config.customCommands.findIndex(cmd => cmd.id === id)
423
+ if (index !== -1) {
424
+ config.customCommands.splice(index, 1)
425
+ await configManager.saveConfig(config)
426
+ }
427
+ }
428
+
429
+ res.json({ success: true })
430
+ } catch (error) {
431
+ res.status(500).json({ success: false, error: error.message })
432
+ }
433
+ })
434
+
435
+ // 更新自定义命令
436
+ app.post('/api/config/update-custom-command', express.json(), async (req, res) => {
437
+ try {
438
+ const { id, command } = req.body
439
+
440
+ if (!id || !command || !command.name || !command.command) {
441
+ return res.status(400).json({ success: false, error: '缺少必要参数' })
442
+ }
443
+
444
+ const config = await configManager.loadConfig()
445
+
446
+ if (Array.isArray(config.customCommands)) {
447
+ const index = config.customCommands.findIndex(cmd => cmd.id === id)
448
+ if (index !== -1) {
449
+ config.customCommands[index] = {
450
+ id,
451
+ name: command.name,
452
+ description: command.description || '',
453
+ directory: command.directory || '',
454
+ command: command.command
455
+ }
456
+ await configManager.saveConfig(config)
457
+ } else {
458
+ return res.status(404).json({ success: false, error: '未找到指定命令' })
459
+ }
460
+ } else {
461
+ return res.status(404).json({ success: false, error: '命令列表不存在' })
462
+ }
463
+
464
+ res.json({ success: true })
465
+ } catch (error) {
466
+ res.status(500).json({ success: false, error: error.message })
467
+ }
468
+ })
469
+
470
+ // 保存指令编排
471
+ app.post('/api/config/save-orchestration', express.json(), async (req, res) => {
472
+ try {
473
+ const { orchestration } = req.body
474
+
475
+ if (!orchestration || !orchestration.name || !Array.isArray(orchestration.steps)) {
476
+ return res.status(400).json({ success: false, error: '缺少必要参数' })
477
+ }
478
+
479
+ const config = await configManager.loadConfig()
480
+
481
+ // 确保编排数组存在
482
+ if (!Array.isArray(config.orchestrations)) {
483
+ config.orchestrations = []
484
+ }
485
+
486
+ // 生成唯一ID
487
+ const id = `orch_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
488
+ const newOrchestration = {
489
+ id,
490
+ name: orchestration.name,
491
+ description: orchestration.description || '',
492
+ steps: orchestration.steps,
493
+ flowData: orchestration.flowData || null
494
+ }
495
+
496
+ config.orchestrations.push(newOrchestration)
497
+ await configManager.saveConfig(config)
498
+
499
+ res.json({ success: true, orchestration: newOrchestration })
500
+ } catch (error) {
501
+ res.status(500).json({ success: false, error: error.message })
502
+ }
503
+ })
504
+
505
+ // 删除指令编排
506
+ app.post('/api/config/delete-orchestration', express.json(), async (req, res) => {
507
+ try {
508
+ const { id } = req.body
509
+
510
+ if (!id) {
511
+ return res.status(400).json({ success: false, error: '缺少编排ID参数' })
512
+ }
513
+
514
+ const config = await configManager.loadConfig()
515
+
516
+ if (Array.isArray(config.orchestrations)) {
517
+ const index = config.orchestrations.findIndex(orch => orch.id === id)
518
+ if (index !== -1) {
519
+ config.orchestrations.splice(index, 1)
520
+ await configManager.saveConfig(config)
521
+ }
522
+ }
523
+
524
+ res.json({ success: true })
525
+ } catch (error) {
526
+ res.status(500).json({ success: false, error: error.message })
527
+ }
528
+ })
529
+
530
+ // 更新指令编排
531
+ app.post('/api/config/update-orchestration', express.json(), async (req, res) => {
532
+ try {
533
+ const { id, orchestration } = req.body
534
+
535
+ if (!id || !orchestration || !orchestration.name || !Array.isArray(orchestration.steps)) {
536
+ return res.status(400).json({ success: false, error: '缺少必要参数' })
537
+ }
538
+
539
+ const config = await configManager.loadConfig()
540
+
541
+ if (Array.isArray(config.orchestrations)) {
542
+ const index = config.orchestrations.findIndex(orch => orch.id === id)
543
+ if (index !== -1) {
544
+ config.orchestrations[index] = {
545
+ id,
546
+ name: orchestration.name,
547
+ description: orchestration.description || '',
548
+ steps: orchestration.steps,
549
+ flowData: orchestration.flowData || null
550
+ }
551
+ await configManager.saveConfig(config)
552
+ } else {
553
+ return res.status(404).json({ success: false, error: '未找到指定编排' })
554
+ }
555
+ } else {
556
+ return res.status(404).json({ success: false, error: '编排列表不存在' })
557
+ }
558
+
559
+ res.json({ success: true })
560
+ } catch (error) {
561
+ res.status(500).json({ success: false, error: error.message })
562
+ }
563
+ })
564
+
565
+ // 保存项目启动项
566
+ app.post('/api/config/save-startup-items', express.json(), async (req, res) => {
567
+ try {
568
+ const { startupItems, startupAutoRun } = req.body
569
+
570
+ if (!Array.isArray(startupItems)) {
571
+ return res.status(400).json({ success: false, error: '启动项必须是数组' })
572
+ }
573
+
574
+ const config = await configManager.loadConfig()
575
+ config.startupItems = startupItems
576
+ if (typeof startupAutoRun === 'boolean') {
577
+ config.startupAutoRun = startupAutoRun
578
+ }
579
+ await configManager.saveConfig(config)
580
+
581
+ res.json({ success: true })
582
+ } catch (error) {
583
+ res.status(500).json({ success: false, error: error.message })
584
+ }
585
+ })
586
+ }