116 lines
4.0 KiB
TypeScript
116 lines
4.0 KiB
TypeScript
import { randomUUID } from "crypto";
|
|
import { NextResponse } from "next/server";
|
|
import { createSupabaseRouteClient } from "@/lib/supabase/server";
|
|
import { isConvexEnabled } from "@/lib/convex/enabled";
|
|
import { requireAuthContext } from "@/lib/auth/authContext";
|
|
import { getConvexHttpClient } from "@/lib/convex/server";
|
|
import { api } from "@/lib/convex/api";
|
|
import { getBlocksFromDocumentContent, findBlockInTree, withBlocksWrittenBack } from "@/lib/blocks";
|
|
|
|
type EmbedBlockPayload = {
|
|
sourceDocumentId: string;
|
|
blockId: string;
|
|
targetDocumentId: string;
|
|
position?: "end";
|
|
};
|
|
|
|
export async function POST(request: Request) {
|
|
const { sourceDocumentId, blockId, targetDocumentId }: EmbedBlockPayload = await request.json();
|
|
|
|
if (!sourceDocumentId || !blockId || !targetDocumentId) {
|
|
return NextResponse.json({ error: "缺少参数" }, { status: 400 });
|
|
}
|
|
|
|
if (sourceDocumentId === targetDocumentId) {
|
|
return NextResponse.json({ error: "禁止嵌入到当前页面" }, { status: 400 });
|
|
}
|
|
|
|
if (isConvexEnabled()) {
|
|
const auth = await requireAuthContext();
|
|
const client = getConvexHttpClient();
|
|
|
|
const source = await client.query(api.documents.getContent, { userId: auth.userId, id: sourceDocumentId });
|
|
if (!source) return NextResponse.json({ error: "源页面不存在或无权限" }, { status: 404 });
|
|
const sourceBlocks = getBlocksFromDocumentContent(source.content);
|
|
const hit = findBlockInTree(sourceBlocks, blockId);
|
|
if (!hit) return NextResponse.json({ error: "源块不存在或无权限" }, { status: 404 });
|
|
|
|
const target = await client.query(api.documents.getContent, { userId: auth.userId, id: targetDocumentId });
|
|
if (!target) return NextResponse.json({ error: "目标页面不存在或无权限" }, { status: 404 });
|
|
|
|
const targetBlocks = getBlocksFromDocumentContent(target.content);
|
|
const referenceBlock = {
|
|
id: randomUUID(),
|
|
type: "blockReference",
|
|
props: {
|
|
sourceDocumentId,
|
|
targetBlockId: blockId,
|
|
display: "embed",
|
|
},
|
|
content: [],
|
|
children: [],
|
|
};
|
|
|
|
const nextBlocks = [...targetBlocks, referenceBlock];
|
|
const payload = withBlocksWrittenBack(target.content, nextBlocks);
|
|
await client.mutation(api.documents.updateContent, { userId: auth.userId, id: targetDocumentId, content: payload });
|
|
|
|
return NextResponse.json({ ok: true });
|
|
}
|
|
|
|
const supabase = await createSupabaseRouteClient();
|
|
const {
|
|
data: { session },
|
|
} = await supabase.auth.getSession();
|
|
|
|
if (!session) {
|
|
return NextResponse.json({ error: "未登录" }, { status: 401 });
|
|
}
|
|
|
|
const { data: sourceDoc } = await supabase
|
|
.from("documents")
|
|
.select("id,content,user_id")
|
|
.eq("id", sourceDocumentId)
|
|
.eq("user_id", session.user.id)
|
|
.single();
|
|
if (!sourceDoc) return NextResponse.json({ error: "源页面不存在或无权限" }, { status: 404 });
|
|
|
|
const sourceBlocks = getBlocksFromDocumentContent(sourceDoc.content);
|
|
if (!findBlockInTree(sourceBlocks, blockId)) {
|
|
return NextResponse.json({ error: "源块不存在或无权限" }, { status: 404 });
|
|
}
|
|
|
|
const { data: targetDoc } = await supabase
|
|
.from("documents")
|
|
.select("id,content,user_id")
|
|
.eq("id", targetDocumentId)
|
|
.eq("user_id", session.user.id)
|
|
.single();
|
|
if (!targetDoc) return NextResponse.json({ error: "目标页面不存在或无权限" }, { status: 404 });
|
|
|
|
const targetBlocks = getBlocksFromDocumentContent(targetDoc.content);
|
|
const referenceBlock = {
|
|
id: randomUUID(),
|
|
type: "blockReference",
|
|
props: {
|
|
sourceDocumentId,
|
|
targetBlockId: blockId,
|
|
display: "embed",
|
|
},
|
|
content: [],
|
|
children: [],
|
|
};
|
|
|
|
const nextBlocks = [...targetBlocks, referenceBlock];
|
|
const payload = withBlocksWrittenBack(targetDoc.content, nextBlocks);
|
|
|
|
const { error } = await supabase
|
|
.from("documents")
|
|
.update({ content: payload })
|
|
.eq("id", targetDocumentId)
|
|
.eq("user_id", session.user.id);
|
|
|
|
if (error) return NextResponse.json({ error: error.message }, { status: 500 });
|
|
return NextResponse.json({ ok: true });
|
|
}
|