feat: add session manager with CRUD, switching, bookmarks
This commit is contained in:
@@ -0,0 +1,92 @@
|
|||||||
|
import { Store, type SessionInfo } from "../state/store.js";
|
||||||
|
import { basename } from "path";
|
||||||
|
|
||||||
|
export class SessionManager {
|
||||||
|
constructor(private store: Store) {}
|
||||||
|
|
||||||
|
get activeSession(): string | null {
|
||||||
|
return this.store.data.activeSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
get activeSessionInfo(): SessionInfo | null {
|
||||||
|
const name = this.store.data.activeSession;
|
||||||
|
if (!name) return null;
|
||||||
|
return this.store.data.sessions[name] ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
getAllSessions(): Record<string, SessionInfo> {
|
||||||
|
return this.store.data.sessions;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolveProjectPath(nameOrPath: string): { name: string; path: string } | null {
|
||||||
|
const bookmarked = this.store.data.projects[nameOrPath];
|
||||||
|
if (bookmarked) {
|
||||||
|
return { name: nameOrPath, path: bookmarked };
|
||||||
|
}
|
||||||
|
const name = this.generateName(basename(nameOrPath));
|
||||||
|
return { name, path: nameOrPath };
|
||||||
|
}
|
||||||
|
|
||||||
|
private generateName(base: string): string {
|
||||||
|
if (!this.store.data.sessions[base]) return base;
|
||||||
|
let i = 2;
|
||||||
|
while (this.store.data.sessions[`${base}-${i}`]) i++;
|
||||||
|
return `${base}-${i}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
createSession(name: string, cwd: string, sessionId: string): void {
|
||||||
|
this.store.data.sessions[name] = { sessionId, cwd, status: "idle" };
|
||||||
|
this.store.data.activeSession = name;
|
||||||
|
this.store.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
stopSession(name: string): boolean {
|
||||||
|
if (!this.store.data.sessions[name]) return false;
|
||||||
|
delete this.store.data.sessions[name];
|
||||||
|
if (this.store.data.activeSession === name) {
|
||||||
|
const remaining = Object.keys(this.store.data.sessions);
|
||||||
|
this.store.data.activeSession = remaining.length > 0 ? remaining[0] : null;
|
||||||
|
}
|
||||||
|
this.store.save();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
stopAll(): number {
|
||||||
|
const count = Object.keys(this.store.data.sessions).length;
|
||||||
|
this.store.data.sessions = {};
|
||||||
|
this.store.data.activeSession = null;
|
||||||
|
this.store.save();
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
switchSession(name: string): boolean {
|
||||||
|
if (!this.store.data.sessions[name]) return false;
|
||||||
|
this.store.data.activeSession = name;
|
||||||
|
this.store.save();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
setStatus(name: string, status: "idle" | "busy"): void {
|
||||||
|
const session = this.store.data.sessions[name];
|
||||||
|
if (session) {
|
||||||
|
session.status = status;
|
||||||
|
this.store.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
saveProject(name: string, path: string): void {
|
||||||
|
this.store.data.projects[name] = path;
|
||||||
|
this.store.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
removeProject(name: string): boolean {
|
||||||
|
if (!this.store.data.projects[name]) return false;
|
||||||
|
delete this.store.data.projects[name];
|
||||||
|
this.store.save();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
getProjects(): Record<string, string> {
|
||||||
|
return this.store.data.projects;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user