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>
This commit is contained in:
75
packages/dashboard/app/utils/nodeProjectAssignment.ts
Normal file
75
packages/dashboard/app/utils/nodeProjectAssignment.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
Reference in New Issue
Block a user