From af6774fab6502b3f49a71dea955357992e5edc77 Mon Sep 17 00:00:00 2001 From: MohamedBassem Date: Sun, 6 Apr 2025 23:50:39 +0100 Subject: feat: Add a search matcher for rss feed bookmarks --- packages/trpc/lib/__tests__/search.test.ts | 48 ++++++++++++++++++++++++++++++ packages/trpc/lib/search.ts | 29 ++++++++++++++++++ 2 files changed, 77 insertions(+) (limited to 'packages/trpc') diff --git a/packages/trpc/lib/__tests__/search.test.ts b/packages/trpc/lib/__tests__/search.test.ts index 7f573b4f..9f8aac88 100644 --- a/packages/trpc/lib/__tests__/search.test.ts +++ b/packages/trpc/lib/__tests__/search.test.ts @@ -9,6 +9,8 @@ import { bookmarksInLists, bookmarkTags, bookmarkTexts, + rssFeedImportsTable, + rssFeedsTable, tagsOnBookmarks, users, } from "@hoarder/db/schema"; @@ -151,6 +153,32 @@ beforeEach(async () => { { bookmarkId: "b6", listId: "l1" }, ]); + await db.insert(rssFeedsTable).values([ + { id: "f1", userId: testUserId, name: "feed1", url: "url1" }, + { id: "f2", userId: testUserId, name: "feed2", url: "url2" }, + ]); + + await db.insert(rssFeedImportsTable).values([ + { + id: "imp1", + entryId: "entry1", + rssFeedId: "f1", + bookmarkId: "b1", + }, + { + id: "imp2", + entryId: "entry2", + rssFeedId: "f2", + bookmarkId: "b3", + }, + { + id: "imp3", + entryId: "entry3", + rssFeedId: "f1", + bookmarkId: "b5", + }, + ]); + mockCtx = { db, user: { @@ -423,6 +451,26 @@ describe("getBookmarkIdsFromMatcher", () => { expect(result).toEqual(["b3"]); }); + it("should handle rssFeedName matcher", async () => { + const matcher: Matcher = { + type: "rssFeedName", + feedName: "feed1", + inverse: false, + }; + const result = await getBookmarkIdsFromMatcher(mockCtx, matcher); + expect(result.sort()).toEqual(["b1", "b5"]); + }); + + it("should handle rssFeedName matcher with inverse=true", async () => { + const matcher: Matcher = { + type: "rssFeedName", + feedName: "feed1", + inverse: true, + }; + const result = await getBookmarkIdsFromMatcher(mockCtx, matcher); + expect(result.sort()).toEqual(["b2", "b3", "b4", "b6"]); + }); + it("should throw error for unknown matcher type", async () => { const matcher = { type: "unknown" } as unknown as Matcher; await expect(getBookmarkIdsFromMatcher(mockCtx, matcher)).rejects.toThrow( diff --git a/packages/trpc/lib/search.ts b/packages/trpc/lib/search.ts index de76748b..83dfa674 100644 --- a/packages/trpc/lib/search.ts +++ b/packages/trpc/lib/search.ts @@ -20,6 +20,8 @@ import { bookmarks, bookmarksInLists, bookmarkTags, + rssFeedImportsTable, + rssFeedsTable, tagsOnBookmarks, } from "@hoarder/db/schema"; import { Matcher } from "@hoarder/shared/types/search"; @@ -177,6 +179,33 @@ async function getIds( ), ); } + case "rssFeedName": { + const comp = matcher.inverse ? notExists : exists; + return db + .selectDistinct({ id: bookmarks.id }) + .from(bookmarks) + .where( + and( + eq(bookmarks.userId, userId), + comp( + db + .select() + .from(rssFeedImportsTable) + .innerJoin( + rssFeedsTable, + eq(rssFeedImportsTable.rssFeedId, rssFeedsTable.id), + ) + .where( + and( + eq(rssFeedImportsTable.bookmarkId, bookmarks.id), + eq(rssFeedsTable.userId, userId), + eq(rssFeedsTable.name, matcher.feedName), + ), + ), + ), + ), + ); + } case "archived": { return db .select({ id: bookmarks.id }) -- cgit v1.2.3-70-g09d2