Files
pikasTech-HWLAB/web/hwlab-cloud-web/src/api/projectManagement.ts
T
2026-06-25 22:12:13 +08:00

170 lines
6.8 KiB
TypeScript

// SPEC: PJ2026-010404 项目管理 draft-2026-06-25-p0-project-management-mdtodo.
// Responsibility: Cloud Web client for the public project-management same-origin API.
import { fetchJson } from "./client";
import type { ApiResult } from "@/types";
export interface ProjectManagementEnvelope {
contractVersion?: string;
serviceId?: string;
ok?: boolean;
valuesRedacted?: boolean;
}
export interface ProjectNavigationItem {
id: string;
label: string;
apiRoute?: string;
}
export interface ProjectNavigationCapabilities {
mdtodoProjection?: boolean;
workbenchLaunch?: boolean;
workbenchLinks?: boolean;
sourceOfTruth?: string;
[key: string]: unknown;
}
export interface ProjectNavigation {
id: string;
label: string;
actor?: { id?: string | null; role?: string | null; authMethod?: string | null } | null;
items?: ProjectNavigationItem[];
capabilities?: ProjectNavigationCapabilities;
}
export interface ProjectProjectionSummary {
sourceId?: string;
documentCount?: number;
taskCount?: number;
projectedAt?: string;
startedAt?: string;
}
export interface ProjectNavigationResponse extends ProjectManagementEnvelope {
navigation?: ProjectNavigation;
projection?: ProjectProjectionSummary | null;
}
export interface ProjectRecord {
projectId: string;
name?: string;
title?: string;
sourceIds?: string[];
sourceOfTruth?: string;
status?: string;
}
export interface ProjectSource {
sourceId: string;
kind?: string;
sourceKind?: string;
displayName?: string;
projectId?: string;
status?: string;
hwpodId?: string | null;
nodeId?: string | null;
workspaceRootRef?: string | null;
mdtodoRootRef?: string | null;
maxFiles?: number;
updatedAt?: string;
valuesRedacted?: boolean;
}
export interface ProjectSourceInput {
sourceId?: string;
sourceKind?: string;
displayName?: string;
projectId?: string;
hwpodId?: string;
nodeId?: string;
workspaceRootRef?: string;
mdtodoRootRef?: string;
maxFiles?: number;
}
export interface MdtodoFileRecord {
sourceId: string;
fileRef: string;
projectId?: string;
relativePath?: string;
title?: string;
fingerprint?: string;
taskCount?: number;
parseError?: string | null;
revision?: number;
lastIndexedAt?: string;
updatedAt?: string;
}
export interface MdtodoTaskRecord {
taskRef: string;
projectId?: string;
sourceId?: string;
fileRef?: string;
taskId?: string;
title?: string;
status?: string;
parentTaskRef?: string | null;
depth?: number;
lineNumber?: number;
ordinal?: number;
linkCount?: number;
updatedAt?: string;
}
export interface ProjectWorkbenchLinkRecord {
linkId: string;
projectId?: string;
taskRef?: string | null;
sessionId?: string | null;
traceId?: string | null;
createdBy?: string | null;
role?: string;
createdAt?: string;
updatedAt?: string;
}
export interface ProjectListResponse extends ProjectManagementEnvelope { projects?: ProjectRecord[] }
export interface ProjectSourceListResponse extends ProjectManagementEnvelope { sources?: ProjectSource[] }
export interface ProjectSourceMutationResponse extends ProjectManagementEnvelope { source?: ProjectSource }
export interface ProjectSourceProbeResponse extends ProjectManagementEnvelope { probe?: { ok?: boolean; status?: string; sourceId?: string; sourceKind?: string; entries?: number; valuesRedacted?: boolean } }
export interface ProjectSourceReindexResponse extends ProjectManagementEnvelope { projection?: ProjectProjectionSummary & { sourceKind?: string; rootRef?: string; valuesRedacted?: boolean } }
export interface MdtodoFileListResponse extends ProjectManagementEnvelope { files?: MdtodoFileRecord[] }
export interface MdtodoTaskListResponse extends ProjectManagementEnvelope { tasks?: MdtodoTaskRecord[] }
export interface ProjectWorkbenchLinkListResponse extends ProjectManagementEnvelope { links?: ProjectWorkbenchLinkRecord[] }
export interface MdtodoTaskQuery {
sourceId?: string | null;
fileRef?: string | null;
projectId?: string | null;
}
export interface ProjectWorkbenchLinkQuery {
taskRef?: string | null;
projectId?: string | null;
sessionId?: string | null;
}
export const projectManagementAPI = {
navigation: (): Promise<ApiResult<ProjectNavigationResponse>> => fetchJson("/v1/project-management/navigation", { timeoutMs: 12000, timeoutName: "project navigation" }),
projects: (): Promise<ApiResult<ProjectListResponse>> => fetchJson("/v1/project-management/projects", { timeoutMs: 12000, timeoutName: "project list" }),
sources: (): Promise<ApiResult<ProjectSourceListResponse>> => fetchJson("/v1/project-management/mdtodo/sources", { timeoutMs: 12000, timeoutName: "project mdtodo sources" }),
createSource: (input: ProjectSourceInput): Promise<ApiResult<ProjectSourceMutationResponse>> => fetchJson("/v1/project-management/mdtodo/sources", { method: "POST", body: JSON.stringify(input), timeoutMs: 12000, timeoutName: "project mdtodo source create" }),
updateSource: (sourceId: string, input: ProjectSourceInput): Promise<ApiResult<ProjectSourceMutationResponse>> => fetchJson(`/v1/project-management/mdtodo/sources/${encodeURIComponent(sourceId)}`, { method: "PATCH", body: JSON.stringify(input), timeoutMs: 12000, timeoutName: "project mdtodo source update" }),
probeSource: (sourceId: string): Promise<ApiResult<ProjectSourceProbeResponse>> => fetchJson(`/v1/project-management/mdtodo/sources/${encodeURIComponent(sourceId)}/probe`, { method: "POST", body: JSON.stringify({}), timeoutMs: 12000, timeoutName: "project mdtodo source probe" }),
reindexSource: (sourceId: string): Promise<ApiResult<ProjectSourceReindexResponse>> => fetchJson(`/v1/project-management/mdtodo/sources/${encodeURIComponent(sourceId)}/reindex`, { method: "POST", body: JSON.stringify({}), timeoutMs: 12000, timeoutName: "project mdtodo source reindex" }),
files: (sourceId?: string | null): Promise<ApiResult<MdtodoFileListResponse>> => fetchJson(`/v1/project-management/mdtodo/files${queryString({ sourceId })}`, { timeoutMs: 12000, timeoutName: "project mdtodo files" }),
tasks: (query: MdtodoTaskQuery = {}): Promise<ApiResult<MdtodoTaskListResponse>> => fetchJson(`/v1/project-management/mdtodo/tasks${queryString({ sourceId: query.sourceId, fileRef: query.fileRef, projectId: query.projectId })}`, { timeoutMs: 12000, timeoutName: "project mdtodo tasks" }),
workbenchLinks: (query: ProjectWorkbenchLinkQuery = {}): Promise<ApiResult<ProjectWorkbenchLinkListResponse>> => fetchJson(`/v1/project-management/workbench-links${queryString({ taskRef: query.taskRef, projectId: query.projectId, sessionId: query.sessionId })}`, { timeoutMs: 12000, timeoutName: "project workbench links" })
};
function queryString(values: Record<string, string | null | undefined>): string {
const params = new URLSearchParams();
for (const [key, value] of Object.entries(values)) {
if (value) params.set(key, value);
}
const text = params.toString();
return text ? `?${text}` : "";
}