diff options
| author | MohamedBassem <me@mbassem.com> | 2024-02-07 02:48:38 +0000 |
|---|---|---|
| committer | MohamedBassem <me@mbassem.com> | 2024-02-07 02:48:38 +0000 |
| commit | daebbf0154a290fb690ed94fca23377e0f739f53 (patch) | |
| tree | d02b91093a976704a558971490cf2e6406c48b94 /web/lib/api.ts | |
| parent | c3ecb08ec0addfb02e2da7e79e168ca17d38cd3b (diff) | |
| download | karakeep-daebbf0154a290fb690ed94fca23377e0f739f53.tar.zst | |
[ui] Very first draft of the link grid
Diffstat (limited to 'web/lib/api.ts')
| -rw-r--r-- | web/lib/api.ts | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/web/lib/api.ts b/web/lib/api.ts new file mode 100644 index 00000000..193d9bb7 --- /dev/null +++ b/web/lib/api.ts @@ -0,0 +1,87 @@ +"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; +}; + +async function doRequest<Schema extends ZodTypeAny>( + _path: string, + respSchema: Schema, + _opts: RequestInit | undefined, +): Promise<[z.infer<typeof respSchema>, undefined] | [undefined, FetchError]>; + +async function doRequest<_Schema>( + _path: string, + _respSchema: undefined, + _opts: RequestInit | undefined, +): Promise<[undefined, undefined] | [undefined, FetchError]>; + +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), + }); + } +} |
