diff options
Diffstat (limited to 'packages/web/lib')
| -rw-r--r-- | packages/web/lib/api.ts | 19 | ||||
| -rw-r--r-- | packages/web/lib/services/bookmarks.ts | 92 | ||||
| -rw-r--r-- | packages/web/lib/services/links.ts | 78 | ||||
| -rw-r--r-- | packages/web/lib/types/api/bookmarks.ts | 37 | ||||
| -rw-r--r-- | packages/web/lib/types/api/links.ts | 33 | ||||
| -rw-r--r-- | packages/web/lib/types/api/tags.ts | 1 |
6 files changed, 140 insertions, 120 deletions
diff --git a/packages/web/lib/api.ts b/packages/web/lib/api.ts index 56686cde..8ee08601 100644 --- a/packages/web/lib/api.ts +++ b/packages/web/lib/api.ts @@ -2,9 +2,9 @@ import { ZodTypeAny, z } from "zod"; import { - ZNewBookmarkedLinkRequest, - zGetLinksResponseSchema, -} from "./types/api/links"; + ZNewBookmarkRequest, + zGetBookmarksResponseSchema, +} from "./types/api/bookmarks"; import serverConfig from "./config"; @@ -57,24 +57,25 @@ async function doRequest<T>( } export default class APIClient { - static async getLinks() { - return await doRequest(`/links`, zGetLinksResponseSchema, { + static async getBookmarks() { + return await doRequest(`/bookmarks`, zGetBookmarksResponseSchema, { next: { tags: ["links"] }, }); } static async bookmarkLink(url: string) { - const body: ZNewBookmarkedLinkRequest = { + const body: ZNewBookmarkRequest = { + type: "link", url, }; - return await doRequest(`/links`, undefined, { + return await doRequest(`/bookmarks`, undefined, { method: "POST", body: JSON.stringify(body), }); } - static async unbookmarkLink(linkId: string) { - return await doRequest(`/links/${linkId}`, undefined, { + static async deleteBookmark(id: string) { + return await doRequest(`/bookmarks/${id}`, undefined, { method: "DELETE", }); } diff --git a/packages/web/lib/services/bookmarks.ts b/packages/web/lib/services/bookmarks.ts new file mode 100644 index 00000000..3c9929bc --- /dev/null +++ b/packages/web/lib/services/bookmarks.ts @@ -0,0 +1,92 @@ +import { LinkCrawlerQueue } from "@remember/shared/queues"; +import prisma from "@remember/db"; +import { ZBookmark, ZBookmarkContent } from "@/lib/types/api/bookmarks"; + +const defaultBookmarkFields = { + id: true, + favourited: true, + archived: true, + createdAt: true, + link: { + select: { + url: true, + title: true, + description: true, + imageUrl: true, + favicon: true, + }, + }, + tags: { + include: { + tag: true, + }, + }, +}; + +async function dummyPrismaReturnType() { + const x = await prisma.bookmark.findFirstOrThrow({ + select: defaultBookmarkFields, + }); + return x; +} + +function toZodSchema( + bookmark: Awaited<ReturnType<typeof dummyPrismaReturnType>>, +): ZBookmark { + const { tags, link, ...rest } = bookmark; + + let content: ZBookmarkContent; + if (link) { + content = { type: "link", ...link }; + } else { + throw new Error("Unknown content type"); + } + + return { + tags: tags.map((t) => t.tag), + content, + ...rest, + }; +} + +export async function deleteBookmark(bookmarkId: string, userId: string) { + await prisma.bookmark.delete({ + where: { + id: bookmarkId, + userId, + }, + }); +} + +export async function bookmarkLink(url: string, userId: string) { + const bookmark = await prisma.bookmark.create({ + data: { + link: { + create: { + url, + }, + }, + userId, + }, + select: defaultBookmarkFields, + }); + + // Enqueue crawling request + await LinkCrawlerQueue.add("crawl", { + bookmarkId: bookmark.id, + url: url, + }); + + return toZodSchema(bookmark); +} + +export async function getBookmarks(userId: string) { + return ( + await prisma.bookmark.findMany({ + where: { + userId, + }, + select: defaultBookmarkFields, + }) + ).map(toZodSchema); +} diff --git a/packages/web/lib/services/links.ts b/packages/web/lib/services/links.ts deleted file mode 100644 index d273b118..00000000 --- a/packages/web/lib/services/links.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { LinkCrawlerQueue } from "@remember/shared/queues"; -import prisma from "@remember/db"; -import { ZBookmarkedLink } from "@/lib/types/api/links"; - -const defaultLinkFields = { - id: true, - url: true, - createdAt: true, - details: { - select: { - title: true, - description: true, - imageUrl: true, - favicon: true, - }, - }, - tags: { - include: { - tag: true, - }, - }, -}; - -async function dummyPrismaReturnType() { - return await prisma.bookmarkedLink.findFirstOrThrow({ - select: defaultLinkFields, - }); -} - -function toZodSchema( - link: Awaited<ReturnType<typeof dummyPrismaReturnType>>, -): ZBookmarkedLink { - return { - id: link.id, - url: link.url, - createdAt: link.createdAt, - details: link.details, - tags: link.tags.map((t) => t.tag), - }; -} - -export async function unbookmarkLink(linkId: string, userId: string) { - await prisma.bookmarkedLink.delete({ - where: { - id: linkId, - userId, - }, - }); -} - -export async function bookmarkLink(url: string, userId: string) { - const link = await prisma.bookmarkedLink.create({ - data: { - url, - userId, - }, - select: defaultLinkFields, - }); - - // Enqueue crawling request - await LinkCrawlerQueue.add("crawl", { - linkId: link.id, - url: link.url, - }); - - return toZodSchema(link); -} - -export async function getLinks(userId: string) { - return ( - await prisma.bookmarkedLink.findMany({ - where: { - userId, - }, - select: defaultLinkFields, - }) - ).map(toZodSchema); -} diff --git a/packages/web/lib/types/api/bookmarks.ts b/packages/web/lib/types/api/bookmarks.ts new file mode 100644 index 00000000..485fbfab --- /dev/null +++ b/packages/web/lib/types/api/bookmarks.ts @@ -0,0 +1,37 @@ +import { z } from "zod"; +import { zBookmarkTagSchema } from "@/lib/types/api/tags"; + +export const zBookmarkedLinkSchema = z.object({ + type: z.literal("link"), + url: z.string().url(), + title: z.string().nullish(), + description: z.string().nullish(), + imageUrl: z.string().url().nullish(), + favicon: z.string().url().nullish(), +}); +export type ZBookmarkedLink = z.infer<typeof zBookmarkedLinkSchema>; + +export const zBookmarkContentSchema = z.discriminatedUnion("type", [ + zBookmarkedLinkSchema, +]); +export type ZBookmarkContent = z.infer<typeof zBookmarkContentSchema>; + +export const zBookmarkSchema = z.object({ + id: z.string(), + createdAt: z.coerce.date(), + archived: z.boolean(), + favourited: z.boolean(), + tags: z.array(zBookmarkTagSchema), + content: zBookmarkContentSchema, +}); +export type ZBookmark = z.infer<typeof zBookmarkSchema>; + +// POST /v1/bookmarks +export const zNewBookmarkRequestSchema = zBookmarkContentSchema; +export type ZNewBookmarkRequest = z.infer<typeof zNewBookmarkRequestSchema>; + +// GET /v1/bookmarks +export const zGetBookmarksResponseSchema = z.object({ + bookmarks: z.array(zBookmarkSchema), +}); +export type ZGetBookmarksResponse = z.infer<typeof zGetBookmarksResponseSchema>; diff --git a/packages/web/lib/types/api/links.ts b/packages/web/lib/types/api/links.ts deleted file mode 100644 index f84445f6..00000000 --- a/packages/web/lib/types/api/links.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { z } from "zod"; -import { zBookmarkTagSchema } from "@/lib/types/api/tags"; - -export const zBookmarkedLinkSchema = z.object({ - id: z.string(), - url: z.string().url(), - createdAt: z.coerce.date(), - - details: z - .object({ - title: z.string().nullish(), - description: z.string().nullish(), - imageUrl: z.string().url().nullish(), - favicon: z.string().url().nullish(), - }) - .nullish(), - tags: z.array(zBookmarkTagSchema), -}); -export type ZBookmarkedLink = z.infer<typeof zBookmarkedLinkSchema>; - -// POST /v1/links -export const zNewBookmarkedLinkRequestSchema = zBookmarkedLinkSchema.pick({ - url: true, -}); -export type ZNewBookmarkedLinkRequest = z.infer< - typeof zNewBookmarkedLinkRequestSchema ->; - -// GET /v1/links -export const zGetLinksResponseSchema = z.object({ - links: z.array(zBookmarkedLinkSchema), -}); -export type ZGetLinksResponse = z.infer<typeof zGetLinksResponseSchema>; diff --git a/packages/web/lib/types/api/tags.ts b/packages/web/lib/types/api/tags.ts index f2d2bc18..bcd16f5b 100644 --- a/packages/web/lib/types/api/tags.ts +++ b/packages/web/lib/types/api/tags.ts @@ -4,3 +4,4 @@ export const zBookmarkTagSchema = z.object({ id: z.string(), name: z.string(), }); +export type ZBookmarkTags = z.infer<typeof zBookmarkTagSchema>; |
