aboutsummaryrefslogtreecommitdiffstats
path: root/packages/web/lib
diff options
context:
space:
mode:
Diffstat (limited to 'packages/web/lib')
-rw-r--r--packages/web/lib/api.ts19
-rw-r--r--packages/web/lib/services/bookmarks.ts92
-rw-r--r--packages/web/lib/services/links.ts78
-rw-r--r--packages/web/lib/types/api/bookmarks.ts37
-rw-r--r--packages/web/lib/types/api/links.ts33
-rw-r--r--packages/web/lib/types/api/tags.ts1
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>;