"use server"; import { revalidatePath } from "next/cache"; import { eq } from "drizzle-orm"; import { db } from "@/lib/db"; import { blocksTable, IBlock } from "@/lib/db/schema"; import { requireAuth } from "./auth"; import { assertNoteOwner } from "./notes"; export async function assertBlockOwner(blockId: string): Promise { const user = await requireAuth(); const block = await db.query.blocksTable.findFirst({ where: eq(blocksTable.id, blockId), with: { note: true }, }); if (!block) { return false; } return block.note.authorId === user.id; } export async function createBlock(formData: FormData) { const noteId = formData.get("noteId") as string; const isAllowed = await assertNoteOwner(noteId); if (!isAllowed) return; const blocks = await getBlocks(noteId); const lastBlock = blocks.pop(); const order = lastBlock === undefined ? 1 : lastBlock.order + 1; await db .insert(blocksTable) .values({ noteId, order }); revalidatePath("/notes/[id]", "page"); } async function getBlock(blockId: string): Promise { const isAllowed = await assertBlockOwner(blockId); if (!isAllowed) return null; const blocks = await db .select() .from(blocksTable) .where(eq(blocksTable.id, blockId)); if (blocks.length === 0) { return null; } else { return blocks[0]; } } export async function getBlocks(noteId: string): Promise { const isAllowed = await assertNoteOwner(noteId); if (!isAllowed) return []; return db .select() .from(blocksTable) .where(eq(blocksTable.noteId, noteId)) .orderBy(blocksTable.order); } export async function deleteBlock(formData: FormData) { const blockId = formData.get("blockId") as string; const isAllowed = await assertBlockOwner(blockId); if (!isAllowed) return; await db .delete(blocksTable) .where(eq(blocksTable.id, blockId)); revalidatePath("/notes/[id]", "page"); } export async function changeLock(formData: FormData) { const blockId = formData.get("blockId") as string; const isLocked = formData.get("isLocked") === null ? false : true; const isAllowed = await assertBlockOwner(blockId); if (!isAllowed) return; await db .update(blocksTable) .set({ isLocked }) .where(eq(blocksTable.id, blockId)); revalidatePath("/notes/[id]", "page"); } export async function addLine(formData: FormData) { const blockId = formData.get("blockId") as string; const isAllowed = await assertBlockOwner(blockId); if (!isAllowed) return; const blocks = await db .select() .from(blocksTable) .where(eq(blocksTable.id, blockId)); if (blocks.length === 0) { return; } const block = blocks[0]; await db .update(blocksTable) .set({ lines: [...block.lines, ""] }) .where(eq(blocksTable.id, blockId)); revalidatePath("/notes/[id]", "page"); } export async function deleteLine(formData: FormData) { const blockId = formData.get("blockId") as string; const block = await getBlock(blockId); const isAllowed = await assertBlockOwner(blockId); if (!isAllowed) return; if (!block) { return; } await db .update(blocksTable) .set({ lines: block.lines.slice(0, -1) }) .where(eq(blocksTable.id, blockId)); revalidatePath("/notes/[id]", "page"); } export async function moveUp(formData: FormData) { const blockId = formData.get("blockId") as string; const isAllowed = await assertBlockOwner(blockId); if (!isAllowed) return; const block = await getBlock(blockId); if (!block) return; const siblings = await getBlocks(block.noteId); const currentIndex = siblings.findIndex((b) => b.id === block.id); if (currentIndex <= 0) return; const prevBlock = siblings[currentIndex - 1]; if (!prevBlock) return; await db.transaction(async (tx) => { await tx .update(blocksTable) .set({ order: prevBlock.order }) .where(eq(blocksTable.id, block.id)); await tx .update(blocksTable) .set({ order: block.order }) .where(eq(blocksTable.id, prevBlock.id)); }); revalidatePath("/notes/[id]", "page"); } export async function moveDown(formData: FormData) { const blockId = formData.get("blockId") as string; const isAllowed = await assertBlockOwner(blockId); if (!isAllowed) return; const block = await getBlock(blockId); if (!block) return; const siblings = await getBlocks(block.noteId); const currentIndex = siblings.findIndex((b) => b.id === block.id); if (currentIndex === -1 || currentIndex >= siblings.length - 1) return; const nextBlock = siblings[currentIndex + 1]; if (!nextBlock) return; await db.transaction(async (tx) => { await tx .update(blocksTable) .set({ order: nextBlock.order }) .where(eq(blocksTable.id, block.id)); await tx .update(blocksTable) .set({ order: block.order }) .where(eq(blocksTable.id, nextBlock.id)); }); revalidatePath("/notes/[id]", "page"); } export async function setLines(blockId: string, lines: string[]) { const isAllowed = await assertBlockOwner(blockId); if (!isAllowed) return; await db .update(blocksTable) .set({ lines }) .where(eq(blocksTable.id, blockId)); } export async function setTag(blockId: string, tag: string) { const isAllowed = await assertBlockOwner(blockId); if (!isAllowed) return; await db .update(blocksTable) .set({ tag }) .where(eq(blocksTable.id, blockId)); }