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

86 lines
2.1 KiB
TypeScript

import { allow, deny } from "@/lib/decision"
import { toApiError } from "@/lib/errors"
import type { Comment } 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 listCommentsByPost(
postId: string,
options?: ListOptions,
): Promise<Comment[]> {
const encodedId = encodeURIComponent(postId)
const res = await httpJson<Paginated<Comment>>(
withOffsetLimit(`/api/v1/posts/${encodedId}/comments`, options),
{
cache: "no-store",
},
)
return res.items
}
export async function addComment(postId: string, content: string) {
const encodedId = encodeURIComponent(postId)
try {
await httpJson<unknown>(`/api/v1/posts/${encodedId}/comments`, {
method: "POST",
cache: "no-store",
json: { content },
})
return allow()
} catch (err: unknown) {
if (err instanceof Error && err.message === "UNAUTHORIZED") {
return deny(401, "请先登录")
}
const apiError = toApiError(err)
return deny(apiError.code, apiError.msg)
}
}
export async function toggleCommentLike(commentId: string, currentlyLiked: boolean) {
const encodedId = encodeURIComponent(commentId)
try {
if (currentlyLiked) {
await httpJson<unknown>(`/api/v1/comments/${encodedId}/like`, {
method: "DELETE",
cache: "no-store",
})
} else {
await httpJson<unknown>(`/api/v1/comments/${encodedId}/like`, {
method: "POST",
cache: "no-store",
})
}
return allow()
} catch (err: unknown) {
if (err instanceof Error && err.message === "UNAUTHORIZED") {
return deny(401, "请先登录")
}
const apiError = toApiError(err)
return deny(apiError.code, apiError.msg)
}
}