import { api } from "@/lib/convex/api"; import { getAuthedConvexClient } from "@/lib/convex/route"; import { buildDocumentBridgeMutationRequest, executeDocumentBridgeMutationRequest, type CommandEnvelope, type BridgeContext, } from "@/lib/documents/bridge"; import { recordBridgeCommandArtifacts } from "@/lib/documents/bridge-log"; import type { DocumentSavePayload } from "@/lib/documents/save-contract"; import { DocumentBridgeError } from "@/lib/documents/bridge"; export type DocumentSaveExecutionResult = { requestId: string; traceId: string; commandId: string; commandName: string; revision: number | null; conflictDetectionKey: string | null; }; export async function executeSaveBridgeCommand(input: { context: BridgeContext; envelope: CommandEnvelope; }): Promise { const { client } = await getAuthedConvexClient(); const mutationRequest = buildDocumentBridgeMutationRequest({ context: input.context, envelope: input.envelope, mapConvexArgs: (payload) => ({ id: payload.documentId, content: payload.content, expectedRevision: payload.revision, conflictDetectionKey: payload.conflictDetectionKey, }), }); let mutationResult; try { mutationResult = await executeDocumentBridgeMutationRequest({ client, mutation: api.documents.updateContent, request: mutationRequest, }); } catch (error) { if (error instanceof Error && /正文(内容已变更|冲突检测失败)/.test(error.message)) { throw new DocumentBridgeError(error.message, 409, "REJECTED", { reason: "content_conflict", revision: input.envelope.payload.revision, conflictDetectionKey: input.envelope.payload.conflictDetectionKey, }); } throw error; } await recordBridgeCommandArtifacts({ context: input.context, envelope: input.envelope, }); return { requestId: input.context.requestId, traceId: input.context.traceId, commandId: input.envelope.commandId, commandName: input.envelope.name, revision: typeof mutationResult?.revision === "number" && Number.isInteger(mutationResult.revision) ? mutationResult.revision : null, conflictDetectionKey: typeof mutationResult?.conflict_detection_key === "string" && mutationResult.conflict_detection_key.trim() ? mutationResult.conflict_detection_key : null, }; }