Snippet
publicLanguage: typescript
Created
Jan 22, 2026 • 11:23 AM
Visibility
public
1// Lightweight fetch wrapper with typed responses
2
3export type ApiError = {
4 status: number
5 message: string
6}
7
8export class ApiClient {
9 private baseUrl: string
10 private token?: string
11
12 constructor(baseUrl: string, token?: string) {
13 this.baseUrl = baseUrl.replace(/\/$/, "")
14 this.token = token
15 }
16
17 setToken(token: string) {
18 this.token = token
19 }
20
21 async get<T>(path: string): Promise<T> {
22 return this.request<T>("GET", path)
23 }
24
25 async post<T>(path: string, body?: unknown): Promise<T> {
26 return this.request<T>("POST", path, body)
27 }
28
29 private async request<T>(
30 method: string,
31 path: string,
32 body?: unknown
33 ): Promise<T> {
34 const res = await fetch(this.baseUrl + path, {
35 method,
36 headers: {
37 "Content-Type": "application/json",
38 ...(this.token && { Authorization: `Bearer ${this.token}` }),
39 },
40 body: body ? JSON.stringify(body) : undefined,
41 })
42
43 if (!res.ok) {
44 const msg = await res.text()
45 throw <ApiError>{
46 status: res.status,
47 message: msg || res.statusText,
48 }
49 }
50
51 return (await res.json()) as T
52 }
53}
54
55// Example usage:
56const api = new ApiClient("https://api.pastehub.de", "user-token")
57
58api.get<{ username: string }>("/me").then((me) => {
59 console.log("Logged in as", me.username)
60})
61