aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/web/app/api/v1/bookmarks/[bookmarkId]/lists/route.ts18
-rw-r--r--apps/web/app/api/v1/bookmarks/[bookmarkId]/tags/route.ts45
-rw-r--r--apps/web/app/api/v1/lists/[listId]/bookmarks/[bookmarkId]/route.ts35
-rw-r--r--apps/web/app/api/v1/lists/[listId]/bookmarks/route.ts18
-rw-r--r--apps/web/app/api/v1/lists/[listId]/route.ts22
-rw-r--r--apps/web/app/api/v1/tags/[tagId]/bookmarks/route.ts25
-rw-r--r--apps/web/app/api/v1/tags/[tagId]/route.ts22
7 files changed, 151 insertions, 34 deletions
diff --git a/apps/web/app/api/v1/bookmarks/[bookmarkId]/lists/route.ts b/apps/web/app/api/v1/bookmarks/[bookmarkId]/lists/route.ts
new file mode 100644
index 00000000..ad3052c9
--- /dev/null
+++ b/apps/web/app/api/v1/bookmarks/[bookmarkId]/lists/route.ts
@@ -0,0 +1,18 @@
+import { NextRequest } from "next/server";
+import { buildHandler } from "@/app/api/v1/utils/handler";
+
+export const dynamic = "force-dynamic";
+
+export const GET = (
+ req: NextRequest,
+ params: { params: { bookmarkId: string } },
+) =>
+ buildHandler({
+ req,
+ handler: async ({ api }) => {
+ const resp = await api.lists.getListsOfBookmark({
+ bookmarkId: params.params.bookmarkId,
+ });
+ return { status: 200, resp };
+ },
+ });
diff --git a/apps/web/app/api/v1/bookmarks/[bookmarkId]/tags/route.ts b/apps/web/app/api/v1/bookmarks/[bookmarkId]/tags/route.ts
new file mode 100644
index 00000000..df464618
--- /dev/null
+++ b/apps/web/app/api/v1/bookmarks/[bookmarkId]/tags/route.ts
@@ -0,0 +1,45 @@
+import { NextRequest } from "next/server";
+import { buildHandler } from "@/app/api/v1/utils/handler";
+import { z } from "zod";
+
+import { zManipulatedTagSchema } from "@hoarder/shared/types/bookmarks";
+
+export const dynamic = "force-dynamic";
+
+export const POST = (
+ req: NextRequest,
+ params: { params: { bookmarkId: string } },
+) =>
+ buildHandler({
+ req,
+ bodySchema: z.object({
+ tags: z.array(zManipulatedTagSchema),
+ }),
+ handler: async ({ api, body }) => {
+ const resp = await api.bookmarks.updateTags({
+ bookmarkId: params.params.bookmarkId,
+ attach: body!.tags,
+ detach: [],
+ });
+ return { status: 200, resp: { attached: resp.attached } };
+ },
+ });
+
+export const DELETE = (
+ req: NextRequest,
+ params: { params: { bookmarkId: string } },
+) =>
+ buildHandler({
+ req,
+ bodySchema: z.object({
+ tags: z.array(zManipulatedTagSchema),
+ }),
+ handler: async ({ api, body }) => {
+ const resp = await api.bookmarks.updateTags({
+ bookmarkId: params.params.bookmarkId,
+ detach: body!.tags,
+ attach: [],
+ });
+ return { status: 200, resp: { detached: resp.detached } };
+ },
+ });
diff --git a/apps/web/app/api/v1/lists/[listId]/bookmarks/[bookmarkId]/route.ts b/apps/web/app/api/v1/lists/[listId]/bookmarks/[bookmarkId]/route.ts
new file mode 100644
index 00000000..6efe2055
--- /dev/null
+++ b/apps/web/app/api/v1/lists/[listId]/bookmarks/[bookmarkId]/route.ts
@@ -0,0 +1,35 @@
+import { NextRequest } from "next/server";
+import { buildHandler } from "@/app/api/v1/utils/handler";
+
+export const dynamic = "force-dynamic";
+
+export const PUT = (
+ req: NextRequest,
+ { params }: { params: { listId: string; bookmarkId: string } },
+) =>
+ buildHandler({
+ req,
+ handler: async ({ api }) => {
+ // TODO: PUT is supposed to be idempotent, but we currently fail if the bookmark is already in the list.
+ await api.lists.addToList({
+ listId: params.listId,
+ bookmarkId: params.bookmarkId,
+ });
+ return { status: 204 };
+ },
+ });
+
+export const DELETE = (
+ req: NextRequest,
+ { params }: { params: { listId: string; bookmarkId: string } },
+) =>
+ buildHandler({
+ req,
+ handler: async ({ api }) => {
+ await api.lists.removeFromList({
+ listId: params.listId,
+ bookmarkId: params.bookmarkId,
+ });
+ return { status: 204 };
+ },
+ });
diff --git a/apps/web/app/api/v1/lists/[listId]/bookmarks/route.ts b/apps/web/app/api/v1/lists/[listId]/bookmarks/route.ts
new file mode 100644
index 00000000..72d4aa5f
--- /dev/null
+++ b/apps/web/app/api/v1/lists/[listId]/bookmarks/route.ts
@@ -0,0 +1,18 @@
+import { NextRequest } from "next/server";
+import { buildHandler } from "@/app/api/v1/utils/handler";
+import { adaptPagination, zPagination } from "@/app/api/v1/utils/pagination";
+
+export const dynamic = "force-dynamic";
+
+export const GET = (req: NextRequest, params: { params: { listId: string } }) =>
+ buildHandler({
+ req,
+ searchParamsSchema: zPagination,
+ handler: async ({ api, searchParams }) => {
+ const bookmarks = await api.bookmarks.getBookmarks({
+ listId: params.params.listId,
+ ...searchParams,
+ });
+ return { status: 200, resp: adaptPagination(bookmarks) };
+ },
+ });
diff --git a/apps/web/app/api/v1/lists/[listId]/route.ts b/apps/web/app/api/v1/lists/[listId]/route.ts
index d3e1f17c..f5af286d 100644
--- a/apps/web/app/api/v1/lists/[listId]/route.ts
+++ b/apps/web/app/api/v1/lists/[listId]/route.ts
@@ -1,6 +1,5 @@
import { NextRequest } from "next/server";
import { buildHandler } from "@/app/api/v1/utils/handler";
-import { adaptPagination, zPagination } from "@/app/api/v1/utils/pagination";
export const dynamic = "force-dynamic";
@@ -10,24 +9,13 @@ export const GET = (
) =>
buildHandler({
req,
- searchParamsSchema: zPagination,
- handler: async ({ api, searchParams }) => {
- const [list, bookmarks] = await Promise.all([
- api.lists.get({
- listId: params.listId,
- }),
- api.bookmarks.getBookmarks({
- listId: params.listId,
- limit: searchParams.limit,
- cursor: searchParams.cursor,
- }),
- ]);
+ handler: async ({ api }) => {
+ const list = await api.lists.get({
+ listId: params.listId,
+ });
return {
status: 200,
- resp: {
- ...list,
- ...adaptPagination(bookmarks),
- },
+ resp: list,
};
},
});
diff --git a/apps/web/app/api/v1/tags/[tagId]/bookmarks/route.ts b/apps/web/app/api/v1/tags/[tagId]/bookmarks/route.ts
new file mode 100644
index 00000000..98133ec7
--- /dev/null
+++ b/apps/web/app/api/v1/tags/[tagId]/bookmarks/route.ts
@@ -0,0 +1,25 @@
+import { NextRequest } from "next/server";
+import { buildHandler } from "@/app/api/v1/utils/handler";
+import { adaptPagination, zPagination } from "@/app/api/v1/utils/pagination";
+
+export const dynamic = "force-dynamic";
+
+export const GET = (
+ req: NextRequest,
+ { params }: { params: { tagId: string } },
+) =>
+ buildHandler({
+ req,
+ searchParamsSchema: zPagination,
+ handler: async ({ api, searchParams }) => {
+ const bookmarks = await api.bookmarks.getBookmarks({
+ tagId: params.tagId,
+ limit: searchParams.limit,
+ cursor: searchParams.cursor,
+ });
+ return {
+ status: 200,
+ resp: adaptPagination(bookmarks),
+ };
+ },
+ });
diff --git a/apps/web/app/api/v1/tags/[tagId]/route.ts b/apps/web/app/api/v1/tags/[tagId]/route.ts
index a82e693c..439b6149 100644
--- a/apps/web/app/api/v1/tags/[tagId]/route.ts
+++ b/apps/web/app/api/v1/tags/[tagId]/route.ts
@@ -1,6 +1,5 @@
import { NextRequest } from "next/server";
import { buildHandler } from "@/app/api/v1/utils/handler";
-import { adaptPagination, zPagination } from "@/app/api/v1/utils/pagination";
export const dynamic = "force-dynamic";
@@ -10,24 +9,13 @@ export const GET = (
) =>
buildHandler({
req,
- searchParamsSchema: zPagination,
- handler: async ({ api, searchParams }) => {
- const [tag, bookmarks] = await Promise.all([
- api.tags.get({
- tagId: params.tagId,
- }),
- api.bookmarks.getBookmarks({
- tagId: params.tagId,
- limit: searchParams.limit,
- cursor: searchParams.cursor,
- }),
- ]);
+ handler: async ({ api }) => {
+ const tag = await api.tags.get({
+ tagId: params.tagId,
+ });
return {
status: 200,
- resp: {
- ...tag,
- ...adaptPagination(bookmarks),
- },
+ resp: tag,
};
},
});