Files
fusion/packages/dashboard/app/utils/nodeProjectAssignment.ts
gsxdsm 0489f035b5 fix: scope all git, activity, webhook, and summarize-title routes to correct project store
- Fix 30 git routes to use getScopedStore(req) instead of global store
- Fix activity GET/DELETE routes to use scoped store
- Fix POST /api/github/webhooks to use scoped store for badge updates
- Fix POST /api/ai/summarize-title to use scoped store for settings
- Fix GET /api/git/worktrees to use scoped store for task listing
- Add projectId parameter to all git and activity frontend API functions
- Update useActivityLog hook to pass projectId through

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
2026-04-12 17:55:07 -07:00

76 lines
2.4 KiB
TypeScript

/**
* Node-Project Assignment Utilities
*
* Provides canonical counting logic for projects routed to a node.
*
* **Runtime Behavior:**
* - Projects with `nodeId` pointing to a remote node → run on that remote node
* - Projects with `nodeId` pointing to a local node → run on that local node
* - Projects without `nodeId` (unassigned) → run on local in-process runtime
*
* **Counting Rules:**
* - Local nodes: include both explicitly-assigned projects AND unassigned projects
* - Remote nodes: include only explicitly-assigned projects
*/
import type { NodeInfo, ProjectInfo } from "../api";
/**
* Check if a project is routed to a specific node based on runtime rules.
*
* @param project - The project to check
* @param node - The node to check against
* @returns true if the project runs on this node
*/
export function isProjectRoutedToNode(project: ProjectInfo, node: NodeInfo): boolean {
if (node.type === "remote") {
// Remote nodes: only explicit assignment counts
return project.nodeId === node.id;
}
// Local nodes: explicit assignment OR unassigned (null/undefined)
if (project.nodeId === node.id) {
return true;
}
// Unassigned projects run on local in-process runtime
if (project.nodeId === undefined || project.nodeId === null) {
return true;
}
return false;
}
/**
* Get all projects that are routed to a specific node.
*
* @param projects - All projects
* @param node - The node to filter by
* @returns Projects routed to this node
*/
export function getProjectsForNode(projects: ProjectInfo[], node: NodeInfo): ProjectInfo[] {
return projects.filter((project) => isProjectRoutedToNode(project, node));
}
/**
* Get the count of projects routed to a specific node.
*
* @param projects - All projects
* @param node - The node to count projects for
* @returns Number of projects on this node
*/
export function getProjectCountForNode(projects: ProjectInfo[], node: NodeInfo): number {
return getProjectsForNode(projects, node).length;
}
/**
* Get the count of unassigned projects (projects without nodeId).
* These projects run on the local in-process runtime.
*
* @param projects - All projects
* @returns Number of unassigned projects
*/
export function getUnassignedProjectCount(projects: ProjectInfo[]): number {
return projects.filter((project) => project.nodeId === undefined || project.nodeId === null).length;
}