170 lines
6.8 KiB
TypeScript
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}` : "";
|
|
}
|