This repository has been archived on 2026-08-23. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
pi-web/src/server/sessions/sessionArchiveTree.ts
T

48 lines
1.8 KiB
TypeScript

export interface SessionArchiveTreeCandidate {
id: string;
path: string;
archived: boolean;
parentSessionPath?: string;
}
export interface SessionArchiveTreePlan<T extends SessionArchiveTreeCandidate> {
targets: T[];
unarchivedTargets: T[];
skippedAlreadyArchivedCount: number;
}
export function findArchiveCandidateByIdOrPrefix<T extends SessionArchiveTreeCandidate>(candidates: readonly T[], sessionId: string): T | undefined {
return candidates.find((candidate) => candidate.id === sessionId) ?? candidates.find((candidate) => candidate.id.startsWith(sessionId));
}
export function planSessionArchiveTree<T extends SessionArchiveTreeCandidate>(root: T, candidates: readonly T[]): SessionArchiveTreePlan<T> {
const targets = sessionArchiveSubtree(root, candidates);
const unarchivedTargets = targets.filter((target) => !target.archived);
return {
targets,
unarchivedTargets,
skippedAlreadyArchivedCount: targets.length - unarchivedTargets.length,
};
}
function sessionArchiveSubtree<T extends SessionArchiveTreeCandidate>(root: T, candidates: readonly T[]): T[] {
const childrenByParentPath = new Map<string, T[]>();
for (const candidate of candidates) {
if (candidate.parentSessionPath === undefined) continue;
const children = childrenByParentPath.get(candidate.parentSessionPath) ?? [];
children.push(candidate);
childrenByParentPath.set(candidate.parentSessionPath, children);
}
const result: T[] = [];
const visit = (candidate: T, seenPaths: Set<string>) => {
if (seenPaths.has(candidate.path)) return;
result.push(candidate);
const nextSeenPaths = new Set(seenPaths);
nextSeenPaths.add(candidate.path);
for (const child of childrenByParentPath.get(candidate.path) ?? []) visit(child, nextSeenPaths);
};
visit(root, new Set());
return result;
}