import { clearWorkspaceArchivePending, markWorkspaceArchivePending, } from "@/contexts/session-workspace-upserts"; import { useSessionStore, type WorkspaceDescriptor } from "@/stores/session-store"; import { resolveWorkspaceMapKeyByIdentity } from "@/utils/workspace-execution"; export interface WorkspaceArchiveTarget { serverId: string; workspaceId: string; workspaceDirectory?: string | null; } interface WorkspaceArchiveClient { archiveWorkspace: (workspaceId: string) => Promise<{ error: string | null }>; } interface OptimisticWorkspaceArchiveSnapshot { workspace: WorkspaceDescriptor | null; } export interface WorkspaceArchiveFailure { workspaceId: string; error: unknown; } function isWorkspaceArchiveFailure(error: unknown): error is WorkspaceArchiveFailure { return ( typeof error === "object" && error !== null && "workspaceId" in error && typeof error.workspaceId === "string" && "error" in error ); } function hideWorkspaceOptimistically( workspace: WorkspaceArchiveTarget, ): OptimisticWorkspaceArchiveSnapshot { const workspaces = useSessionStore.getState().sessions[workspace.serverId]?.workspaces; const workspaceKey = resolveWorkspaceMapKeyByIdentity({ workspaces, workspaceId: workspace.workspaceId, }); const snapshot = workspaceKey ? (workspaces?.get(workspaceKey) ?? null) : null; markWorkspaceArchivePending({ serverId: workspace.serverId, workspaceId: workspace.workspaceId, workspaceDirectory: workspace.workspaceDirectory, }); useSessionStore.getState().removeWorkspace(workspace.serverId, workspace.workspaceId); return { workspace: snapshot }; } function restoreOptimisticallyHiddenWorkspace(input: { serverId: string; workspaceId: string; snapshot: OptimisticWorkspaceArchiveSnapshot; }): void { clearWorkspaceArchivePending({ serverId: input.serverId, workspaceId: input.workspaceId, }); if (input.snapshot.workspace) { useSessionStore.getState().mergeWorkspaces(input.serverId, [input.snapshot.workspace]); } } async function archiveWorkspaceOrThrow(input: { client: WorkspaceArchiveClient; workspaceId: string; }): Promise { const payload = await input.client.archiveWorkspace(input.workspaceId); if (payload.error) { throw new Error(payload.error); } } export async function archiveWorkspaceOptimistically(input: { client: WorkspaceArchiveClient; workspace: WorkspaceArchiveTarget; afterHide?: () => void; }): Promise { const snapshot = hideWorkspaceOptimistically(input.workspace); input.afterHide?.(); try { await archiveWorkspaceOrThrow({ client: input.client, workspaceId: input.workspace.workspaceId, }); } catch (error) { restoreOptimisticallyHiddenWorkspace({ serverId: input.workspace.serverId, workspaceId: input.workspace.workspaceId, snapshot, }); throw error; } } export async function archiveWorkspacesOptimistically(input: { client: WorkspaceArchiveClient; workspaces: WorkspaceArchiveTarget[]; }): Promise { const results = await Promise.allSettled( input.workspaces.map(async (workspace) => { try { await archiveWorkspaceOptimistically({ client: input.client, workspace, }); } catch (error) { throw { workspaceId: workspace.workspaceId, error } satisfies WorkspaceArchiveFailure; } }), ); return results.flatMap((result) => result.status === "rejected" && isWorkspaceArchiveFailure(result.reason) ? [result.reason] : [], ); }