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, }; }