79 lines
1.9 KiB
TypeScript
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",
|
|
})
|
|
}
|