refactor(server): extract shared task graph utilities (#839)

* refactor(server): extract checkout status projection

* refactor(server): extract shared task graph utilities
This commit is contained in:
Mohamed Boudra
2026-05-09 21:28:40 +08:00
committed by GitHub
parent e5deb90986
commit 73f35537f9
3 changed files with 89 additions and 121 deletions
+66
View File
@@ -0,0 +1,66 @@
import type { Task, TaskStore } from "./types.js";
export interface TaskGraph {
allTasks: Task[];
candidates: Task[];
taskMap: Map<string, Task>;
childrenMap: Map<string, Task[]>;
candidateIds: Set<string>;
}
type TaskGraphStore = Pick<TaskStore, "list" | "get" | "getDescendants">;
export function sortByPriorityThenCreated(a: Task, b: Task): number {
if (a.priority !== undefined && b.priority === undefined) return -1;
if (a.priority === undefined && b.priority !== undefined) return 1;
if (a.priority !== undefined && b.priority !== undefined) {
if (a.priority !== b.priority) return a.priority - b.priority;
}
return a.created.localeCompare(b.created);
}
export function buildTaskMap(tasks: Task[]): Map<string, Task> {
return new Map(tasks.map((task) => [task.id, task]));
}
export function buildChildrenMap(tasks: Task[]): Map<string, Task[]> {
const childrenMap = new Map<string, Task[]>();
for (const task of tasks) {
if (task.parentId) {
const siblings = childrenMap.get(task.parentId) ?? [];
siblings.push(task);
childrenMap.set(task.parentId, siblings);
}
}
return childrenMap;
}
export async function loadScopedTaskGraph(
store: TaskGraphStore,
scopeId?: string,
): Promise<TaskGraph> {
const allTasks = await store.list();
const candidates = await loadScopedCandidates(store, allTasks, scopeId);
return {
allTasks,
candidates,
taskMap: buildTaskMap(allTasks),
childrenMap: buildChildrenMap(allTasks),
candidateIds: new Set(candidates.map((task) => task.id)),
};
}
async function loadScopedCandidates(
store: TaskGraphStore,
allTasks: Task[],
scopeId?: string,
): Promise<Task[]> {
if (!scopeId) {
return allTasks;
}
const scopeTask = await store.get(scopeId);
const descendants = await store.getDescendants(scopeId);
return scopeTask ? [scopeTask, ...descendants] : descendants;
}