import type { SQL } from "drizzle-orm"; import { and, desc, eq, lt, sql } from "drizzle-orm"; import type { Database } from "@/client"; import { bookmarkArticles, bookmarks } from "@/schema"; import { type PageRequest, type PaginationMeta, buildPaginationResult, createPageState, decodeCursor, } from "@/utils/pagination"; export interface BookmarkRow { bookmark_id: string; bookmark_name: string; bookmark_description: string | null; bookmark_created_at: string; bookmark_updated_at: string | null; bookmark_articles_count: number; bookmark_is_public: boolean; } export interface BookmarkListResult { data: BookmarkRow[]; pagination: PaginationMeta; } export async function getBookmarkList( db: Database, params: { userId: string; page?: PageRequest }, ): Promise { const page = createPageState(params.page); const whereConditions: SQL[] = [eq(bookmarks.userId, params.userId)]; const cursor = decodeCursor(page.cursor); if (cursor?.id) { whereConditions.push(lt(bookmarks.id, cursor.id)); } let query = db .select({ bookmark_articles_count: sql`count(${bookmarkArticles.articleId})`, bookmark_created_at: bookmarks.createdAt, bookmark_description: bookmarks.description, bookmark_id: bookmarks.id, bookmark_is_public: bookmarks.isPublic, bookmark_name: bookmarks.name, bookmark_updated_at: bookmarks.updatedAt, }) .from(bookmarks) .leftJoin(bookmarkArticles, eq(bookmarkArticles.bookmarkId, bookmarks.id)) .groupBy(bookmarks.id); if (whereConditions.length === 1) { query = query.where(whereConditions[0]); } else if (whereConditions.length > 1) { query = query.where(and(...whereConditions)); } const rows = await query .orderBy(desc(bookmarks.createdAt), desc(bookmarks.id)) .limit(page.limit + 1); return buildPaginationResult(rows, page, { id: "bookmark_id" }); }