@cloudcli-ai/cloudcli 1.30.0 → 1.31.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/dist/assets/{index-DI22MZMb.css → index-DF8TTVHl.css} +1 -1
- package/dist/assets/index-DbZAcc9z.js +1262 -0
- package/dist/index.html +2 -2
- package/dist-server/server/index.js +115 -955
- package/dist-server/server/index.js.map +1 -1
- package/dist-server/server/middleware/auth.js +1 -1
- package/dist-server/server/middleware/auth.js.map +1 -1
- package/dist-server/server/modules/database/connection.js +125 -0
- package/dist-server/server/modules/database/connection.js.map +1 -0
- package/dist-server/server/modules/database/index.js +13 -0
- package/dist-server/server/modules/database/index.js.map +1 -0
- package/dist-server/server/modules/database/init-db.js +18 -0
- package/dist-server/server/modules/database/init-db.js.map +1 -0
- package/dist-server/server/modules/database/migrations.js +370 -0
- package/dist-server/server/modules/database/migrations.js.map +1 -0
- package/dist-server/server/modules/database/repositories/api-keys.js +72 -0
- package/dist-server/server/modules/database/repositories/api-keys.js.map +1 -0
- package/dist-server/server/modules/database/repositories/app-config.js +47 -0
- package/dist-server/server/modules/database/repositories/app-config.js.map +1 -0
- package/dist-server/server/modules/database/repositories/credentials.js +68 -0
- package/dist-server/server/modules/database/repositories/credentials.js.map +1 -0
- package/dist-server/server/modules/database/repositories/github-tokens.js +54 -0
- package/dist-server/server/modules/database/repositories/github-tokens.js.map +1 -0
- package/dist-server/server/modules/database/repositories/notification-preferences.js +72 -0
- package/dist-server/server/modules/database/repositories/notification-preferences.js.map +1 -0
- package/dist-server/server/modules/database/repositories/projects.db.integration.test.js +64 -0
- package/dist-server/server/modules/database/repositories/projects.db.integration.test.js.map +1 -0
- package/dist-server/server/modules/database/repositories/projects.db.js +160 -0
- package/dist-server/server/modules/database/repositories/projects.db.js.map +1 -0
- package/dist-server/server/modules/database/repositories/push-subscriptions.js +49 -0
- package/dist-server/server/modules/database/repositories/push-subscriptions.js.map +1 -0
- package/dist-server/server/modules/database/repositories/scan-state.db.js +31 -0
- package/dist-server/server/modules/database/repositories/scan-state.db.js.map +1 -0
- package/dist-server/server/modules/database/repositories/sessions.db.js +109 -0
- package/dist-server/server/modules/database/repositories/sessions.db.js.map +1 -0
- package/dist-server/server/modules/database/repositories/users.js +88 -0
- package/dist-server/server/modules/database/repositories/users.js.map +1 -0
- package/dist-server/server/modules/database/repositories/vapid-keys.js +38 -0
- package/dist-server/server/modules/database/repositories/vapid-keys.js.map +1 -0
- package/dist-server/server/modules/database/schema.js +143 -0
- package/dist-server/server/modules/database/schema.js.map +1 -0
- package/dist-server/server/modules/projects/index.js +4 -0
- package/dist-server/server/modules/projects/index.js.map +1 -0
- package/dist-server/server/modules/projects/projects.routes.js +188 -0
- package/dist-server/server/modules/projects/projects.routes.js.map +1 -0
- package/dist-server/server/modules/projects/services/project-clone.service.js +219 -0
- package/dist-server/server/modules/projects/services/project-clone.service.js.map +1 -0
- package/dist-server/server/modules/projects/services/project-delete.service.js +65 -0
- package/dist-server/server/modules/projects/services/project-delete.service.js.map +1 -0
- package/dist-server/server/modules/projects/services/project-management.service.js +93 -0
- package/dist-server/server/modules/projects/services/project-management.service.js.map +1 -0
- package/dist-server/server/modules/projects/services/project-star.service.js +60 -0
- package/dist-server/server/modules/projects/services/project-star.service.js.map +1 -0
- package/dist-server/server/modules/projects/services/projects-has-taskmaster.service.js +167 -0
- package/dist-server/server/modules/projects/services/projects-has-taskmaster.service.js.map +1 -0
- package/dist-server/server/modules/projects/services/projects-with-sessions-fetch.service.js +169 -0
- package/dist-server/server/modules/projects/services/projects-with-sessions-fetch.service.js.map +1 -0
- package/dist-server/server/modules/projects/tests/project-clone.service.test.js +126 -0
- package/dist-server/server/modules/projects/tests/project-clone.service.test.js.map +1 -0
- package/dist-server/server/modules/projects/tests/project-management.service.test.js +85 -0
- package/dist-server/server/modules/projects/tests/project-management.service.test.js.map +1 -0
- package/dist-server/server/modules/projects/tests/project-star.service.test.js +95 -0
- package/dist-server/server/modules/projects/tests/project-star.service.test.js.map +1 -0
- package/dist-server/server/modules/projects/tests/projects-has-taskmaster.service.test.js +87 -0
- package/dist-server/server/modules/projects/tests/projects-has-taskmaster.service.test.js.map +1 -0
- package/dist-server/server/modules/providers/index.js +4 -0
- package/dist-server/server/modules/providers/index.js.map +1 -0
- package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js +63 -0
- package/dist-server/server/modules/providers/list/claude/claude-session-synchronizer.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js +144 -7
- package/dist-server/server/modules/providers/list/claude/claude-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/claude/claude.provider.js +2 -0
- package/dist-server/server/modules/providers/list/claude/claude.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js +71 -0
- package/dist-server/server/modules/providers/list/codex/codex-session-synchronizer.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js +225 -13
- package/dist-server/server/modules/providers/list/codex/codex-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/codex/codex.provider.js +2 -0
- package/dist-server/server/modules/providers/list/codex/codex.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.js +127 -0
- package/dist-server/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/cursor/cursor.provider.js +2 -0
- package/dist-server/server/modules/providers/list/cursor/cursor.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/gemini/gemini-session-synchronizer.provider.js +296 -0
- package/dist-server/server/modules/providers/list/gemini/gemini-session-synchronizer.provider.js.map +1 -0
- package/dist-server/server/modules/providers/list/gemini/gemini-sessions.provider.js +277 -10
- package/dist-server/server/modules/providers/list/gemini/gemini-sessions.provider.js.map +1 -1
- package/dist-server/server/modules/providers/list/gemini/gemini.provider.js +2 -0
- package/dist-server/server/modules/providers/list/gemini/gemini.provider.js.map +1 -1
- package/dist-server/server/modules/providers/provider.routes.js +172 -0
- package/dist-server/server/modules/providers/provider.routes.js.map +1 -1
- package/dist-server/server/modules/providers/services/session-conversations-search.service.js +868 -0
- package/dist-server/server/modules/providers/services/session-conversations-search.service.js.map +1 -0
- package/dist-server/server/modules/providers/services/session-synchronizer.service.js +56 -0
- package/dist-server/server/modules/providers/services/session-synchronizer.service.js.map +1 -0
- package/dist-server/server/modules/providers/services/sessions-watcher.service.js +234 -0
- package/dist-server/server/modules/providers/services/sessions-watcher.service.js.map +1 -0
- package/dist-server/server/modules/providers/services/sessions.service.js +78 -3
- package/dist-server/server/modules/providers/services/sessions.service.js.map +1 -1
- package/dist-server/server/modules/providers/shared/base/abstract.provider.js.map +1 -1
- package/dist-server/server/modules/websocket/index.js +3 -0
- package/dist-server/server/modules/websocket/index.js.map +1 -0
- package/dist-server/server/modules/websocket/services/chat-websocket.service.js +188 -0
- package/dist-server/server/modules/websocket/services/chat-websocket.service.js.map +1 -0
- package/dist-server/server/modules/websocket/services/plugin-websocket-proxy.service.js +52 -0
- package/dist-server/server/modules/websocket/services/plugin-websocket-proxy.service.js.map +1 -0
- package/dist-server/server/modules/websocket/services/shell-websocket.service.js +334 -0
- package/dist-server/server/modules/websocket/services/shell-websocket.service.js.map +1 -0
- package/dist-server/server/modules/websocket/services/websocket-auth.service.js +32 -0
- package/dist-server/server/modules/websocket/services/websocket-auth.service.js.map +1 -0
- package/dist-server/server/modules/websocket/services/websocket-server.service.js +36 -0
- package/dist-server/server/modules/websocket/services/websocket-server.service.js.map +1 -0
- package/dist-server/server/modules/websocket/services/websocket-state.service.js +14 -0
- package/dist-server/server/modules/websocket/services/websocket-state.service.js.map +1 -0
- package/dist-server/server/modules/websocket/services/websocket-writer.service.js +32 -0
- package/dist-server/server/modules/websocket/services/websocket-writer.service.js.map +1 -0
- package/dist-server/server/routes/agent.js +10 -17
- package/dist-server/server/routes/agent.js.map +1 -1
- package/dist-server/server/routes/auth.js +3 -1
- package/dist-server/server/routes/auth.js.map +1 -1
- package/dist-server/server/routes/commands.js +1 -1
- package/dist-server/server/routes/commands.js.map +1 -1
- package/dist-server/server/routes/gemini.js +2 -2
- package/dist-server/server/routes/gemini.js.map +1 -1
- package/dist-server/server/routes/git.js +33 -29
- package/dist-server/server/routes/git.js.map +1 -1
- package/dist-server/server/routes/settings.js +1 -1
- package/dist-server/server/routes/settings.js.map +1 -1
- package/dist-server/server/routes/taskmaster.js +97 -110
- package/dist-server/server/routes/taskmaster.js.map +1 -1
- package/dist-server/server/routes/user.js +1 -1
- package/dist-server/server/routes/user.js.map +1 -1
- package/dist-server/server/services/notification-orchestrator.js +2 -2
- package/dist-server/server/services/notification-orchestrator.js.map +1 -1
- package/dist-server/server/services/vapid-keys.js +2 -1
- package/dist-server/server/services/vapid-keys.js.map +1 -1
- package/dist-server/server/shared/types.js +0 -1
- package/dist-server/server/shared/types.js.map +1 -1
- package/dist-server/server/shared/utils.js +408 -7
- package/dist-server/server/shared/utils.js.map +1 -1
- package/dist-server/server/utils/taskmaster-websocket.js +18 -12
- package/dist-server/server/utils/taskmaster-websocket.js.map +1 -1
- package/dist-server/shared/modelConstants.js +2 -1
- package/dist-server/shared/modelConstants.js.map +1 -1
- package/package.json +3 -1
- package/server/index.js +146 -1012
- package/server/middleware/auth.js +1 -1
- package/server/modules/database/connection.ts +143 -0
- package/server/modules/database/index.ts +12 -0
- package/server/modules/database/init-db.ts +17 -0
- package/server/modules/database/migrations.ts +442 -0
- package/server/modules/database/repositories/api-keys.ts +119 -0
- package/server/modules/database/repositories/app-config.ts +53 -0
- package/server/modules/database/repositories/credentials.ts +106 -0
- package/server/modules/database/repositories/github-tokens.ts +100 -0
- package/server/modules/database/repositories/notification-preferences.ts +103 -0
- package/server/modules/database/repositories/projects.db.integration.test.ts +72 -0
- package/server/modules/database/repositories/projects.db.ts +183 -0
- package/server/modules/database/repositories/push-subscriptions.ts +80 -0
- package/server/modules/database/repositories/scan-state.db.ts +42 -0
- package/server/modules/database/repositories/sessions.db.ts +174 -0
- package/server/modules/database/repositories/users.ts +140 -0
- package/server/modules/database/repositories/vapid-keys.ts +57 -0
- package/server/modules/database/schema.ts +152 -0
- package/server/modules/projects/index.ts +6 -0
- package/server/modules/projects/projects.routes.ts +247 -0
- package/server/modules/projects/services/project-clone.service.ts +321 -0
- package/server/modules/projects/services/project-delete.service.ts +75 -0
- package/server/modules/projects/services/project-management.service.ts +150 -0
- package/server/modules/projects/services/project-star.service.ts +78 -0
- package/server/modules/projects/services/projects-has-taskmaster.service.ts +248 -0
- package/server/modules/projects/services/projects-with-sessions-fetch.service.ts +285 -0
- package/server/modules/projects/tests/project-clone.service.test.ts +183 -0
- package/server/modules/projects/tests/project-management.service.test.ts +117 -0
- package/server/modules/projects/tests/project-star.service.test.ts +123 -0
- package/server/modules/projects/tests/projects-has-taskmaster.service.test.ts +105 -0
- package/server/modules/providers/index.ts +4 -0
- package/server/modules/providers/list/claude/claude-session-synchronizer.provider.ts +110 -0
- package/server/modules/providers/list/claude/claude-sessions.provider.ts +182 -13
- package/server/modules/providers/list/claude/claude.provider.ts +3 -1
- package/server/modules/providers/list/codex/codex-session-synchronizer.provider.ts +119 -0
- package/server/modules/providers/list/codex/codex-sessions.provider.ts +262 -17
- package/server/modules/providers/list/codex/codex.provider.ts +3 -1
- package/server/modules/providers/list/cursor/cursor-session-synchronizer.provider.ts +176 -0
- package/server/modules/providers/list/cursor/cursor.provider.ts +3 -1
- package/server/modules/providers/list/gemini/gemini-session-synchronizer.provider.ts +401 -0
- package/server/modules/providers/list/gemini/gemini-sessions.provider.ts +327 -13
- package/server/modules/providers/list/gemini/gemini.provider.ts +3 -1
- package/server/modules/providers/provider.routes.ts +220 -12
- package/server/modules/providers/services/session-conversations-search.service.ts +1167 -0
- package/server/modules/providers/services/session-synchronizer.service.ts +74 -0
- package/server/modules/providers/services/sessions-watcher.service.ts +283 -0
- package/server/modules/providers/services/sessions.service.ts +89 -4
- package/server/modules/providers/shared/base/abstract.provider.ts +8 -1
- package/server/modules/websocket/README.md +267 -0
- package/server/modules/websocket/index.ts +2 -0
- package/server/modules/websocket/services/chat-websocket.service.ts +271 -0
- package/server/modules/websocket/services/plugin-websocket-proxy.service.ts +65 -0
- package/server/modules/websocket/services/shell-websocket.service.ts +453 -0
- package/server/modules/websocket/services/websocket-auth.service.ts +54 -0
- package/server/modules/websocket/services/websocket-server.service.ts +58 -0
- package/server/modules/websocket/services/websocket-state.service.ts +16 -0
- package/server/modules/websocket/services/websocket-writer.service.ts +38 -0
- package/server/routes/agent.js +11 -16
- package/server/routes/auth.js +4 -2
- package/server/routes/commands.js +1 -1
- package/server/routes/gemini.js +3 -2
- package/server/routes/git.js +33 -28
- package/server/routes/settings.js +1 -1
- package/server/routes/taskmaster.js +108 -111
- package/server/routes/user.js +1 -1
- package/server/services/notification-orchestrator.js +3 -2
- package/server/services/vapid-keys.js +2 -1
- package/server/shared/interfaces.ts +39 -1
- package/server/shared/types.ts +185 -30
- package/server/shared/utils.ts +485 -9
- package/server/utils/taskmaster-websocket.js +19 -13
- package/shared/modelConstants.js +2 -1
- package/dist/assets/index-RX-W_g_Q.js +0 -1262
- package/dist-server/server/database/db.js +0 -535
- package/dist-server/server/database/db.js.map +0 -1
- package/dist-server/server/database/schema.js +0 -97
- package/dist-server/server/database/schema.js.map +0 -1
- package/dist-server/server/projects.js +0 -2325
- package/dist-server/server/projects.js.map +0 -1
- package/dist-server/server/routes/codex.js +0 -18
- package/dist-server/server/routes/codex.js.map +0 -1
- package/dist-server/server/routes/messages.js +0 -56
- package/dist-server/server/routes/messages.js.map +0 -1
- package/dist-server/server/routes/projects.js +0 -505
- package/dist-server/server/routes/projects.js.map +0 -1
- package/server/database/db.js +0 -593
- package/server/database/schema.js +0 -102
- package/server/projects.js +0 -2555
- package/server/routes/codex.js +0 -19
- package/server/routes/messages.js +0 -61
- package/server/routes/projects.js +0 -548
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VAPID keys repository.
|
|
3
|
+
*
|
|
4
|
+
* Stores and retrieves the Web Push VAPID key pair.
|
|
5
|
+
*/
|
|
6
|
+
import { getConnection } from '../../../modules/database/connection.js';
|
|
7
|
+
export const vapidKeysDb = {
|
|
8
|
+
/** Returns the latest stored VAPID key pair, or null when unset. */
|
|
9
|
+
getVapidKeys() {
|
|
10
|
+
const db = getConnection();
|
|
11
|
+
const row = db
|
|
12
|
+
.prepare('SELECT public_key, private_key FROM vapid_keys ORDER BY id DESC LIMIT 1')
|
|
13
|
+
.get();
|
|
14
|
+
if (!row)
|
|
15
|
+
return null;
|
|
16
|
+
return {
|
|
17
|
+
publicKey: row.public_key,
|
|
18
|
+
privateKey: row.private_key,
|
|
19
|
+
};
|
|
20
|
+
},
|
|
21
|
+
/** Persists a new VAPID key pair. */
|
|
22
|
+
createVapidKeys(publicKey, privateKey) {
|
|
23
|
+
const db = getConnection();
|
|
24
|
+
db.prepare('INSERT INTO vapid_keys (public_key, private_key) VALUES (?, ?)').run(publicKey, privateKey);
|
|
25
|
+
},
|
|
26
|
+
/** Replaces all existing keys with a fresh pair. */
|
|
27
|
+
updateVapidKeys(publicKey, privateKey) {
|
|
28
|
+
const db = getConnection();
|
|
29
|
+
db.prepare('DELETE FROM vapid_keys').run();
|
|
30
|
+
vapidKeysDb.createVapidKeys(publicKey, privateKey);
|
|
31
|
+
},
|
|
32
|
+
/** Deletes all VAPID key rows. */
|
|
33
|
+
deleteVapidKeys() {
|
|
34
|
+
const db = getConnection();
|
|
35
|
+
db.prepare('DELETE FROM vapid_keys').run();
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
//# sourceMappingURL=vapid-keys.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vapid-keys.js","sourceRoot":"","sources":["../../../../../server/modules/database/repositories/vapid-keys.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAYjE,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,oEAAoE;IACpE,YAAY;QACV,MAAM,EAAE,GAAG,aAAa,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,EAAE;aACX,OAAO,CACN,yEAAyE,CAC1E;aACA,GAAG,EAAiE,CAAC;QAExE,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QACtB,OAAO;YACL,SAAS,EAAE,GAAG,CAAC,UAAU;YACzB,UAAU,EAAE,GAAG,CAAC,WAAW;SAC5B,CAAC;IACJ,CAAC;IAED,qCAAqC;IACrC,eAAe,CAAC,SAAiB,EAAE,UAAkB;QACnD,MAAM,EAAE,GAAG,aAAa,EAAE,CAAC;QAC3B,EAAE,CAAC,OAAO,CACR,gEAAgE,CACjE,CAAC,GAAG,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAC/B,CAAC;IAED,oDAAoD;IACpD,eAAe,CAAC,SAAiB,EAAE,UAAkB;QACnD,MAAM,EAAE,GAAG,aAAa,EAAE,CAAC;QAC3B,EAAE,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC,GAAG,EAAE,CAAC;QAC3C,WAAW,CAAC,eAAe,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IACrD,CAAC;IAED,kCAAkC;IAClC,eAAe;QACb,MAAM,EAAE,GAAG,aAAa,EAAE,CAAC;QAC3B,EAAE,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC,GAAG,EAAE,CAAC;IAC7C,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
const USER_TABLE_SCHEMA_SQL = `
|
|
2
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
3
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
4
|
+
username TEXT UNIQUE NOT NULL,
|
|
5
|
+
password_hash TEXT NOT NULL,
|
|
6
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
7
|
+
last_login DATETIME,
|
|
8
|
+
is_active BOOLEAN DEFAULT 1,
|
|
9
|
+
git_name TEXT,
|
|
10
|
+
git_email TEXT,
|
|
11
|
+
has_completed_onboarding BOOLEAN DEFAULT 0
|
|
12
|
+
);
|
|
13
|
+
`;
|
|
14
|
+
export const API_KEYS_TABLE_SCHEMA_SQL = `
|
|
15
|
+
CREATE TABLE IF NOT EXISTS api_keys (
|
|
16
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
17
|
+
user_id INTEGER NOT NULL,
|
|
18
|
+
key_name TEXT NOT NULL,
|
|
19
|
+
api_key TEXT UNIQUE NOT NULL,
|
|
20
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
21
|
+
last_used DATETIME,
|
|
22
|
+
is_active BOOLEAN DEFAULT 1,
|
|
23
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
24
|
+
);
|
|
25
|
+
`;
|
|
26
|
+
export const USER_CREDENTIALS_TABLE_SCHEMA_SQL = `
|
|
27
|
+
CREATE TABLE IF NOT EXISTS user_credentials (
|
|
28
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
29
|
+
user_id INTEGER NOT NULL,
|
|
30
|
+
credential_name TEXT NOT NULL,
|
|
31
|
+
credential_type TEXT NOT NULL, -- 'github_token', 'gitlab_token', 'bitbucket_token', etc.
|
|
32
|
+
credential_value TEXT NOT NULL,
|
|
33
|
+
description TEXT,
|
|
34
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
35
|
+
is_active BOOLEAN DEFAULT 1,
|
|
36
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
37
|
+
);
|
|
38
|
+
`;
|
|
39
|
+
export const USER_NOTIFICATION_PREFERENCES_TABLE_SCHEMA_SQL = `
|
|
40
|
+
CREATE TABLE IF NOT EXISTS user_notification_preferences (
|
|
41
|
+
user_id INTEGER PRIMARY KEY,
|
|
42
|
+
preferences_json TEXT NOT NULL,
|
|
43
|
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
44
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
45
|
+
);
|
|
46
|
+
`;
|
|
47
|
+
export const VAPID_KEYS_TABLE_SCHEMA_SQL = `
|
|
48
|
+
CREATE TABLE IF NOT EXISTS vapid_keys (
|
|
49
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
50
|
+
public_key TEXT NOT NULL,
|
|
51
|
+
private_key TEXT NOT NULL,
|
|
52
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
53
|
+
);
|
|
54
|
+
`;
|
|
55
|
+
export const PUSH_SUBSCRIPTIONS_TABLE_SCHEMA_SQL = `
|
|
56
|
+
CREATE TABLE IF NOT EXISTS push_subscriptions (
|
|
57
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
58
|
+
user_id INTEGER NOT NULL,
|
|
59
|
+
endpoint TEXT NOT NULL UNIQUE,
|
|
60
|
+
keys_p256dh TEXT NOT NULL,
|
|
61
|
+
keys_auth TEXT NOT NULL,
|
|
62
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
63
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
64
|
+
);
|
|
65
|
+
`;
|
|
66
|
+
export const PROJECTS_TABLE_SCHEMA_SQL = `
|
|
67
|
+
CREATE TABLE IF NOT EXISTS projects (
|
|
68
|
+
project_id TEXT PRIMARY KEY NOT NULL,
|
|
69
|
+
project_path TEXT NOT NULL UNIQUE,
|
|
70
|
+
custom_project_name TEXT DEFAULT NULL,
|
|
71
|
+
isStarred BOOLEAN DEFAULT 0,
|
|
72
|
+
isArchived BOOLEAN DEFAULT 0
|
|
73
|
+
);
|
|
74
|
+
`;
|
|
75
|
+
export const SESSIONS_TABLE_SCHEMA_SQL = `
|
|
76
|
+
CREATE TABLE IF NOT EXISTS sessions (
|
|
77
|
+
session_id TEXT NOT NULL,
|
|
78
|
+
provider TEXT NOT NULL DEFAULT 'claude',
|
|
79
|
+
custom_name TEXT,
|
|
80
|
+
project_path TEXT,
|
|
81
|
+
jsonl_path TEXT,
|
|
82
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
83
|
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
84
|
+
PRIMARY KEY (session_id),
|
|
85
|
+
FOREIGN KEY (project_path) REFERENCES projects(project_path)
|
|
86
|
+
ON DELETE SET NULL
|
|
87
|
+
ON UPDATE CASCADE
|
|
88
|
+
);
|
|
89
|
+
`;
|
|
90
|
+
export const LAST_SCANNED_AT_SQL = `
|
|
91
|
+
CREATE TABLE IF NOT EXISTS scan_state (
|
|
92
|
+
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
93
|
+
last_scanned_at TIMESTAMP NULL
|
|
94
|
+
);
|
|
95
|
+
`;
|
|
96
|
+
export const APP_CONFIG_TABLE_SCHEMA_SQL = `
|
|
97
|
+
CREATE TABLE IF NOT EXISTS app_config (
|
|
98
|
+
key TEXT PRIMARY KEY,
|
|
99
|
+
value TEXT NOT NULL,
|
|
100
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
101
|
+
);
|
|
102
|
+
`;
|
|
103
|
+
export const INIT_SCHEMA_SQL = `
|
|
104
|
+
-- Initialize authentication database
|
|
105
|
+
PRAGMA foreign_keys = ON;
|
|
106
|
+
|
|
107
|
+
${USER_TABLE_SCHEMA_SQL}
|
|
108
|
+
-- Indexes for performance for user lookups
|
|
109
|
+
CREATE INDEX IF NOT EXISTS idx_users_username ON users(username);
|
|
110
|
+
CREATE INDEX IF NOT EXISTS idx_users_active ON users(is_active);
|
|
111
|
+
|
|
112
|
+
${API_KEYS_TABLE_SCHEMA_SQL}
|
|
113
|
+
CREATE INDEX IF NOT EXISTS idx_api_keys_key ON api_keys(api_key);
|
|
114
|
+
CREATE INDEX IF NOT EXISTS idx_api_keys_user_id ON api_keys(user_id);
|
|
115
|
+
CREATE INDEX IF NOT EXISTS idx_api_keys_active ON api_keys(is_active);
|
|
116
|
+
|
|
117
|
+
${USER_CREDENTIALS_TABLE_SCHEMA_SQL}
|
|
118
|
+
CREATE INDEX IF NOT EXISTS idx_user_credentials_user_id ON user_credentials(user_id);
|
|
119
|
+
CREATE INDEX IF NOT EXISTS idx_user_credentials_type ON user_credentials(credential_type);
|
|
120
|
+
CREATE INDEX IF NOT EXISTS idx_user_credentials_active ON user_credentials(is_active);
|
|
121
|
+
|
|
122
|
+
${USER_NOTIFICATION_PREFERENCES_TABLE_SCHEMA_SQL}
|
|
123
|
+
CREATE INDEX IF NOT EXISTS idx_user_notification_preferences_user_id ON user_notification_preferences(user_id);
|
|
124
|
+
|
|
125
|
+
${VAPID_KEYS_TABLE_SCHEMA_SQL}
|
|
126
|
+
|
|
127
|
+
${PUSH_SUBSCRIPTIONS_TABLE_SCHEMA_SQL}
|
|
128
|
+
CREATE INDEX IF NOT EXISTS idx_push_subscriptions_user_id ON push_subscriptions(user_id);
|
|
129
|
+
|
|
130
|
+
${PROJECTS_TABLE_SCHEMA_SQL}
|
|
131
|
+
-- NOTE: These indexes are created in migrations after legacy table-shape repairs.
|
|
132
|
+
-- Creating them here can fail on upgraded installs where projects lacks those columns.
|
|
133
|
+
|
|
134
|
+
${SESSIONS_TABLE_SCHEMA_SQL}
|
|
135
|
+
CREATE INDEX IF NOT EXISTS idx_session_ids_lookup ON sessions(session_id);
|
|
136
|
+
-- NOTE: This index is created in migrations after sessions is rebuilt to include project_path.
|
|
137
|
+
-- Creating it here can fail on upgraded installs where the legacy sessions table has no project_path.
|
|
138
|
+
|
|
139
|
+
${LAST_SCANNED_AT_SQL}
|
|
140
|
+
|
|
141
|
+
${APP_CONFIG_TABLE_SCHEMA_SQL}
|
|
142
|
+
`;
|
|
143
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../../server/modules/database/schema.ts"],"names":[],"mappings":"AAAA,MAAM,qBAAqB,GAAG;;;;;;;;;;;;CAY7B,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAG;;;;;;;;;;;CAWxC,CAAC;AAEF,MAAM,CAAC,MAAM,iCAAiC,GAAG;;;;;;;;;;;;CAYhD,CAAC;AAEF,MAAM,CAAC,MAAM,8CAA8C,GAAG;;;;;;;CAO7D,CAAC;AAEF,MAAM,CAAC,MAAM,2BAA2B,GAAG;;;;;;;CAO1C,CAAC;AAEF,MAAM,CAAC,MAAM,mCAAmC,GAAG;;;;;;;;;;CAUlD,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAG;;;;;;;;CAQxC,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAG;;;;;;;;;;;;;;CAcxC,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG;;;;;CAKlC,CAAC;AAEF,MAAM,CAAC,MAAM,2BAA2B,GAAG;;;;;;CAM1C,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG;;;;EAI7B,qBAAqB;;;;;EAKrB,yBAAyB;;;;;EAKzB,iCAAiC;;;;;EAKjC,8CAA8C;;;EAG9C,2BAA2B;;EAE3B,mCAAmC;;;EAGnC,yBAAyB;;;;EAIzB,yBAAyB;;;;;EAKzB,mBAAmB;;EAEnB,2BAA2B;CAC5B,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { generateDisplayName, getProjectsWithSessions, } from './services/projects-with-sessions-fetch.service.js';
|
|
2
|
+
export { updateProjectDisplayName } from './services/project-management.service.js';
|
|
3
|
+
export { deleteOrArchiveProject, deleteSessionJsonlFilesForProjectPath } from './services/project-delete.service.js';
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../server/modules/projects/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,oDAAoD,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,0CAA0C,CAAC;AACpF,OAAO,EAAE,sBAAsB,EAAE,qCAAqC,EAAE,MAAM,sCAAsC,CAAC"}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import { createProject, updateProjectDisplayName } from '../../modules/projects/services/project-management.service.js';
|
|
3
|
+
import { startCloneProject } from '../../modules/projects/services/project-clone.service.js';
|
|
4
|
+
import { getProjectTaskMaster } from '../../modules/projects/services/projects-has-taskmaster.service.js';
|
|
5
|
+
import { AppError, asyncHandler } from '../../shared/utils.js';
|
|
6
|
+
import { getProjectSessionsPage, getProjectsWithSessions } from '../../modules/projects/services/projects-with-sessions-fetch.service.js';
|
|
7
|
+
import { deleteOrArchiveProject } from '../../modules/projects/services/project-delete.service.js';
|
|
8
|
+
import { applyLegacyStarredProjectIds, toggleProjectStar } from '../../modules/projects/services/project-star.service.js';
|
|
9
|
+
const router = express.Router();
|
|
10
|
+
function readQueryStringValue(value) {
|
|
11
|
+
if (typeof value === 'string') {
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
if (Array.isArray(value) && typeof value[0] === 'string') {
|
|
15
|
+
return value[0];
|
|
16
|
+
}
|
|
17
|
+
return '';
|
|
18
|
+
}
|
|
19
|
+
function readOptionalNumericQueryValue(value) {
|
|
20
|
+
const rawValue = readQueryStringValue(value).trim();
|
|
21
|
+
if (!rawValue) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const parsedValue = Number.parseInt(rawValue, 10);
|
|
25
|
+
return Number.isNaN(parsedValue) ? null : parsedValue;
|
|
26
|
+
}
|
|
27
|
+
function parseNonNegativeIntQuery(value, name, fallback) {
|
|
28
|
+
const rawValue = readQueryStringValue(value).trim();
|
|
29
|
+
if (!rawValue) {
|
|
30
|
+
return fallback;
|
|
31
|
+
}
|
|
32
|
+
const parsedValue = Number.parseInt(rawValue, 10);
|
|
33
|
+
if (Number.isNaN(parsedValue) || parsedValue < 0) {
|
|
34
|
+
throw new AppError(`${name} must be a non-negative integer`, {
|
|
35
|
+
code: 'INVALID_QUERY_PARAMETER',
|
|
36
|
+
statusCode: 400,
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return parsedValue;
|
|
40
|
+
}
|
|
41
|
+
function resolveRouteErrorMessage(error) {
|
|
42
|
+
if (error instanceof AppError) {
|
|
43
|
+
return error.message;
|
|
44
|
+
}
|
|
45
|
+
if (error instanceof Error && error.message) {
|
|
46
|
+
return error.message;
|
|
47
|
+
}
|
|
48
|
+
return 'Failed to clone repository';
|
|
49
|
+
}
|
|
50
|
+
router.get('/', asyncHandler(async (_req, res) => {
|
|
51
|
+
const projects = await getProjectsWithSessions();
|
|
52
|
+
res.json(projects);
|
|
53
|
+
}));
|
|
54
|
+
router.get('/:projectId/sessions', asyncHandler(async (req, res) => {
|
|
55
|
+
const projectId = typeof req.params.projectId === 'string' ? req.params.projectId : '';
|
|
56
|
+
const limit = parseNonNegativeIntQuery(req.query.limit, 'limit', 20);
|
|
57
|
+
const offset = parseNonNegativeIntQuery(req.query.offset, 'offset', 0);
|
|
58
|
+
const sessionsPage = await getProjectSessionsPage(projectId, { limit, offset });
|
|
59
|
+
res.json(sessionsPage);
|
|
60
|
+
}));
|
|
61
|
+
router.post('/create-project', asyncHandler(async (req, res) => {
|
|
62
|
+
const requestBody = req.body;
|
|
63
|
+
const projectPath = typeof requestBody.path === 'string' ? requestBody.path : '';
|
|
64
|
+
const customName = typeof requestBody.customName === 'string' ? requestBody.customName : null;
|
|
65
|
+
if (requestBody.workspaceType !== undefined) {
|
|
66
|
+
throw new AppError('workspaceType is no longer supported. Use the single create-project flow.', {
|
|
67
|
+
code: 'LEGACY_WORKSPACE_TYPE_UNSUPPORTED',
|
|
68
|
+
statusCode: 400,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
if (requestBody.githubUrl || requestBody.githubTokenId || requestBody.newGithubToken) {
|
|
72
|
+
throw new AppError('Repository cloning is not supported on create-project', {
|
|
73
|
+
code: 'CLONE_NOT_SUPPORTED_ON_CREATE_PROJECT',
|
|
74
|
+
statusCode: 400,
|
|
75
|
+
details: 'Use /api/projects/clone-progress for cloning workflows',
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
const projectCreationResult = await createProject({
|
|
79
|
+
projectPath,
|
|
80
|
+
customName,
|
|
81
|
+
});
|
|
82
|
+
res.json({
|
|
83
|
+
success: true,
|
|
84
|
+
project: projectCreationResult.project,
|
|
85
|
+
message: projectCreationResult.outcome === 'reactivated_archived'
|
|
86
|
+
? 'Archived project path reused successfully'
|
|
87
|
+
: 'Project created successfully',
|
|
88
|
+
});
|
|
89
|
+
}));
|
|
90
|
+
/**
|
|
91
|
+
* One-time (or idempotent) migration: apply legacy `localStorage` starred projectIds to the DB, then clear client storage.
|
|
92
|
+
*/
|
|
93
|
+
router.post('/migrate-legacy-stars', asyncHandler(async (req, res) => {
|
|
94
|
+
const projectIds = Array.isArray(req.body?.projectIds)
|
|
95
|
+
? req.body.projectIds.map((x) => String(x))
|
|
96
|
+
: [];
|
|
97
|
+
const { updated } = applyLegacyStarredProjectIds(projectIds);
|
|
98
|
+
res.json({ success: true, updated });
|
|
99
|
+
}));
|
|
100
|
+
router.get('/clone-progress', async (req, res) => {
|
|
101
|
+
res.setHeader('Content-Type', 'text/event-stream');
|
|
102
|
+
res.setHeader('Cache-Control', 'no-cache');
|
|
103
|
+
res.setHeader('Connection', 'keep-alive');
|
|
104
|
+
res.flushHeaders();
|
|
105
|
+
const sendEvent = (type, data) => {
|
|
106
|
+
if (res.writableEnded) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
res.write(`data: ${JSON.stringify({ type, ...data })}\n\n`);
|
|
110
|
+
};
|
|
111
|
+
let cloneOperation = null;
|
|
112
|
+
const closeListener = () => {
|
|
113
|
+
cloneOperation?.cancel();
|
|
114
|
+
};
|
|
115
|
+
req.on('close', closeListener);
|
|
116
|
+
try {
|
|
117
|
+
const queryParams = req.query;
|
|
118
|
+
const workspacePath = readQueryStringValue(queryParams.path);
|
|
119
|
+
const githubUrl = readQueryStringValue(queryParams.githubUrl);
|
|
120
|
+
const githubTokenId = readOptionalNumericQueryValue(queryParams.githubTokenId);
|
|
121
|
+
const newGithubToken = readQueryStringValue(queryParams.newGithubToken) || null;
|
|
122
|
+
const authenticatedUser = req.user;
|
|
123
|
+
const userId = authenticatedUser?.id;
|
|
124
|
+
if (userId === undefined || userId === null) {
|
|
125
|
+
throw new AppError('Authenticated user is required', {
|
|
126
|
+
code: 'AUTHENTICATION_REQUIRED',
|
|
127
|
+
statusCode: 401,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
cloneOperation = await startCloneProject({
|
|
131
|
+
workspacePath,
|
|
132
|
+
githubUrl,
|
|
133
|
+
githubTokenId,
|
|
134
|
+
newGithubToken,
|
|
135
|
+
userId,
|
|
136
|
+
}, {
|
|
137
|
+
onProgress: (message) => {
|
|
138
|
+
sendEvent('progress', { message });
|
|
139
|
+
},
|
|
140
|
+
onComplete: ({ project, message }) => {
|
|
141
|
+
sendEvent('complete', { project, message });
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
await cloneOperation.waitForCompletion;
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
sendEvent('error', { message: resolveRouteErrorMessage(error) });
|
|
148
|
+
}
|
|
149
|
+
finally {
|
|
150
|
+
req.off('close', closeListener);
|
|
151
|
+
if (!res.writableEnded) {
|
|
152
|
+
res.end();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
router.get('/:projectId/taskmaster', asyncHandler(async (req, res) => {
|
|
157
|
+
const projectId = typeof req.params.projectId === 'string' ? req.params.projectId : '';
|
|
158
|
+
const taskMasterDetails = await getProjectTaskMaster(projectId);
|
|
159
|
+
res.json(taskMasterDetails);
|
|
160
|
+
}));
|
|
161
|
+
router.put('/:projectId/rename', (req, res) => {
|
|
162
|
+
try {
|
|
163
|
+
const projectId = typeof req.params.projectId === 'string' ? req.params.projectId : '';
|
|
164
|
+
const { displayName } = req.body;
|
|
165
|
+
updateProjectDisplayName(projectId, displayName);
|
|
166
|
+
res.json({ success: true });
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
res.status(500).json({ error: error instanceof Error ? error.message : 'Failed to rename project' });
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
router.post('/:projectId/toggle-star', asyncHandler(async (req, res) => {
|
|
173
|
+
const projectId = typeof req.params.projectId === 'string' ? req.params.projectId : '';
|
|
174
|
+
const { isStarred } = toggleProjectStar(projectId);
|
|
175
|
+
res.json({ success: true, isStarred });
|
|
176
|
+
}));
|
|
177
|
+
/**
|
|
178
|
+
* - `force` not set / false: archive project in DB only (`isArchived` = 1; hidden from active list).
|
|
179
|
+
* - `force=true`: remove DB row, delete session rows for that path, remove all `*.jsonl` under the Claude project dir.
|
|
180
|
+
*/
|
|
181
|
+
router.delete('/:projectId', asyncHandler(async (req, res) => {
|
|
182
|
+
const projectId = typeof req.params.projectId === 'string' ? req.params.projectId : '';
|
|
183
|
+
const force = req.query.force === 'true';
|
|
184
|
+
await deleteOrArchiveProject(projectId, force);
|
|
185
|
+
res.json({ success: true });
|
|
186
|
+
}));
|
|
187
|
+
export default router;
|
|
188
|
+
//# sourceMappingURL=projects.routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projects.routes.js","sourceRoot":"","sources":["../../../../server/modules/projects/projects.routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { access, mkdir, rm } from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { githubTokensDb } from '../../../modules/database/index.js';
|
|
5
|
+
import { createProject } from '../../../modules/projects/services/project-management.service.js';
|
|
6
|
+
import { AppError, validateWorkspacePath } from '../../../shared/utils.js';
|
|
7
|
+
async function defaultPathExists(targetPath) {
|
|
8
|
+
try {
|
|
9
|
+
await access(targetPath);
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
catch (error) {
|
|
13
|
+
if (error.code === 'ENOENT') {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
throw error;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function sanitizeGitError(message, token) {
|
|
20
|
+
if (!message || !token) {
|
|
21
|
+
return message;
|
|
22
|
+
}
|
|
23
|
+
const escapedToken = token.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
24
|
+
return message.replace(new RegExp(escapedToken, 'g'), '***');
|
|
25
|
+
}
|
|
26
|
+
function resolveCloneFailureMessage(lastError, sanitizedError) {
|
|
27
|
+
if (lastError.includes('Authentication failed') || lastError.includes('could not read Username')) {
|
|
28
|
+
return 'Authentication failed. Please check your credentials.';
|
|
29
|
+
}
|
|
30
|
+
if (lastError.includes('Repository not found')) {
|
|
31
|
+
return 'Repository not found. Please check the URL and ensure you have access.';
|
|
32
|
+
}
|
|
33
|
+
if (lastError.includes('already exists')) {
|
|
34
|
+
return 'Directory already exists';
|
|
35
|
+
}
|
|
36
|
+
if (sanitizedError) {
|
|
37
|
+
return sanitizedError;
|
|
38
|
+
}
|
|
39
|
+
return 'Git clone failed';
|
|
40
|
+
}
|
|
41
|
+
function resolveErrorMessage(error) {
|
|
42
|
+
if (error instanceof AppError) {
|
|
43
|
+
return error.message;
|
|
44
|
+
}
|
|
45
|
+
if (error instanceof Error && error.message) {
|
|
46
|
+
return error.message;
|
|
47
|
+
}
|
|
48
|
+
return 'Unexpected error';
|
|
49
|
+
}
|
|
50
|
+
const defaultDependencies = {
|
|
51
|
+
validatePath: validateWorkspacePath,
|
|
52
|
+
ensureDirectory: async (directoryPath) => {
|
|
53
|
+
await mkdir(directoryPath, { recursive: true });
|
|
54
|
+
},
|
|
55
|
+
pathExists: defaultPathExists,
|
|
56
|
+
removePath: async (targetPath) => {
|
|
57
|
+
await rm(targetPath, { recursive: true, force: true });
|
|
58
|
+
},
|
|
59
|
+
getGithubTokenById: async (tokenId, userId) => {
|
|
60
|
+
const tokenRow = githubTokensDb.getGithubTokenById(userId, tokenId);
|
|
61
|
+
return tokenRow;
|
|
62
|
+
},
|
|
63
|
+
spawnGitClone: (cloneUrl, clonePath) => spawn('git', ['clone', '--progress', '--', cloneUrl, clonePath], {
|
|
64
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
65
|
+
env: {
|
|
66
|
+
...process.env,
|
|
67
|
+
GIT_TERMINAL_PROMPT: '0',
|
|
68
|
+
},
|
|
69
|
+
}),
|
|
70
|
+
registerProject: async (projectPath, customName) => createProject({
|
|
71
|
+
projectPath,
|
|
72
|
+
customName,
|
|
73
|
+
}),
|
|
74
|
+
logError: (message, error) => {
|
|
75
|
+
console.error(message, error);
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
export async function startCloneProject(input, handlers, dependencies = defaultDependencies) {
|
|
79
|
+
const normalizedWorkspacePath = input.workspacePath.trim();
|
|
80
|
+
const normalizedGithubUrl = input.githubUrl.trim();
|
|
81
|
+
if (!normalizedWorkspacePath) {
|
|
82
|
+
throw new AppError('workspacePath and githubUrl are required', {
|
|
83
|
+
code: 'WORKSPACE_PATH_REQUIRED',
|
|
84
|
+
statusCode: 400,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
if (!normalizedGithubUrl) {
|
|
88
|
+
throw new AppError('workspacePath and githubUrl are required', {
|
|
89
|
+
code: 'GITHUB_URL_REQUIRED',
|
|
90
|
+
statusCode: 400,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
if (normalizedGithubUrl.startsWith('-')) {
|
|
94
|
+
throw new AppError('Invalid githubUrl', {
|
|
95
|
+
code: 'INVALID_GITHUB_URL',
|
|
96
|
+
statusCode: 400,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
const pathValidation = await dependencies.validatePath(normalizedWorkspacePath);
|
|
100
|
+
if (!pathValidation.valid || !pathValidation.resolvedPath) {
|
|
101
|
+
throw new AppError(pathValidation.error || 'Invalid workspace path', {
|
|
102
|
+
code: 'INVALID_PROJECT_PATH',
|
|
103
|
+
statusCode: 400,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
const absolutePath = pathValidation.resolvedPath;
|
|
107
|
+
await dependencies.ensureDirectory(absolutePath);
|
|
108
|
+
let githubToken = null;
|
|
109
|
+
if (typeof input.githubTokenId === 'number') {
|
|
110
|
+
const numericUserId = typeof input.userId === 'number' ? input.userId : Number.parseInt(String(input.userId), 10);
|
|
111
|
+
if (Number.isNaN(numericUserId)) {
|
|
112
|
+
throw new AppError('Authenticated user is required', {
|
|
113
|
+
code: 'AUTHENTICATION_REQUIRED',
|
|
114
|
+
statusCode: 401,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
const token = await dependencies.getGithubTokenById(input.githubTokenId, numericUserId);
|
|
118
|
+
if (!token) {
|
|
119
|
+
throw new AppError('GitHub token not found', {
|
|
120
|
+
code: 'GITHUB_TOKEN_NOT_FOUND',
|
|
121
|
+
statusCode: 404,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
githubToken = token.github_token;
|
|
125
|
+
}
|
|
126
|
+
else if (input.newGithubToken && input.newGithubToken.trim().length > 0) {
|
|
127
|
+
githubToken = input.newGithubToken.trim();
|
|
128
|
+
}
|
|
129
|
+
const sanitizedGithubUrl = normalizedGithubUrl.replace(/\/+$/, '').replace(/\.git$/, '');
|
|
130
|
+
const repoName = sanitizedGithubUrl.split('/').pop() || 'repository';
|
|
131
|
+
const clonePath = path.join(absolutePath, repoName);
|
|
132
|
+
if (await dependencies.pathExists(clonePath)) {
|
|
133
|
+
throw new AppError(`Directory "${repoName}" already exists. Please choose a different location or remove the existing directory.`, {
|
|
134
|
+
code: 'CLONE_TARGET_ALREADY_EXISTS',
|
|
135
|
+
statusCode: 409,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
let cloneUrl = normalizedGithubUrl;
|
|
139
|
+
if (githubToken) {
|
|
140
|
+
try {
|
|
141
|
+
const url = new URL(normalizedGithubUrl);
|
|
142
|
+
url.username = githubToken;
|
|
143
|
+
url.password = '';
|
|
144
|
+
cloneUrl = url.toString();
|
|
145
|
+
}
|
|
146
|
+
catch {
|
|
147
|
+
// SSH URLs cannot be represented by URL constructor and are used as-is.
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
handlers.onProgress(`Cloning into '${repoName}'...`);
|
|
151
|
+
const gitProcess = dependencies.spawnGitClone(cloneUrl, clonePath);
|
|
152
|
+
let lastError = '';
|
|
153
|
+
gitProcess.stdout?.on('data', (data) => {
|
|
154
|
+
const message = data.toString().trim();
|
|
155
|
+
if (message) {
|
|
156
|
+
handlers.onProgress(message);
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
gitProcess.stderr?.on('data', (data) => {
|
|
160
|
+
const message = data.toString().trim();
|
|
161
|
+
lastError = message;
|
|
162
|
+
if (message) {
|
|
163
|
+
handlers.onProgress(message);
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
const waitForCompletion = new Promise((resolve, reject) => {
|
|
167
|
+
gitProcess.on('close', async (code) => {
|
|
168
|
+
if (code === 0) {
|
|
169
|
+
try {
|
|
170
|
+
const createdProject = await dependencies.registerProject(clonePath, repoName);
|
|
171
|
+
handlers.onComplete({
|
|
172
|
+
project: createdProject.project,
|
|
173
|
+
message: 'Repository cloned successfully',
|
|
174
|
+
});
|
|
175
|
+
resolve();
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
reject(new AppError(`Clone succeeded but failed to add project: ${resolveErrorMessage(error)}`, {
|
|
179
|
+
code: 'CLONE_PROJECT_REGISTRATION_FAILED',
|
|
180
|
+
statusCode: 500,
|
|
181
|
+
}));
|
|
182
|
+
}
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const sanitizedError = sanitizeGitError(lastError, githubToken);
|
|
186
|
+
const errorMessage = resolveCloneFailureMessage(lastError, sanitizedError);
|
|
187
|
+
try {
|
|
188
|
+
await dependencies.removePath(clonePath);
|
|
189
|
+
}
|
|
190
|
+
catch (cleanupError) {
|
|
191
|
+
dependencies.logError('Failed to clean up after clone failure:', cleanupError);
|
|
192
|
+
}
|
|
193
|
+
reject(new AppError(errorMessage, {
|
|
194
|
+
code: 'GIT_CLONE_FAILED',
|
|
195
|
+
statusCode: 500,
|
|
196
|
+
}));
|
|
197
|
+
});
|
|
198
|
+
gitProcess.on('error', (error) => {
|
|
199
|
+
if (error.code === 'ENOENT') {
|
|
200
|
+
reject(new AppError('Git is not installed or not in PATH', {
|
|
201
|
+
code: 'GIT_NOT_FOUND',
|
|
202
|
+
statusCode: 500,
|
|
203
|
+
}));
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
reject(new AppError(error.message, {
|
|
207
|
+
code: 'GIT_EXECUTION_FAILED',
|
|
208
|
+
statusCode: 500,
|
|
209
|
+
}));
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
return {
|
|
213
|
+
waitForCompletion,
|
|
214
|
+
cancel: () => {
|
|
215
|
+
gitProcess.kill();
|
|
216
|
+
},
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=project-clone.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-clone.service.js","sourceRoot":"","sources":["../../../../../server/modules/projects/services/project-clone.service.ts"],"names":[],"mappings":"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"}
|