mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-05-01 10:18:37 +00:00
76 lines
2.2 KiB
TypeScript
76 lines
2.2 KiB
TypeScript
import { promises as fs } from 'node:fs';
|
|
import path from 'node:path';
|
|
|
|
import { projectsDb, sessionsDb } from '@/modules/database/index.js';
|
|
import { AppError } from '@/shared/utils.js';
|
|
|
|
function uniqueJsonlPathsFromSessions(
|
|
sessions: Array<{ jsonl_path: string | null }>,
|
|
): string[] {
|
|
const seen = new Set<string>();
|
|
const result: string[] = [];
|
|
|
|
for (const row of sessions) {
|
|
const raw = row.jsonl_path?.trim();
|
|
if (!raw) {
|
|
continue;
|
|
}
|
|
const absolute = path.isAbsolute(raw) ? path.normalize(raw) : path.resolve(raw);
|
|
if (seen.has(absolute)) {
|
|
continue;
|
|
}
|
|
seen.add(absolute);
|
|
result.push(absolute);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
async function unlinkJsonlIfExists(filePath: string): Promise<void> {
|
|
try {
|
|
await fs.unlink(filePath);
|
|
} catch (error) {
|
|
const code = (error as NodeJS.ErrnoException).code;
|
|
if (code === 'ENOENT') {
|
|
return;
|
|
}
|
|
console.warn(`[project-delete] Failed to remove ${filePath}:`, (error as Error).message);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Loads all session rows for the project path and removes each distinct `jsonl_path` file on disk.
|
|
*/
|
|
export async function deleteSessionJsonlFilesForProjectPath(projectPath: string): Promise<void> {
|
|
const sessions = sessionsDb.getSessionsByProjectPath(projectPath);
|
|
const paths = uniqueJsonlPathsFromSessions(sessions);
|
|
|
|
for (const filePath of paths) {
|
|
await unlinkJsonlIfExists(filePath);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* - **Soft delete** (`force` false): set `isArchived` on the `projects` row (hide from the active list; DB only).
|
|
* - **Force** (`force` true): for each session row for that `project_path`, delete the file at `jsonl_path`
|
|
* (when set), then remove session rows and the `projects` row.
|
|
*/
|
|
export async function deleteOrArchiveProject(projectId: string, force: boolean): Promise<void> {
|
|
const row = projectsDb.getProjectById(projectId);
|
|
if (!row) {
|
|
throw new AppError(`Unknown projectId: ${projectId}`, {
|
|
code: 'PROJECT_NOT_FOUND',
|
|
statusCode: 404,
|
|
});
|
|
}
|
|
|
|
if (!force) {
|
|
projectsDb.updateProjectIsArchivedById(projectId, true);
|
|
return;
|
|
}
|
|
|
|
await deleteSessionJsonlFilesForProjectPath(row.project_path);
|
|
sessionsDb.deleteSessionsByProjectPath(row.project_path);
|
|
projectsDb.deleteProjectById(projectId);
|
|
}
|