aboutsummaryrefslogtreecommitdiffstats
path: root/packages/trpc/routers/highlights.ts
diff options
context:
space:
mode:
authorMohamed Bassem <me@mbassem.com>2024-12-27 19:21:43 +0000
committerMohamed Bassem <me@mbassem.com>2024-12-27 19:34:04 +0000
commit3f56389f55ef116f8cea17c15c684798fb942290 (patch)
tree1a398accbcfc75674c5cc4970bc85fd27c637911 /packages/trpc/routers/highlights.ts
parent86d74e3f32dd5bccc8df195b55391e206df9a1c4 (diff)
downloadkarakeep-3f56389f55ef116f8cea17c15c684798fb942290.tar.zst
feat: Add REST APIs for manipulating highlights. Fixes #620
Diffstat (limited to 'packages/trpc/routers/highlights.ts')
-rw-r--r--packages/trpc/routers/highlights.ts62
1 files changed, 61 insertions, 1 deletions
diff --git a/packages/trpc/routers/highlights.ts b/packages/trpc/routers/highlights.ts
index 14d0ffa9..e4446679 100644
--- a/packages/trpc/routers/highlights.ts
+++ b/packages/trpc/routers/highlights.ts
@@ -1,13 +1,15 @@
import { experimental_trpcMiddleware, TRPCError } from "@trpc/server";
-import { and, eq } from "drizzle-orm";
+import { and, eq, lt, lte, or } from "drizzle-orm";
import { z } from "zod";
import { highlights } from "@hoarder/db/schema";
import {
+ DEFAULT_NUM_HIGHLIGHTS_PER_PAGE,
zHighlightSchema,
zNewHighlightSchema,
zUpdateHighlightSchema,
} from "@hoarder/shared/types/highlights";
+import { zCursorV2 } from "@hoarder/shared/types/pagination";
import { authedProcedure, Context, router } from "../index";
import { ensureBookmarkOwnership } from "./bookmarks";
@@ -77,6 +79,64 @@ export const highlightsAppRouter = router({
});
return { highlights: results };
}),
+ get: authedProcedure
+ .input(z.object({ highlightId: z.string() }))
+ .output(zHighlightSchema)
+ .use(ensureHighlightOwnership)
+ .query(async ({ input, ctx }) => {
+ const result = await ctx.db.query.highlights.findFirst({
+ where: and(
+ eq(highlights.id, input.highlightId),
+ eq(highlights.userId, ctx.user.id),
+ ),
+ });
+ if (!result) {
+ throw new TRPCError({ code: "NOT_FOUND" });
+ }
+ return result;
+ }),
+ getAll: authedProcedure
+ .input(
+ z.object({
+ cursor: zCursorV2.nullish(),
+ limit: z.number().optional().default(DEFAULT_NUM_HIGHLIGHTS_PER_PAGE),
+ }),
+ )
+ .output(
+ z.object({
+ highlights: z.array(zHighlightSchema),
+ nextCursor: zCursorV2.nullable(),
+ }),
+ )
+ .query(async ({ input, ctx }) => {
+ const results = await ctx.db.query.highlights.findMany({
+ where: and(
+ eq(highlights.userId, ctx.user.id),
+ input.cursor
+ ? or(
+ lt(highlights.createdAt, input.cursor.createdAt),
+ and(
+ eq(highlights.createdAt, input.cursor.createdAt),
+ lte(highlights.id, input.cursor.id),
+ ),
+ )
+ : undefined,
+ ),
+ limit: input.limit + 1,
+ });
+ let nextCursor: z.infer<typeof zCursorV2> | null = null;
+ if (results.length > input.limit) {
+ const nextItem = results.pop()!;
+ nextCursor = {
+ id: nextItem.id,
+ createdAt: nextItem.createdAt,
+ };
+ }
+ return {
+ highlights: results,
+ nextCursor,
+ };
+ }),
delete: authedProcedure
.input(z.object({ highlightId: z.string() }))
.output(zHighlightSchema)