diff options
| author | MohamedBassem <me@mbassem.com> | 2024-02-08 15:14:23 +0000 |
|---|---|---|
| committer | MohamedBassem <me@mbassem.com> | 2024-02-08 15:15:21 +0000 |
| commit | 80bb8a108f29331cdb2f2695f6801beee104dc89 (patch) | |
| tree | b1ae2a512963a9c916c4bfed71f7633f508de131 /packages/web/lib/api.ts | |
| parent | 333429adbaaa592cc96b480a5228f0e3f1de4cc2 (diff) | |
| download | karakeep-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.ts | 81 |
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", + }); + } +} |
