Files
juwan-frontend/lib/api/posts.ts
T

79 lines
1.9 KiB
TypeScript

import { isApiError } from "@/lib/errors"
import type { Post } from "@/lib/types"
import { httpJson } from "./http"
type Paginated<T> = {
items: T[]
meta: {
total: number
offset: number
limit: number
}
}
type ListOptions = {
offset?: number
limit?: number
}
function withOffsetLimit(path: string, options?: ListOptions): string {
const offset = options?.offset ?? 0
const limit = options?.limit ?? 100
const searchParams = new URLSearchParams({
offset: String(offset),
limit: String(limit),
})
return `${path}?${searchParams.toString()}`
}
export async function listPosts(options?: ListOptions): Promise<Post[]> {
const res = await httpJson<Paginated<Post>>(withOffsetLimit("/api/v1/posts", options), {
cache: "no-store",
})
return res.items
}
export async function getPostById(postId: string): Promise<Post | undefined> {
try {
return await httpJson<Post>(`/api/v1/posts/${encodeURIComponent(postId)}`, {
cache: "no-store",
})
} catch (error) {
if (error instanceof Error && error.message === "UNAUTHORIZED") {
throw error
}
if (isApiError(error) && error.code === 404) {
return undefined
}
throw error
}
}
export async function listPostsByAuthor(userId: string, options?: ListOptions): Promise<Post[]> {
const res = await httpJson<Paginated<Post>>(
withOffsetLimit(`/api/v1/users/${encodeURIComponent(userId)}/posts`, options),
{
cache: "no-store",
},
)
return res.items
}
export async function togglePostLike(postId: string, currentlyLiked: boolean): Promise<void> {
const encodedId = encodeURIComponent(postId)
if (currentlyLiked) {
await httpJson<unknown>(`/api/v1/posts/${encodedId}/like`, {
method: "DELETE",
cache: "no-store",
})
return
}
await httpJson<unknown>(`/api/v1/posts/${encodedId}/like`, {
method: "POST",
cache: "no-store",
})
}