aboutsummaryrefslogtreecommitdiffstats
path: root/packages/web/lib/api.ts
diff options
context:
space:
mode:
authorMohamedBassem <me@mbassem.com>2024-02-08 15:14:23 +0000
committerMohamedBassem <me@mbassem.com>2024-02-08 15:15:21 +0000
commit80bb8a108f29331cdb2f2695f6801beee104dc89 (patch)
treeb1ae2a512963a9c916c4bfed71f7633f508de131 /packages/web/lib/api.ts
parent333429adbaaa592cc96b480a5228f0e3f1de4cc2 (diff)
downloadkarakeep-80bb8a108f29331cdb2f2695f6801beee104dc89.tar.zst
[refactor] Move the different packages to the package subdir
Diffstat (limited to 'packages/web/lib/api.ts')
-rw-r--r--packages/web/lib/api.ts81
1 files changed, 81 insertions, 0 deletions
diff --git a/packages/web/lib/api.ts b/packages/web/lib/api.ts
new file mode 100644
index 00000000..56686cde
--- /dev/null
+++ b/packages/web/lib/api.ts
@@ -0,0 +1,81 @@
+"use client";
+
+import { ZodTypeAny, z } from "zod";
+import {
+ ZNewBookmarkedLinkRequest,
+ zGetLinksResponseSchema,
+} from "./types/api/links";
+
+import serverConfig from "./config";
+
+const BASE_URL = `${serverConfig.api_url}/api/v1`;
+
+export type FetchError = {
+ status?: number;
+ message?: string;
+};
+
+type InputSchema<T> = T extends ZodTypeAny ? T : undefined;
+
+async function doRequest<T>(
+ path: string,
+ respSchema?: InputSchema<T>,
+ opts?: RequestInit,
+): Promise<
+ | (InputSchema<T> extends ZodTypeAny
+ ? [z.infer<InputSchema<T>>, undefined]
+ : [undefined, undefined])
+ | [undefined, FetchError]
+> {
+ try {
+ const res = await fetch(`${BASE_URL}${path}`, opts);
+ if (!res.ok) {
+ return [
+ undefined,
+ { status: res.status, message: await res.text() },
+ ] as const;
+ }
+ if (!respSchema) {
+ return [undefined, undefined] as const;
+ }
+
+ let parsed = respSchema.safeParse(await res.json());
+ if (!parsed.success) {
+ return [
+ undefined,
+ { message: `Failed to parse response: ${parsed.error.toString()}` },
+ ] as const;
+ }
+
+ return [parsed.data, undefined] as const;
+ } catch (error: any) {
+ return [
+ undefined,
+ { message: `Failed to execute fetch request: ${error}` },
+ ] as const;
+ }
+}
+
+export default class APIClient {
+ static async getLinks() {
+ return await doRequest(`/links`, zGetLinksResponseSchema, {
+ next: { tags: ["links"] },
+ });
+ }
+
+ static async bookmarkLink(url: string) {
+ const body: ZNewBookmarkedLinkRequest = {
+ url,
+ };
+ return await doRequest(`/links`, undefined, {
+ method: "POST",
+ body: JSON.stringify(body),
+ });
+ }
+
+ static async unbookmarkLink(linkId: string) {
+ return await doRequest(`/links/${linkId}`, undefined, {
+ method: "DELETE",
+ });
+ }
+}