aboutsummaryrefslogtreecommitdiffstats
path: root/packages/web/server
diff options
context:
space:
mode:
authorMohamedBassem <me@mbassem.com>2024-02-28 20:45:28 +0000
committerMohamedBassem <me@mbassem.com>2024-02-28 20:45:28 +0000
commit3208dda3848ad739f54cebf44c423e2b68e85b2d (patch)
tree25602c451354a296e8779197fdd42acab7526502 /packages/web/server
parent7096fb3941579e5c045796361745d597e03ff7fc (diff)
downloadkarakeep-3208dda3848ad739f54cebf44c423e2b68e85b2d.tar.zst
feature: Add support for storing and previewing raw notes
Diffstat (limited to 'packages/web/server')
-rw-r--r--packages/web/server/api/routers/bookmarks.test.ts36
-rw-r--r--packages/web/server/api/routers/bookmarks.ts89
2 files changed, 95 insertions, 30 deletions
diff --git a/packages/web/server/api/routers/bookmarks.test.ts b/packages/web/server/api/routers/bookmarks.test.ts
index 16f82992..603a173e 100644
--- a/packages/web/server/api/routers/bookmarks.test.ts
+++ b/packages/web/server/api/routers/bookmarks.test.ts
@@ -1,17 +1,18 @@
import { CustomTestContext, defaultBeforeEach } from "@/lib/testUtils";
-import { expect, describe, test, beforeEach } from "vitest";
+import { expect, describe, test, beforeEach, assert } from "vitest";
beforeEach<CustomTestContext>(defaultBeforeEach);
describe("Bookmark Routes", () => {
test<CustomTestContext>("create bookmark", async ({ apiCallers }) => {
const api = apiCallers[0].bookmarks;
- const bookmark = await api.bookmarkLink({
+ const bookmark = await api.createBookmark({
url: "https://google.com",
type: "link",
});
const res = await api.getBookmark({ bookmarkId: bookmark.id });
+ assert(res.content.type == "link");
expect(res.content.url).toEqual("https://google.com");
expect(res.favourited).toEqual(false);
expect(res.archived).toEqual(false);
@@ -22,7 +23,7 @@ describe("Bookmark Routes", () => {
const api = apiCallers[0].bookmarks;
// Create the bookmark
- const bookmark = await api.bookmarkLink({
+ const bookmark = await api.createBookmark({
url: "https://google.com",
type: "link",
});
@@ -43,7 +44,7 @@ describe("Bookmark Routes", () => {
const api = apiCallers[0].bookmarks;
// Create the bookmark
- const bookmark = await api.bookmarkLink({
+ const bookmark = await api.createBookmark({
url: "https://google.com",
type: "link",
});
@@ -64,12 +65,12 @@ describe("Bookmark Routes", () => {
const emptyBookmarks = await api.getBookmarks({});
expect(emptyBookmarks.bookmarks.length).toEqual(0);
- const bookmark1 = await api.bookmarkLink({
+ const bookmark1 = await api.createBookmark({
url: "https://google.com",
type: "link",
});
- const bookmark2 = await api.bookmarkLink({
+ const bookmark2 = await api.createBookmark({
url: "https://google2.com",
type: "link",
});
@@ -113,7 +114,7 @@ describe("Bookmark Routes", () => {
test<CustomTestContext>("update tags", async ({ apiCallers }) => {
const api = apiCallers[0].bookmarks;
- let bookmark = await api.bookmarkLink({
+ let bookmark = await api.createBookmark({
url: "https://google.com",
type: "link",
});
@@ -139,12 +140,29 @@ describe("Bookmark Routes", () => {
expect(bookmark.tags.map((t) => t.name).sort()).toEqual(["tag2", "tag3"]);
});
+ test<CustomTestContext>("update bookmark text", async ({ apiCallers }) => {
+ const api = apiCallers[0].bookmarks;
+ let bookmark = await api.createBookmark({
+ text: "HELLO WORLD",
+ type: "text",
+ });
+
+ await api.updateBookmarkText({
+ bookmarkId: bookmark.id,
+ text: "WORLD HELLO",
+ });
+
+ bookmark = await api.getBookmark({ bookmarkId: bookmark.id });
+ assert(bookmark.content.type == "text");
+ expect(bookmark.content.text).toEqual("WORLD HELLO");
+ });
+
test<CustomTestContext>("privacy", async ({ apiCallers }) => {
- const user1Bookmark = await apiCallers[0].bookmarks.bookmarkLink({
+ const user1Bookmark = await apiCallers[0].bookmarks.createBookmark({
type: "link",
url: "https://google.com",
});
- const user2Bookmark = await apiCallers[1].bookmarks.bookmarkLink({
+ const user2Bookmark = await apiCallers[1].bookmarks.createBookmark({
type: "link",
url: "https://google.com",
});
diff --git a/packages/web/server/api/routers/bookmarks.ts b/packages/web/server/api/routers/bookmarks.ts
index 64755e4e..bfa0580f 100644
--- a/packages/web/server/api/routers/bookmarks.ts
+++ b/packages/web/server/api/routers/bookmarks.ts
@@ -13,6 +13,7 @@ import {
import {
bookmarkLinks,
bookmarkTags,
+ bookmarkTexts,
bookmarks,
tagsOnBookmarks,
} from "@hoarder/db/schema";
@@ -64,6 +65,7 @@ async function dummyDrizzleReturnType() {
},
},
link: true,
+ text: true,
},
});
if (!x) {
@@ -75,11 +77,13 @@ async function dummyDrizzleReturnType() {
function toZodSchema(
bookmark: Awaited<ReturnType<typeof dummyDrizzleReturnType>>,
): ZBookmark {
- const { tagsOnBookmarks, link, ...rest } = bookmark;
+ const { tagsOnBookmarks, link, text, ...rest } = bookmark;
let content: ZBookmarkContent;
if (link) {
content = { type: "link", ...link };
+ } else if (text) {
+ content = { type: "text", text: text.text || "" };
} else {
throw new Error("Unknown content type");
}
@@ -95,12 +99,10 @@ function toZodSchema(
}
export const bookmarksAppRouter = router({
- bookmarkLink: authedProcedure
+ createBookmark: authedProcedure
.input(zNewBookmarkRequestSchema)
.output(zBookmarkSchema)
.mutation(async ({ input, ctx }) => {
- const { url } = input;
-
const bookmark = await ctx.db.transaction(
async (tx): Promise<ZBookmark> => {
const bookmark = (
@@ -112,20 +114,39 @@ export const bookmarksAppRouter = router({
.returning()
)[0];
- const link = (
- await tx
- .insert(bookmarkLinks)
- .values({
- id: bookmark.id,
- url,
- })
- .returning()
- )[0];
+ let content: ZBookmarkContent;
- const content: ZBookmarkContent = {
- type: "link",
- ...link,
- };
+ switch (input.type) {
+ case "link": {
+ const link = (
+ await tx
+ .insert(bookmarkLinks)
+ .values({
+ id: bookmark.id,
+ url: input.url,
+ })
+ .returning()
+ )[0];
+ content = {
+ type: "link",
+ ...link,
+ };
+ break;
+ }
+ case "text": {
+ const text = (
+ await tx
+ .insert(bookmarkTexts)
+ .values({ id: bookmark.id, text: input.text })
+ .returning()
+ )[0];
+ content = {
+ type: "text",
+ text: text.text || "",
+ };
+ break;
+ }
+ }
return {
tags: [] as ZBookmarkTags[],
@@ -170,6 +191,30 @@ export const bookmarksAppRouter = router({
return res[0];
}),
+ updateBookmarkText: authedProcedure
+ .input(
+ z.object({
+ bookmarkId: z.string(),
+ text: z.string().max(2000),
+ }),
+ )
+ .use(ensureBookmarkOwnership)
+ .mutation(async ({ input, ctx }) => {
+ const res = await ctx.db
+ .update(bookmarkTexts)
+ .set({
+ text: input.text,
+ })
+ .where(and(eq(bookmarkTexts.id, input.bookmarkId)))
+ .returning();
+ if (res.length == 0) {
+ throw new TRPCError({
+ code: "NOT_FOUND",
+ message: "Bookmark not found",
+ });
+ }
+ }),
+
deleteBookmark: authedProcedure
.input(z.object({ bookmarkId: z.string() }))
.use(ensureBookmarkOwnership)
@@ -212,6 +257,7 @@ export const bookmarksAppRouter = router({
},
},
link: true,
+ text: true,
},
});
if (!bookmark) {
@@ -246,6 +292,7 @@ export const bookmarksAppRouter = router({
},
},
link: true,
+ text: true,
},
});
@@ -271,7 +318,7 @@ export const bookmarksAppRouter = router({
await ctx.db.transaction(async (tx) => {
// Detaches
if (input.detach.length > 0) {
- await ctx.db.delete(tagsOnBookmarks).where(
+ await tx.delete(tagsOnBookmarks).where(
and(
eq(tagsOnBookmarks.bookmarkId, input.bookmarkId),
inArray(
@@ -295,7 +342,7 @@ export const bookmarksAppRouter = router({
}));
if (toBeCreatedTags.length > 0) {
- await ctx.db
+ await tx
.insert(bookmarkTags)
.values(toBeCreatedTags)
.onConflictDoNothing()
@@ -303,7 +350,7 @@ export const bookmarksAppRouter = router({
}
const allIds = (
- await ctx.db.query.bookmarkTags.findMany({
+ await tx.query.bookmarkTags.findMany({
where: and(
eq(bookmarkTags.userId, ctx.user.id),
inArray(
@@ -317,7 +364,7 @@ export const bookmarksAppRouter = router({
})
).map((t) => t.id);
- await ctx.db
+ await tx
.insert(tagsOnBookmarks)
.values(
allIds.map((i) => ({