Files
mnote/wolai-frontend/src/lib/documents/save-contract.ts
T
2026-04-21 06:26:35 +08:00

109 lines
3.2 KiB
TypeScript

import type { Json } from "@/types/supabase";
import {
editorBlockDocumentFromContent,
editorBlockDocumentFromTiptapDoc,
legacyBlocksFromEditorBlockDocument,
normalizeEditorBlockDocument,
type EditorBlockDocument,
type TiptapDoc,
} from "@/lib/documents/tiptap-content-converter";
export type DocumentSavePayload = {
documentId: string;
workspaceId: string | null;
revision: number | null;
editorDocument: EditorBlockDocument;
content: Json;
tiptapDocument: TiptapDoc | null;
conflictDetectionKey: string | null;
snapshotCapturedAt: string | null;
blockCount: number | null;
};
type BuildDocumentSavePayloadInput = {
documentId: string;
workspaceId?: string | null;
revision?: number | null;
editorDocument?: unknown;
content?: Json;
tiptapDocument?: unknown;
conflictDetectionKey?: string | null;
snapshotCapturedAt?: string | null;
blockCount?: number | null;
};
function resolveEditorDocument(
input: BuildDocumentSavePayloadInput,
normalizedDocumentId: string,
): EditorBlockDocument {
if (input.editorDocument != null) {
return normalizeEditorBlockDocument(input.editorDocument, normalizedDocumentId);
}
if (typeof input.content !== "undefined") {
return normalizeEditorBlockDocument(
editorBlockDocumentFromContent(input.content),
normalizedDocumentId,
);
}
if (input.tiptapDocument != null) {
return normalizeEditorBlockDocument(
editorBlockDocumentFromTiptapDoc(input.tiptapDocument, normalizedDocumentId),
normalizedDocumentId,
);
}
return normalizeEditorBlockDocument(
{
documentId: normalizedDocumentId,
rootBlockIds: [],
blocks: [],
},
normalizedDocumentId,
);
}
export function buildDocumentSavePayload(
input: BuildDocumentSavePayloadInput,
): DocumentSavePayload {
const documentId = input.documentId.trim();
const editorDocument = resolveEditorDocument(input, documentId);
const shouldDeriveLegacyContent =
input.editorDocument != null ||
input.tiptapDocument != null ||
typeof input.content === "undefined";
const content: Json = shouldDeriveLegacyContent
? (legacyBlocksFromEditorBlockDocument(editorDocument) as Json)
: (input.content as Json);
const revision =
typeof input.revision === "number" && Number.isInteger(input.revision) && input.revision >= 0
? input.revision
: null;
const conflictDetectionKey =
typeof input.conflictDetectionKey === "string" && input.conflictDetectionKey.trim()
? input.conflictDetectionKey.trim()
: null;
const snapshotCapturedAt =
typeof input.snapshotCapturedAt === "string" && input.snapshotCapturedAt.trim()
? input.snapshotCapturedAt.trim()
: null;
const blockCount =
typeof input.blockCount === "number" && Number.isInteger(input.blockCount) && input.blockCount >= 0
? input.blockCount
: null;
const tiptapDocument =
input.tiptapDocument && typeof input.tiptapDocument === "object"
? (input.tiptapDocument as TiptapDoc)
: null;
return {
documentId,
workspaceId: input.workspaceId?.trim() || null,
revision,
editorDocument,
content,
tiptapDocument,
conflictDetectionKey,
snapshotCapturedAt,
blockCount,
};
}