import { ORPCError } from '@orpc/server' import { and, eq } from 'drizzle-orm' import * as schema from '@/modules/bookmarks/schema' import { authMiddleware, dbMiddleware } from '@/server/api/middlewares' import { os } from '@/server/api/server' export const category = { list: os.bookmarks.category.list .use(dbMiddleware) .use(authMiddleware) .handler(async ({ context }) => { return await context.db.query.category.findMany({ where: (category, { eq }) => eq(category.userId, context.user.id), orderBy: (category, { asc }) => asc(category.orderId), with: { bookmarks: { orderBy: (bookmark, { asc }) => asc(bookmark.orderId), }, }, }) }), create: os.bookmarks.category.create .use(dbMiddleware) .use(authMiddleware) .handler(async ({ context, input }) => { const [created] = await context.db .insert(schema.category) .values({ ...input, userId: context.user.id }) .returning() if (!created) throw new ORPCError('INTERNAL_SERVER_ERROR', { message: 'Failed to create category' }) return created }), update: os.bookmarks.category.update .use(dbMiddleware) .use(authMiddleware) .handler(async ({ context, input }) => { const [updated] = await context.db .update(schema.category) .set(input.data) .where(and(eq(schema.category.id, input.id), eq(schema.category.userId, context.user.id))) .returning() if (!updated) throw new ORPCError('NOT_FOUND') return updated }), remove: os.bookmarks.category.remove .use(dbMiddleware) .use(authMiddleware) .handler(async ({ context, input }) => { const [deleted] = await context.db .delete(schema.category) .where(and(eq(schema.category.id, input.id), eq(schema.category.userId, context.user.id))) .returning({ id: schema.category.id }) if (!deleted) throw new ORPCError('NOT_FOUND') }), reorder: os.bookmarks.category.reorder .use(dbMiddleware) .use(authMiddleware) .handler(async ({ context, input }) => { await context.db.transaction(async (tx) => { for (const item of input) { await tx .update(schema.category) .set({ orderId: item.orderId }) .where(and(eq(schema.category.id, item.id), eq(schema.category.userId, context.user.id))) } }) }), } export const bookmark = { create: os.bookmarks.bookmark.create .use(dbMiddleware) .use(authMiddleware) .handler(async ({ context, input }) => { const [created] = await context.db .insert(schema.bookmark) .values({ ...input, userId: context.user.id }) .returning() if (!created) throw new ORPCError('INTERNAL_SERVER_ERROR', { message: 'Failed to create bookmark' }) return created }), update: os.bookmarks.bookmark.update .use(dbMiddleware) .use(authMiddleware) .handler(async ({ context, input }) => { const [updated] = await context.db .update(schema.bookmark) .set(input.data) .where(and(eq(schema.bookmark.id, input.id), eq(schema.bookmark.userId, context.user.id))) .returning() if (!updated) throw new ORPCError('NOT_FOUND') return updated }), remove: os.bookmarks.bookmark.remove .use(dbMiddleware) .use(authMiddleware) .handler(async ({ context, input }) => { const [deleted] = await context.db .delete(schema.bookmark) .where(and(eq(schema.bookmark.id, input.id), eq(schema.bookmark.userId, context.user.id))) .returning({ id: schema.bookmark.id }) if (!deleted) throw new ORPCError('NOT_FOUND') }), reorder: os.bookmarks.bookmark.reorder .use(dbMiddleware) .use(authMiddleware) .handler(async ({ context, input }) => { await context.db.transaction(async (tx) => { for (const item of input) { await tx .update(schema.bookmark) .set({ orderId: item.orderId }) .where(and(eq(schema.bookmark.id, item.id), eq(schema.bookmark.userId, context.user.id))) } }) }), }