feat: 收口文档桥接与 OnlyOffice/Sidebar 回归

- 为 documents.save/meta/content、blocks.patch 与 sidebar.dataset.list 补齐 Rust 协议映射、共享契约与桥接执行器

- 对齐 BlockNote、Mindmap、OnlyOffice 的保存/路由元信息,并补真实浏览器回归脚本与 OnlyOffice 部署基线

- 忽略 Rust 本地构建产物与 Harness 调试状态文件,避免临时产物进入仓库历史
This commit is contained in:
lix-2026
2026-04-15 03:06:29 +08:00
parent 84a8454fa9
commit b33ffb99e7
51 changed files with 3260 additions and 379 deletions
+25 -46
View File
@@ -1,14 +1,17 @@
import { randomUUID } from "crypto";
import type { ConvexHttpClient } from "convex/browser";
import type { FunctionReference } from "convex/server";
import type { SidebarInitialData } from "@/components/sidebar/types";
import type { DocumentRecord } from "@/lib/documents";
import { api } from "@/lib/convex/api";
import { buildSidebarInitialData } from "@/lib/sidebar-data";
import {
mapSidebarDatasetListQueryResultToInitialData,
type SidebarDatasetListQueryResult,
} from "@/lib/sidebar-data";
import type { WorkspaceSummary } from "@/lib/workspaces";
type LoadSidebarDataFromConvexInput = {
client: ConvexHttpClient;
userId: string;
fallbackName: string;
requestedWorkspaceId?: string | null;
};
@@ -17,10 +20,20 @@ type LoadSidebarDataFromConvexResult = {
workspaces: WorkspaceSummary[];
activeWorkspaceId: string;
targetWorkspaceId: string | null;
sidebarDataset: SidebarDatasetListQueryResult | null;
sidebarInitialData: SidebarInitialData | null;
documents: DocumentRecord[];
};
const sidebarDatasetListQuery = ((api as unknown as Record<string, unknown>).sidebar as
| Record<string, unknown>
| undefined)?.datasetList as FunctionReference<
"query",
"public",
{ workspaceId: string },
SidebarDatasetListQueryResult
>;
export async function loadSidebarDataFromConvex(
input: LoadSidebarDataFromConvexInput,
): Promise<LoadSidebarDataFromConvexResult> {
@@ -29,9 +42,8 @@ export async function loadSidebarDataFromConvex(
workspaceIdIfCreate: randomUUID(),
});
const summaries = await input.client.query(api.workspaces.fetchWorkspaceSummaries, {});
const workspaces = summaries.workspaces.length > 0 ? summaries.workspaces : bootstrap.workspaces;
const activeWorkspaceId = summaries.activeWorkspaceId || bootstrap.activeWorkspaceId;
const workspaces = bootstrap.workspaces;
const activeWorkspaceId = bootstrap.activeWorkspaceId;
const targetWorkspaceId = input.requestedWorkspaceId?.trim() || activeWorkspaceId || null;
if (!targetWorkspaceId) {
@@ -39,56 +51,23 @@ export async function loadSidebarDataFromConvex(
workspaces,
activeWorkspaceId,
targetWorkspaceId: null,
sidebarDataset: null,
sidebarInitialData: null,
documents: [],
};
}
const [documents, trashedDocuments, mindmaps, mediaAssets, trashedMediaAssets, tables] = await Promise.all([
input.client.query(api.documents.listByWorkspace, {
workspaceId: targetWorkspaceId,
}),
input.client.query(api.documents.listTrashedByWorkspace, {
workspaceId: targetWorkspaceId,
}),
input.client.query(api.mindmaps.listByWorkspace, {
workspaceId: targetWorkspaceId,
includeDeleted: true,
}),
input.client.query(api.mediaAssets.listByWorkspace, {
userId: input.userId,
workspaceId: targetWorkspaceId,
limit: 200,
}),
input.client.query(api.mediaAssets.listDeletedByWorkspace, {
userId: input.userId,
workspaceId: targetWorkspaceId,
limit: 2000,
}),
input.client.query(api.tables.listByWorkspaceForSearch, {
userId: input.userId,
workspaceId: targetWorkspaceId,
includeArchived: true,
limit: 3000,
}),
]);
const normalizedDocuments = documents as DocumentRecord[];
const sidebarDataset = (await input.client.query(sidebarDatasetListQuery, {
workspaceId: targetWorkspaceId,
})) as SidebarDatasetListQueryResult;
const normalizedDocuments = (sidebarDataset.documents ?? []) as DocumentRecord[];
return {
workspaces,
workspaces: sidebarDataset.workspaces ?? workspaces,
activeWorkspaceId,
targetWorkspaceId,
sidebarInitialData: buildSidebarInitialData({
activeWorkspaceId: targetWorkspaceId,
workspaces,
documents: normalizedDocuments,
trashedDocuments,
mindmaps: mindmaps ?? [],
mediaAssets: mediaAssets ?? [],
trashedMediaAssets: trashedMediaAssets ?? [],
tables: tables ?? [],
}),
sidebarDataset,
sidebarInitialData: mapSidebarDatasetListQueryResultToInitialData(sidebarDataset),
documents: normalizedDocuments,
};
}