@pixelbyte-software/pixcode 1.35.2 → 1.35.3
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 +718 -718
- package/README.de.md +248 -248
- package/README.ja.md +240 -240
- package/README.ko.md +240 -240
- package/README.md +303 -303
- package/README.ru.md +248 -248
- package/README.tr.md +250 -250
- package/README.zh-CN.md +240 -240
- package/dist/api-docs.html +548 -548
- package/dist/assets/{index-D1-AIL_5.js → index-D8z78r_D.js} +57 -57
- package/dist/assets/{index-B8w57E1r.css → index-DmchzORZ.css} +1 -1
- package/dist/clear-cache.html +85 -85
- package/dist/convert-icons.md +52 -52
- package/dist/favicon.svg +8 -8
- package/dist/generate-icons.js +48 -48
- package/dist/icons/codex-white.svg +3 -3
- package/dist/icons/codex.svg +3 -3
- package/dist/icons/cursor-white.svg +11 -11
- package/dist/icons/icon-128x128.svg +9 -9
- package/dist/icons/icon-144x144.svg +9 -9
- package/dist/icons/icon-152x152.svg +9 -9
- package/dist/icons/icon-192x192.svg +9 -9
- package/dist/icons/icon-384x384.svg +9 -9
- package/dist/icons/icon-512x512.svg +9 -9
- package/dist/icons/icon-72x72.svg +9 -9
- package/dist/icons/icon-96x96.svg +9 -9
- package/dist/icons/icon-template.svg +9 -9
- package/dist/icons/qwen-logo.svg +14 -14
- package/dist/index.html +59 -59
- package/dist/logo.svg +12 -12
- package/dist/manifest.json +60 -60
- package/dist/openapi.yaml +1693 -1693
- package/dist/sw.js +124 -124
- package/dist-server/server/cli.js +96 -96
- package/dist-server/server/daemon/manager.js +33 -33
- package/dist-server/server/daemon-manager.js +64 -64
- package/dist-server/server/routes/commands.js +25 -25
- package/dist-server/server/routes/git.js +17 -17
- package/dist-server/server/routes/taskmaster.js +419 -419
- package/package.json +180 -180
- package/scripts/fix-node-pty.js +67 -67
- package/scripts/smoke/a2a-roundtrip.mjs +167 -167
- package/scripts/smoke/orchestration-api.mjs +172 -172
- package/scripts/smoke/orchestration-live-run.mjs +176 -176
- package/server/claude-sdk.js +898 -898
- package/server/cli.js +935 -935
- package/server/constants/config.js +4 -4
- package/server/cursor-cli.js +342 -342
- package/server/daemon/manager.js +564 -564
- package/server/daemon-manager.js +959 -959
- package/server/database/db.js +794 -794
- package/server/database/json-store.js +197 -197
- package/server/gemini-cli.js +535 -535
- package/server/gemini-response-handler.js +79 -79
- package/server/index.js +3135 -3135
- package/server/load-env.js +34 -34
- package/server/middleware/auth.js +173 -173
- package/server/modules/orchestration/a2a/adapter-registry.ts +108 -108
- package/server/modules/orchestration/a2a/adapters/abstract-a2a.adapter.ts +55 -55
- package/server/modules/orchestration/a2a/adapters/claude-code.adapter.ts +284 -284
- package/server/modules/orchestration/a2a/adapters/codex.adapter.ts +244 -244
- package/server/modules/orchestration/a2a/adapters/cursor.adapter.ts +249 -249
- package/server/modules/orchestration/a2a/adapters/gemini.adapter.ts +248 -248
- package/server/modules/orchestration/a2a/adapters/opencode.adapter.ts +248 -248
- package/server/modules/orchestration/a2a/adapters/qwen.adapter.ts +248 -248
- package/server/modules/orchestration/a2a/routes.ts +577 -577
- package/server/modules/orchestration/a2a/task-store.ts +178 -178
- package/server/modules/orchestration/a2a/types.ts +125 -125
- package/server/modules/orchestration/a2a/validator.ts +113 -113
- package/server/modules/orchestration/index.ts +66 -66
- package/server/modules/orchestration/preview/port-watcher.ts +112 -112
- package/server/modules/orchestration/preview/preview-proxy.ts +60 -60
- package/server/modules/orchestration/preview/types.ts +19 -19
- package/server/modules/orchestration/tasks/orchestration-task-store.ts +45 -45
- package/server/modules/orchestration/tasks/orchestration-task.routes.ts +73 -73
- package/server/modules/orchestration/tasks/orchestration-task.service.ts +145 -145
- package/server/modules/orchestration/tasks/orchestration-task.types.ts +29 -29
- package/server/modules/orchestration/workflows/built-in-workflows.ts +127 -127
- package/server/modules/orchestration/workflows/workflow-runner.ts +1206 -1206
- package/server/modules/orchestration/workflows/workflow-store.ts +97 -97
- package/server/modules/orchestration/workflows/workflow.routes.ts +169 -169
- package/server/modules/orchestration/workflows/workflow.types.ts +70 -70
- package/server/modules/orchestration/workflows/workspace-target.ts +120 -120
- package/server/modules/orchestration/workspace/docker-workspace.ts +135 -135
- package/server/modules/orchestration/workspace/path-safety.ts +55 -55
- package/server/modules/orchestration/workspace/types.ts +52 -52
- package/server/modules/orchestration/workspace/workspace-manager.ts +97 -97
- package/server/modules/orchestration/workspace/worktree-workspace.ts +125 -125
- package/server/modules/providers/index.ts +2 -2
- package/server/modules/providers/list/claude/claude-auth.provider.ts +145 -145
- package/server/modules/providers/list/claude/claude-mcp.provider.ts +135 -135
- package/server/modules/providers/list/claude/claude-sessions.provider.ts +306 -306
- package/server/modules/providers/list/claude/claude.provider.ts +15 -15
- package/server/modules/providers/list/codex/codex-auth.provider.ts +115 -115
- package/server/modules/providers/list/codex/codex-mcp.provider.ts +135 -135
- package/server/modules/providers/list/codex/codex-sessions.provider.ts +319 -319
- package/server/modules/providers/list/codex/codex.provider.ts +15 -15
- package/server/modules/providers/list/cursor/cursor-auth.provider.ts +143 -143
- package/server/modules/providers/list/cursor/cursor-mcp.provider.ts +108 -108
- package/server/modules/providers/list/cursor/cursor-sessions.provider.ts +421 -421
- package/server/modules/providers/list/cursor/cursor.provider.ts +15 -15
- package/server/modules/providers/list/gemini/gemini-auth.provider.ts +163 -163
- package/server/modules/providers/list/gemini/gemini-mcp.provider.ts +110 -110
- package/server/modules/providers/list/gemini/gemini-sessions.provider.ts +227 -227
- package/server/modules/providers/list/gemini/gemini.provider.ts +15 -15
- package/server/modules/providers/list/opencode/opencode-auth.provider.ts +130 -130
- package/server/modules/providers/list/opencode/opencode-mcp.provider.ts +126 -126
- package/server/modules/providers/list/opencode/opencode-sessions.provider.ts +232 -232
- package/server/modules/providers/list/opencode/opencode.provider.ts +29 -29
- package/server/modules/providers/list/qwen/qwen-auth.provider.ts +145 -145
- package/server/modules/providers/list/qwen/qwen-mcp.provider.ts +114 -114
- package/server/modules/providers/list/qwen/qwen-sessions.provider.ts +265 -265
- package/server/modules/providers/list/qwen/qwen.provider.ts +21 -21
- package/server/modules/providers/provider.registry.ts +40 -40
- package/server/modules/providers/provider.routes.ts +819 -819
- package/server/modules/providers/services/mcp.service.ts +86 -86
- package/server/modules/providers/services/provider-auth.service.ts +26 -26
- package/server/modules/providers/services/sessions.service.ts +45 -45
- package/server/modules/providers/shared/base/abstract.provider.ts +20 -20
- package/server/modules/providers/shared/mcp/mcp.provider.ts +151 -151
- package/server/modules/providers/shared/provider-configs.ts +142 -142
- package/server/modules/providers/tests/mcp.test.ts +293 -293
- package/server/openai-codex.js +462 -462
- package/server/opencode-cli.js +459 -459
- package/server/opencode-response-handler.js +107 -107
- package/server/projects.js +3105 -3105
- package/server/qwen-code-cli.js +395 -395
- package/server/qwen-response-handler.js +73 -73
- package/server/routes/agent.js +1365 -1365
- package/server/routes/auth.js +138 -138
- package/server/routes/codex.js +19 -19
- package/server/routes/commands.js +554 -554
- package/server/routes/cursor.js +52 -52
- package/server/routes/gemini.js +24 -24
- package/server/routes/git.js +1488 -1488
- package/server/routes/mcp-utils.js +31 -31
- package/server/routes/messages.js +61 -61
- package/server/routes/network.js +120 -120
- package/server/routes/plugins.js +318 -318
- package/server/routes/projects.js +915 -915
- package/server/routes/qwen.js +27 -27
- package/server/routes/settings.js +286 -286
- package/server/routes/taskmaster.js +1496 -1496
- package/server/routes/telegram.js +125 -125
- package/server/routes/user.js +123 -123
- package/server/services/external-access.js +171 -171
- package/server/services/install-jobs.js +571 -571
- package/server/services/notification-orchestrator.js +242 -242
- package/server/services/provider-credentials.js +189 -189
- package/server/services/provider-models.js +381 -381
- package/server/services/telegram/bot.js +279 -279
- package/server/services/telegram/telegram-http-client.js +130 -130
- package/server/services/telegram/translations.js +170 -170
- package/server/services/vapid-keys.js +36 -36
- package/server/sessionManager.js +225 -225
- package/server/shared/interfaces.ts +54 -54
- package/server/shared/types.ts +172 -172
- package/server/shared/utils.ts +193 -193
- package/server/tsconfig.json +36 -36
- package/server/utils/colors.js +21 -21
- package/server/utils/commandParser.js +303 -303
- package/server/utils/frontmatter.js +18 -18
- package/server/utils/gitConfig.js +34 -34
- package/server/utils/mcp-detector.js +147 -147
- package/server/utils/plugin-loader.js +457 -457
- package/server/utils/plugin-process-manager.js +184 -184
- package/server/utils/port-access.js +209 -209
- package/server/utils/runtime-paths.js +37 -37
- package/server/utils/taskmaster-websocket.js +128 -128
- package/server/utils/url-detection.js +71 -71
- package/server/vite-daemon.js +78 -78
- package/shared/modelConstants.js +162 -162
- package/shared/networkHosts.js +22 -22
|
@@ -1,125 +1,125 @@
|
|
|
1
|
-
import express from 'express';
|
|
2
|
-
|
|
3
|
-
import { telegramLinksDb } from '../database/db.js';
|
|
4
|
-
import {
|
|
5
|
-
createPairingCode,
|
|
6
|
-
getBotState,
|
|
7
|
-
getPublicConfig,
|
|
8
|
-
removeBotConfig,
|
|
9
|
-
startBot,
|
|
10
|
-
stopBot,
|
|
11
|
-
} from '../services/telegram/bot.js';
|
|
12
|
-
import { SUPPORTED_LANGUAGES } from '../services/telegram/translations.js';
|
|
13
|
-
|
|
14
|
-
const router = express.Router();
|
|
15
|
-
|
|
16
|
-
const sanitizeLanguage = (raw) => {
|
|
17
|
-
if (typeof raw !== 'string') return 'en';
|
|
18
|
-
return SUPPORTED_LANGUAGES.includes(raw) ? raw : 'en';
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
// GET /api/telegram/status — combined bot + personal link state
|
|
22
|
-
router.get('/status', (req, res) => {
|
|
23
|
-
try {
|
|
24
|
-
const bot = getBotState();
|
|
25
|
-
const config = getPublicConfig();
|
|
26
|
-
const link = telegramLinksDb.getByUserId(req.user.id);
|
|
27
|
-
res.json({
|
|
28
|
-
bot: { ...bot, ...config },
|
|
29
|
-
link: link
|
|
30
|
-
? {
|
|
31
|
-
paired: Boolean(link.chat_id && link.verified_at),
|
|
32
|
-
telegramUsername: link.telegram_username,
|
|
33
|
-
language: link.language,
|
|
34
|
-
notificationsEnabled: Boolean(link.notifications_enabled),
|
|
35
|
-
bridgeEnabled: Boolean(link.bridge_enabled),
|
|
36
|
-
pairingCode: link.pairing_code,
|
|
37
|
-
pairingExpiresAt: link.pairing_code_expires_at,
|
|
38
|
-
verifiedAt: link.verified_at,
|
|
39
|
-
}
|
|
40
|
-
: null,
|
|
41
|
-
});
|
|
42
|
-
} catch (error) {
|
|
43
|
-
console.error('telegram/status failed:', error);
|
|
44
|
-
res.status(500).json({ error: 'Failed to read Telegram status' });
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
// POST /api/telegram/bot — save token and start the bot
|
|
49
|
-
router.post('/bot', async (req, res) => {
|
|
50
|
-
const { token } = req.body || {};
|
|
51
|
-
if (typeof token !== 'string' || token.length < 10) {
|
|
52
|
-
return res.status(400).json({ error: 'A valid bot token is required' });
|
|
53
|
-
}
|
|
54
|
-
try {
|
|
55
|
-
const info = await startBot({ token });
|
|
56
|
-
res.json({ success: true, bot: { ...getBotState(), configured: true, username: info.username } });
|
|
57
|
-
} catch (error) {
|
|
58
|
-
console.error('telegram/bot start failed:', error);
|
|
59
|
-
const status = error?.code === 'INVALID_TOKEN' ? 400 : 502;
|
|
60
|
-
res.status(status).json({ error: error?.message || 'Failed to start bot' });
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
// DELETE /api/telegram/bot — stop and remove the configured bot
|
|
65
|
-
router.delete('/bot', async (req, res) => {
|
|
66
|
-
try {
|
|
67
|
-
await removeBotConfig();
|
|
68
|
-
res.json({ success: true, bot: getBotState() });
|
|
69
|
-
} catch (error) {
|
|
70
|
-
console.error('telegram/bot remove failed:', error);
|
|
71
|
-
res.status(502).json({ error: 'Failed to remove bot' });
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
// POST /api/telegram/bot/stop — stop polling but keep the token
|
|
76
|
-
router.post('/bot/stop', async (req, res) => {
|
|
77
|
-
try {
|
|
78
|
-
await stopBot();
|
|
79
|
-
res.json({ success: true, bot: getBotState() });
|
|
80
|
-
} catch (error) {
|
|
81
|
-
console.error('telegram/bot/stop failed:', error);
|
|
82
|
-
res.status(502).json({ error: 'Failed to stop bot' });
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
// POST /api/telegram/pairing-code — (re)generate a 6-digit code for this user
|
|
87
|
-
router.post('/pairing-code', (req, res) => {
|
|
88
|
-
try {
|
|
89
|
-
const language = sanitizeLanguage(req.body?.language);
|
|
90
|
-
const { code, expiresAt } = createPairingCode(req.user.id, language);
|
|
91
|
-
res.json({ success: true, code, expiresAt, language });
|
|
92
|
-
} catch (error) {
|
|
93
|
-
console.error('telegram/pairing-code failed:', error);
|
|
94
|
-
res.status(500).json({ error: 'Failed to generate pairing code' });
|
|
95
|
-
}
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
// PATCH /api/telegram/link — update language / toggles on the user's link
|
|
99
|
-
router.patch('/link', (req, res) => {
|
|
100
|
-
try {
|
|
101
|
-
const { language, notificationsEnabled, bridgeEnabled } = req.body || {};
|
|
102
|
-
const payload = {};
|
|
103
|
-
if (language !== undefined) payload.language = sanitizeLanguage(language);
|
|
104
|
-
if (notificationsEnabled !== undefined) payload.notificationsEnabled = Boolean(notificationsEnabled);
|
|
105
|
-
if (bridgeEnabled !== undefined) payload.bridgeEnabled = Boolean(bridgeEnabled);
|
|
106
|
-
telegramLinksDb.updatePreferences(req.user.id, payload);
|
|
107
|
-
res.json({ success: true, link: telegramLinksDb.getByUserId(req.user.id) });
|
|
108
|
-
} catch (error) {
|
|
109
|
-
console.error('telegram/link patch failed:', error);
|
|
110
|
-
res.status(500).json({ error: 'Failed to update link' });
|
|
111
|
-
}
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
// DELETE /api/telegram/link — unpair
|
|
115
|
-
router.delete('/link', (req, res) => {
|
|
116
|
-
try {
|
|
117
|
-
telegramLinksDb.unlink(req.user.id);
|
|
118
|
-
res.json({ success: true });
|
|
119
|
-
} catch (error) {
|
|
120
|
-
console.error('telegram/link delete failed:', error);
|
|
121
|
-
res.status(500).json({ error: 'Failed to unpair' });
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
export default router;
|
|
1
|
+
import express from 'express';
|
|
2
|
+
|
|
3
|
+
import { telegramLinksDb } from '../database/db.js';
|
|
4
|
+
import {
|
|
5
|
+
createPairingCode,
|
|
6
|
+
getBotState,
|
|
7
|
+
getPublicConfig,
|
|
8
|
+
removeBotConfig,
|
|
9
|
+
startBot,
|
|
10
|
+
stopBot,
|
|
11
|
+
} from '../services/telegram/bot.js';
|
|
12
|
+
import { SUPPORTED_LANGUAGES } from '../services/telegram/translations.js';
|
|
13
|
+
|
|
14
|
+
const router = express.Router();
|
|
15
|
+
|
|
16
|
+
const sanitizeLanguage = (raw) => {
|
|
17
|
+
if (typeof raw !== 'string') return 'en';
|
|
18
|
+
return SUPPORTED_LANGUAGES.includes(raw) ? raw : 'en';
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// GET /api/telegram/status — combined bot + personal link state
|
|
22
|
+
router.get('/status', (req, res) => {
|
|
23
|
+
try {
|
|
24
|
+
const bot = getBotState();
|
|
25
|
+
const config = getPublicConfig();
|
|
26
|
+
const link = telegramLinksDb.getByUserId(req.user.id);
|
|
27
|
+
res.json({
|
|
28
|
+
bot: { ...bot, ...config },
|
|
29
|
+
link: link
|
|
30
|
+
? {
|
|
31
|
+
paired: Boolean(link.chat_id && link.verified_at),
|
|
32
|
+
telegramUsername: link.telegram_username,
|
|
33
|
+
language: link.language,
|
|
34
|
+
notificationsEnabled: Boolean(link.notifications_enabled),
|
|
35
|
+
bridgeEnabled: Boolean(link.bridge_enabled),
|
|
36
|
+
pairingCode: link.pairing_code,
|
|
37
|
+
pairingExpiresAt: link.pairing_code_expires_at,
|
|
38
|
+
verifiedAt: link.verified_at,
|
|
39
|
+
}
|
|
40
|
+
: null,
|
|
41
|
+
});
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.error('telegram/status failed:', error);
|
|
44
|
+
res.status(500).json({ error: 'Failed to read Telegram status' });
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// POST /api/telegram/bot — save token and start the bot
|
|
49
|
+
router.post('/bot', async (req, res) => {
|
|
50
|
+
const { token } = req.body || {};
|
|
51
|
+
if (typeof token !== 'string' || token.length < 10) {
|
|
52
|
+
return res.status(400).json({ error: 'A valid bot token is required' });
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
const info = await startBot({ token });
|
|
56
|
+
res.json({ success: true, bot: { ...getBotState(), configured: true, username: info.username } });
|
|
57
|
+
} catch (error) {
|
|
58
|
+
console.error('telegram/bot start failed:', error);
|
|
59
|
+
const status = error?.code === 'INVALID_TOKEN' ? 400 : 502;
|
|
60
|
+
res.status(status).json({ error: error?.message || 'Failed to start bot' });
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// DELETE /api/telegram/bot — stop and remove the configured bot
|
|
65
|
+
router.delete('/bot', async (req, res) => {
|
|
66
|
+
try {
|
|
67
|
+
await removeBotConfig();
|
|
68
|
+
res.json({ success: true, bot: getBotState() });
|
|
69
|
+
} catch (error) {
|
|
70
|
+
console.error('telegram/bot remove failed:', error);
|
|
71
|
+
res.status(502).json({ error: 'Failed to remove bot' });
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// POST /api/telegram/bot/stop — stop polling but keep the token
|
|
76
|
+
router.post('/bot/stop', async (req, res) => {
|
|
77
|
+
try {
|
|
78
|
+
await stopBot();
|
|
79
|
+
res.json({ success: true, bot: getBotState() });
|
|
80
|
+
} catch (error) {
|
|
81
|
+
console.error('telegram/bot/stop failed:', error);
|
|
82
|
+
res.status(502).json({ error: 'Failed to stop bot' });
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// POST /api/telegram/pairing-code — (re)generate a 6-digit code for this user
|
|
87
|
+
router.post('/pairing-code', (req, res) => {
|
|
88
|
+
try {
|
|
89
|
+
const language = sanitizeLanguage(req.body?.language);
|
|
90
|
+
const { code, expiresAt } = createPairingCode(req.user.id, language);
|
|
91
|
+
res.json({ success: true, code, expiresAt, language });
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.error('telegram/pairing-code failed:', error);
|
|
94
|
+
res.status(500).json({ error: 'Failed to generate pairing code' });
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// PATCH /api/telegram/link — update language / toggles on the user's link
|
|
99
|
+
router.patch('/link', (req, res) => {
|
|
100
|
+
try {
|
|
101
|
+
const { language, notificationsEnabled, bridgeEnabled } = req.body || {};
|
|
102
|
+
const payload = {};
|
|
103
|
+
if (language !== undefined) payload.language = sanitizeLanguage(language);
|
|
104
|
+
if (notificationsEnabled !== undefined) payload.notificationsEnabled = Boolean(notificationsEnabled);
|
|
105
|
+
if (bridgeEnabled !== undefined) payload.bridgeEnabled = Boolean(bridgeEnabled);
|
|
106
|
+
telegramLinksDb.updatePreferences(req.user.id, payload);
|
|
107
|
+
res.json({ success: true, link: telegramLinksDb.getByUserId(req.user.id) });
|
|
108
|
+
} catch (error) {
|
|
109
|
+
console.error('telegram/link patch failed:', error);
|
|
110
|
+
res.status(500).json({ error: 'Failed to update link' });
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// DELETE /api/telegram/link — unpair
|
|
115
|
+
router.delete('/link', (req, res) => {
|
|
116
|
+
try {
|
|
117
|
+
telegramLinksDb.unlink(req.user.id);
|
|
118
|
+
res.json({ success: true });
|
|
119
|
+
} catch (error) {
|
|
120
|
+
console.error('telegram/link delete failed:', error);
|
|
121
|
+
res.status(500).json({ error: 'Failed to unpair' });
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
export default router;
|
package/server/routes/user.js
CHANGED
|
@@ -1,123 +1,123 @@
|
|
|
1
|
-
import express from 'express';
|
|
2
|
-
import { userDb } from '../database/db.js';
|
|
3
|
-
import { authenticateToken } from '../middleware/auth.js';
|
|
4
|
-
import { getSystemGitConfig } from '../utils/gitConfig.js';
|
|
5
|
-
import { spawn } from 'child_process';
|
|
6
|
-
|
|
7
|
-
const router = express.Router();
|
|
8
|
-
|
|
9
|
-
function spawnAsync(command, args, options = {}) {
|
|
10
|
-
return new Promise((resolve, reject) => {
|
|
11
|
-
const child = spawn(command, args, { ...options, shell: false });
|
|
12
|
-
let stdout = '';
|
|
13
|
-
let stderr = '';
|
|
14
|
-
child.stdout.on('data', (data) => { stdout += data.toString(); });
|
|
15
|
-
child.stderr.on('data', (data) => { stderr += data.toString(); });
|
|
16
|
-
child.on('error', (error) => { reject(error); });
|
|
17
|
-
child.on('close', (code) => {
|
|
18
|
-
if (code === 0) { resolve({ stdout, stderr }); return; }
|
|
19
|
-
const error = new Error(`Command failed: ${command} ${args.join(' ')}`);
|
|
20
|
-
error.code = code;
|
|
21
|
-
error.stdout = stdout;
|
|
22
|
-
error.stderr = stderr;
|
|
23
|
-
reject(error);
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
router.get('/git-config', authenticateToken, async (req, res) => {
|
|
29
|
-
try {
|
|
30
|
-
const userId = req.user.id;
|
|
31
|
-
let gitConfig = userDb.getGitConfig(userId);
|
|
32
|
-
|
|
33
|
-
// If database is empty, try to get from system git config
|
|
34
|
-
if (!gitConfig || (!gitConfig.git_name && !gitConfig.git_email)) {
|
|
35
|
-
const systemConfig = await getSystemGitConfig();
|
|
36
|
-
|
|
37
|
-
// If system has values, save them to database for this user
|
|
38
|
-
if (systemConfig.git_name || systemConfig.git_email) {
|
|
39
|
-
userDb.updateGitConfig(userId, systemConfig.git_name, systemConfig.git_email);
|
|
40
|
-
gitConfig = systemConfig;
|
|
41
|
-
console.log(`Auto-populated git config from system for user ${userId}: ${systemConfig.git_name} <${systemConfig.git_email}>`);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
res.json({
|
|
46
|
-
success: true,
|
|
47
|
-
gitName: gitConfig?.git_name || null,
|
|
48
|
-
gitEmail: gitConfig?.git_email || null
|
|
49
|
-
});
|
|
50
|
-
} catch (error) {
|
|
51
|
-
console.error('Error getting git config:', error);
|
|
52
|
-
res.status(500).json({ error: 'Failed to get git configuration' });
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
// Apply git config globally via git config --global
|
|
57
|
-
router.post('/git-config', authenticateToken, async (req, res) => {
|
|
58
|
-
try {
|
|
59
|
-
const userId = req.user.id;
|
|
60
|
-
const { gitName, gitEmail } = req.body;
|
|
61
|
-
|
|
62
|
-
if (!gitName || !gitEmail) {
|
|
63
|
-
return res.status(400).json({ error: 'Git name and email are required' });
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Validate email format
|
|
67
|
-
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
68
|
-
if (!emailRegex.test(gitEmail)) {
|
|
69
|
-
return res.status(400).json({ error: 'Invalid email format' });
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
userDb.updateGitConfig(userId, gitName, gitEmail);
|
|
73
|
-
|
|
74
|
-
try {
|
|
75
|
-
await spawnAsync('git', ['config', '--global', 'user.name', gitName]);
|
|
76
|
-
await spawnAsync('git', ['config', '--global', 'user.email', gitEmail]);
|
|
77
|
-
console.log(`Applied git config globally: ${gitName} <${gitEmail}>`);
|
|
78
|
-
} catch (gitError) {
|
|
79
|
-
console.error('Error applying git config:', gitError);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
res.json({
|
|
83
|
-
success: true,
|
|
84
|
-
gitName,
|
|
85
|
-
gitEmail
|
|
86
|
-
});
|
|
87
|
-
} catch (error) {
|
|
88
|
-
console.error('Error updating git config:', error);
|
|
89
|
-
res.status(500).json({ error: 'Failed to update git configuration' });
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
router.post('/complete-onboarding', authenticateToken, async (req, res) => {
|
|
94
|
-
try {
|
|
95
|
-
const userId = req.user.id;
|
|
96
|
-
userDb.completeOnboarding(userId);
|
|
97
|
-
|
|
98
|
-
res.json({
|
|
99
|
-
success: true,
|
|
100
|
-
message: 'Onboarding completed successfully'
|
|
101
|
-
});
|
|
102
|
-
} catch (error) {
|
|
103
|
-
console.error('Error completing onboarding:', error);
|
|
104
|
-
res.status(500).json({ error: 'Failed to complete onboarding' });
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
router.get('/onboarding-status', authenticateToken, async (req, res) => {
|
|
109
|
-
try {
|
|
110
|
-
const userId = req.user.id;
|
|
111
|
-
const hasCompleted = userDb.hasCompletedOnboarding(userId);
|
|
112
|
-
|
|
113
|
-
res.json({
|
|
114
|
-
success: true,
|
|
115
|
-
hasCompletedOnboarding: hasCompleted
|
|
116
|
-
});
|
|
117
|
-
} catch (error) {
|
|
118
|
-
console.error('Error checking onboarding status:', error);
|
|
119
|
-
res.status(500).json({ error: 'Failed to check onboarding status' });
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
export default router;
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import { userDb } from '../database/db.js';
|
|
3
|
+
import { authenticateToken } from '../middleware/auth.js';
|
|
4
|
+
import { getSystemGitConfig } from '../utils/gitConfig.js';
|
|
5
|
+
import { spawn } from 'child_process';
|
|
6
|
+
|
|
7
|
+
const router = express.Router();
|
|
8
|
+
|
|
9
|
+
function spawnAsync(command, args, options = {}) {
|
|
10
|
+
return new Promise((resolve, reject) => {
|
|
11
|
+
const child = spawn(command, args, { ...options, shell: false });
|
|
12
|
+
let stdout = '';
|
|
13
|
+
let stderr = '';
|
|
14
|
+
child.stdout.on('data', (data) => { stdout += data.toString(); });
|
|
15
|
+
child.stderr.on('data', (data) => { stderr += data.toString(); });
|
|
16
|
+
child.on('error', (error) => { reject(error); });
|
|
17
|
+
child.on('close', (code) => {
|
|
18
|
+
if (code === 0) { resolve({ stdout, stderr }); return; }
|
|
19
|
+
const error = new Error(`Command failed: ${command} ${args.join(' ')}`);
|
|
20
|
+
error.code = code;
|
|
21
|
+
error.stdout = stdout;
|
|
22
|
+
error.stderr = stderr;
|
|
23
|
+
reject(error);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
router.get('/git-config', authenticateToken, async (req, res) => {
|
|
29
|
+
try {
|
|
30
|
+
const userId = req.user.id;
|
|
31
|
+
let gitConfig = userDb.getGitConfig(userId);
|
|
32
|
+
|
|
33
|
+
// If database is empty, try to get from system git config
|
|
34
|
+
if (!gitConfig || (!gitConfig.git_name && !gitConfig.git_email)) {
|
|
35
|
+
const systemConfig = await getSystemGitConfig();
|
|
36
|
+
|
|
37
|
+
// If system has values, save them to database for this user
|
|
38
|
+
if (systemConfig.git_name || systemConfig.git_email) {
|
|
39
|
+
userDb.updateGitConfig(userId, systemConfig.git_name, systemConfig.git_email);
|
|
40
|
+
gitConfig = systemConfig;
|
|
41
|
+
console.log(`Auto-populated git config from system for user ${userId}: ${systemConfig.git_name} <${systemConfig.git_email}>`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
res.json({
|
|
46
|
+
success: true,
|
|
47
|
+
gitName: gitConfig?.git_name || null,
|
|
48
|
+
gitEmail: gitConfig?.git_email || null
|
|
49
|
+
});
|
|
50
|
+
} catch (error) {
|
|
51
|
+
console.error('Error getting git config:', error);
|
|
52
|
+
res.status(500).json({ error: 'Failed to get git configuration' });
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Apply git config globally via git config --global
|
|
57
|
+
router.post('/git-config', authenticateToken, async (req, res) => {
|
|
58
|
+
try {
|
|
59
|
+
const userId = req.user.id;
|
|
60
|
+
const { gitName, gitEmail } = req.body;
|
|
61
|
+
|
|
62
|
+
if (!gitName || !gitEmail) {
|
|
63
|
+
return res.status(400).json({ error: 'Git name and email are required' });
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Validate email format
|
|
67
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
68
|
+
if (!emailRegex.test(gitEmail)) {
|
|
69
|
+
return res.status(400).json({ error: 'Invalid email format' });
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
userDb.updateGitConfig(userId, gitName, gitEmail);
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
await spawnAsync('git', ['config', '--global', 'user.name', gitName]);
|
|
76
|
+
await spawnAsync('git', ['config', '--global', 'user.email', gitEmail]);
|
|
77
|
+
console.log(`Applied git config globally: ${gitName} <${gitEmail}>`);
|
|
78
|
+
} catch (gitError) {
|
|
79
|
+
console.error('Error applying git config:', gitError);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
res.json({
|
|
83
|
+
success: true,
|
|
84
|
+
gitName,
|
|
85
|
+
gitEmail
|
|
86
|
+
});
|
|
87
|
+
} catch (error) {
|
|
88
|
+
console.error('Error updating git config:', error);
|
|
89
|
+
res.status(500).json({ error: 'Failed to update git configuration' });
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
router.post('/complete-onboarding', authenticateToken, async (req, res) => {
|
|
94
|
+
try {
|
|
95
|
+
const userId = req.user.id;
|
|
96
|
+
userDb.completeOnboarding(userId);
|
|
97
|
+
|
|
98
|
+
res.json({
|
|
99
|
+
success: true,
|
|
100
|
+
message: 'Onboarding completed successfully'
|
|
101
|
+
});
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.error('Error completing onboarding:', error);
|
|
104
|
+
res.status(500).json({ error: 'Failed to complete onboarding' });
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
router.get('/onboarding-status', authenticateToken, async (req, res) => {
|
|
109
|
+
try {
|
|
110
|
+
const userId = req.user.id;
|
|
111
|
+
const hasCompleted = userDb.hasCompletedOnboarding(userId);
|
|
112
|
+
|
|
113
|
+
res.json({
|
|
114
|
+
success: true,
|
|
115
|
+
hasCompletedOnboarding: hasCompleted
|
|
116
|
+
});
|
|
117
|
+
} catch (error) {
|
|
118
|
+
console.error('Error checking onboarding status:', error);
|
|
119
|
+
res.status(500).json({ error: 'Failed to check onboarding status' });
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
export default router;
|