@waline/api
Version:
Client API for Waline comment system
1 lines • 19.3 kB
Source Map (JSON)
{"version":3,"file":"api.cjs","sources":["../src/utils.ts","../src/articleCounter.ts","../src/comment.ts","../src/commentCount.ts","../src/login.ts","../src/pageview.ts","../src/recentComment.ts","../src/user.ts"],"sourcesContent":["export interface BaseAPIOptions {\n /**\n * Waline 服务端地址\n *\n * Waline serverURL\n */\n serverURL: string;\n\n /**\n * 错误信息所使用的语言\n *\n * Language used in error text\n */\n lang: string;\n}\n\nexport interface ErrorStatusResponse {\n /**\n * 错误代码\n *\n * Error number\n */\n errno: number;\n\n /**\n * 错误消息\n *\n * Error msg\n */\n errmsg: string;\n}\n\nexport const JSON_HEADERS: Record<string, string> = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n 'Content-Type': 'application/json',\n};\n\nexport const getFetchPrefix = (serverURL: string): string =>\n `${serverURL.replace(/\\/?$/, '/')}api/`;\n\nexport const errorCheck = <T extends ErrorStatusResponse>(\n data: T,\n name = '',\n): T => {\n if (typeof data === 'object' && data.errno)\n throw new TypeError(`${name} failed with ${data.errno}: ${data.errmsg}`);\n\n return data;\n};\n","import type { BaseAPIOptions, ErrorStatusResponse } from './utils.js';\nimport { JSON_HEADERS, errorCheck, getFetchPrefix } from './utils.js';\n\nexport interface GetArticleCounterOptions extends BaseAPIOptions {\n /**\n * 待获取计数器的 path\n *\n * Path of counters\n */\n paths: string[];\n\n /**\n * 待获取计数器的类型\n *\n * Counter type to be fetched\n */\n type: string[];\n\n /**\n * 取消请求的信号\n *\n * AbortSignal to cancel request\n */\n signal?: AbortSignal;\n}\n\nexport interface CounterFields {\n time?: number;\n reaction0?: number;\n reaction1?: number;\n reaction2?: number;\n reaction3?: number;\n reaction4?: number;\n reaction5?: number;\n reaction6?: number;\n reaction7?: number;\n reaction8?: number;\n}\n\nexport type GetArticleCounterResponseItem = Record<string, number> &\n CounterFields;\n\nexport type GetArticleCounterResponse = GetArticleCounterResponseItem[];\n\nexport const getArticleCounter = ({\n serverURL,\n lang,\n paths,\n type,\n signal,\n}: GetArticleCounterOptions): Promise<GetArticleCounterResponse> =>\n fetch(\n `${getFetchPrefix(serverURL)}article?path=${encodeURIComponent(\n paths.join(','),\n )}&type=${encodeURIComponent(type.join(','))}&lang=${lang}`,\n { signal },\n )\n .then(\n (resp) =>\n resp.json() as Promise<\n { data: GetArticleCounterResponse } & ErrorStatusResponse\n >,\n )\n .then((data) => errorCheck(data, 'Get counter').data);\n\nexport interface UpdateArticleCounterOptions extends BaseAPIOptions {\n /**\n * 待更新计数器的 path\n *\n * Path of counter to be updated\n */\n path: string;\n\n /**\n * 待更新计数器的类型\n *\n * Counter type to be updated\n */\n type: string;\n\n /**\n * 更新操作\n *\n * Update operation\n *\n * @default 'inc'\n */\n action?: 'inc' | 'desc';\n}\n\nexport const updateArticleCounter = ({\n serverURL,\n lang,\n path,\n type,\n action,\n}: UpdateArticleCounterOptions): Promise<GetArticleCounterResponse> =>\n fetch(`${getFetchPrefix(serverURL)}article?lang=${lang}`, {\n method: 'POST',\n headers: JSON_HEADERS,\n body: JSON.stringify({ path, type, action }),\n })\n .then(\n (resp) =>\n resp.json() as Promise<\n { data: GetArticleCounterResponse } & ErrorStatusResponse\n >,\n )\n .then((data) => errorCheck(data, 'Update counter').data);\n","import type {\n WalineComment,\n WalineCommentData,\n WalineRootComment,\n} from './typings.js';\nimport type { BaseAPIOptions, ErrorStatusResponse } from './utils.js';\nimport { JSON_HEADERS, errorCheck, getFetchPrefix } from './utils.js';\n\nexport interface GetCommentOptions extends BaseAPIOptions {\n /**\n * 待获取评论列表的 path\n *\n * Path of comment list\n */\n path: string;\n\n /**\n * 评论分页数\n *\n * Comment pagination number\n */\n page: number;\n\n /**\n * 每页评论个数\n *\n * Comment number per page\n */\n pageSize: number;\n\n /**\n * 排序方式\n *\n * Sort method\n */\n sortBy: string;\n\n /**\n * 用户令牌\n *\n * User token\n */\n token?: string;\n\n /**\n * 取消请求的信号\n *\n * AbortSignal to cancel request\n */\n signal?: AbortSignal;\n}\n\nexport interface GetCommentResponse {\n /**\n * 评论数量\n *\n * Comment number\n */\n count: number;\n\n /**\n * 评论分页数\n *\n * Comment pagination number\n */\n page: number;\n\n /**\n * 每页评论个数\n *\n * Comment number per page\n */\n pageSize: number;\n\n /**\n * 评论数据\n *\n * Comment Data\n */\n data: WalineRootComment[];\n\n /**\n * 页面总数\n *\n * Page number\n */\n totalPages: number;\n}\n\nexport const getComment = ({\n serverURL,\n lang,\n path,\n page,\n pageSize,\n sortBy,\n signal,\n token,\n}: GetCommentOptions): Promise<GetCommentResponse> => {\n const headers: Record<string, string> = {};\n\n if (token) headers.Authorization = `Bearer ${token}`;\n\n return fetch(\n `${getFetchPrefix(serverURL)}comment?path=${encodeURIComponent(\n path,\n )}&pageSize=${pageSize}&page=${page}&lang=${lang}&sortBy=${sortBy}`,\n { signal, headers },\n )\n .then(\n (resp) =>\n resp.json() as Promise<\n { data: GetCommentResponse } & ErrorStatusResponse\n >,\n )\n .then((data) => errorCheck(data, 'Get comment data').data);\n};\n\nexport interface AddCommentOptions extends BaseAPIOptions {\n /**\n * 用户令牌\n *\n * User token\n */\n token?: string;\n\n /**\n * 用户待提交的评论数据\n *\n * Comment data being submitted by user\n */\n comment: WalineCommentData;\n}\n\nexport interface AddCommentResponse extends ErrorStatusResponse {\n /**\n * 渲染好的评论数据\n *\n * Comment data rendered\n */\n data?: WalineComment;\n}\n\nexport const addComment = ({\n serverURL,\n lang,\n token,\n comment,\n}: AddCommentOptions): Promise<AddCommentResponse> => {\n const headers: Record<string, string> = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n 'Content-Type': 'application/json',\n };\n\n if (token) headers.Authorization = `Bearer ${token}`;\n\n return fetch(`${getFetchPrefix(serverURL)}comment?lang=${lang}`, {\n method: 'POST',\n headers,\n body: JSON.stringify(comment),\n }).then((resp) => resp.json() as Promise<AddCommentResponse>);\n};\n\nexport interface DeleteCommentOptions extends BaseAPIOptions {\n /**\n * Auth token\n *\n * 认证令牌\n */\n token: string;\n\n /**\n * Comment objectId to be deleted\n *\n * 待删除的评论对象 ID\n */\n objectId: number;\n}\n\nexport interface DeleteCommentResponse extends ErrorStatusResponse {\n data: '';\n}\n\nexport const deleteComment = ({\n serverURL,\n lang,\n token,\n objectId,\n}: DeleteCommentOptions): Promise<DeleteCommentResponse> =>\n fetch(`${getFetchPrefix(serverURL)}comment/${objectId}?lang=${lang}`, {\n method: 'DELETE',\n headers: {\n Authorization: `Bearer ${token}`,\n },\n })\n .then((resp) => resp.json() as Promise<DeleteCommentResponse>)\n .then((resp) => errorCheck(resp, 'Delete comment'));\n\ninterface UpdateWalineCommentData extends Partial<WalineCommentData> {\n /**\n * 点赞还是取消点赞\n *\n * Like or dislike\n */\n like?: boolean;\n\n /**\n * 评论的状态\n *\n * Comment status\n */\n status?: 'approved' | 'waiting' | 'spam';\n\n /**\n * 评论指定状态\n *\n * Comment sticky status\n *\n * @description 0 means not sticky and 1 means sticky\n */\n sticky?: 0 | 1;\n}\nexport interface UpdateCommentOptions extends BaseAPIOptions {\n /**\n * 用户令牌\n *\n * User token\n */\n token: string;\n\n /**\n * 评论的 ID\n *\n * Comment ID\n */\n objectId: number;\n\n /**\n * 评论数据\n *\n * Comment data\n */\n comment?: UpdateWalineCommentData;\n}\n\nexport interface UpdateCommentResponse extends ErrorStatusResponse {\n /**\n * 更新后的评论数据\n *\n * Comment data rendered\n */\n data: WalineComment;\n}\n\nexport const updateComment = ({\n serverURL,\n lang,\n token,\n objectId,\n comment,\n}: UpdateCommentOptions): Promise<UpdateCommentResponse> =>\n fetch(`${getFetchPrefix(serverURL)}comment/${objectId}?lang=${lang}`, {\n method: 'PUT',\n headers: {\n ...JSON_HEADERS,\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(comment),\n })\n .then((resp) => resp.json() as Promise<UpdateCommentResponse>)\n .then((resp) => errorCheck(resp, 'Update comment'));\n","import type { BaseAPIOptions, ErrorStatusResponse } from './utils.js';\nimport { errorCheck, getFetchPrefix } from './utils.js';\n\nexport interface GetCommentCountOptions extends BaseAPIOptions {\n /**\n * 待获取评论数的 path\n *\n * Path of pages to be fetched\n */\n paths: string[];\n\n /**\n * 取消请求的信号\n *\n * AbortSignal to cancel request\n */\n signal?: AbortSignal;\n}\n\nexport const fetchCommentCount = ({\n serverURL,\n lang,\n paths,\n signal,\n}: GetCommentCountOptions): Promise<number[]> =>\n fetch(\n `${getFetchPrefix(serverURL)}comment?type=count&url=${encodeURIComponent(\n paths.join(','),\n )}&lang=${lang}`,\n { signal },\n )\n .then(\n (resp) =>\n resp.json() as Promise<{ data: number[] } & ErrorStatusResponse>,\n )\n .then((data) => errorCheck(data, 'Get comment count').data);\n","/* eslint-disable @typescript-eslint/no-unsafe-member-access */\nimport type { BaseAPIOptions } from './utils.js';\n\nexport interface UserInfo {\n /**\n * 显示姓名\n *\n * User name displayed\n */\n // eslint-disable-next-line @typescript-eslint/naming-convention\n display_name: string;\n\n /**\n * 用户电子邮件地址\n *\n * User email\n */\n email: string;\n\n /**\n * 用户网站地址\n *\n * User website\n */\n url: string;\n\n /**\n * 用户令牌\n *\n * User token\n */\n token: string;\n\n /**\n * 用户头像\n *\n * User avatar\n */\n avatar: string;\n\n /**\n * 用户邮箱 MD5\n *\n * MD5 of User email\n */\n mailMd5: string;\n\n /**\n * 用户对象 ID\n *\n * User object ID\n */\n objectId: number;\n\n /**\n * 用户身份\n *\n * User role\n */\n type: 'administrator' | 'guest';\n}\n\nexport const login = ({\n lang,\n serverURL,\n}: BaseAPIOptions): Promise<UserInfo & { remember: boolean }> => {\n const width = 450;\n const height = 450;\n const left = (window.innerWidth - width) / 2;\n const top = (window.innerHeight - height) / 2;\n\n const handler = window.open(\n `${serverURL.replace(/\\/$/, '')}/ui/login?lng=${encodeURIComponent(lang)}`,\n '_blank',\n `width=${width},height=${height},left=${left},top=${top},scrollbars=no,resizable=no,status=no,location=no,toolbar=no,menubar=no`,\n );\n\n handler?.postMessage({ type: 'TOKEN', data: null }, '*');\n\n return new Promise((resolve) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const receiver = ({ data }: any): void => {\n if (!data || typeof data !== 'object' || data.type !== 'userInfo') return;\n\n if (data.data.token) {\n handler?.close();\n\n window.removeEventListener('message', receiver);\n\n resolve(data.data as UserInfo & { remember: boolean });\n }\n };\n\n window.addEventListener('message', receiver);\n });\n};\n","import type { GetArticleCounterResponse } from './articleCounter.js';\nimport { getArticleCounter, updateArticleCounter } from './articleCounter.js';\nimport type { BaseAPIOptions } from './utils.js';\n\ninterface GetPageviewOptions extends BaseAPIOptions {\n /**\n * 待获取页面的 path\n *\n * Path of pages\n */\n paths: string[];\n\n /**\n * 取消请求的信号\n *\n * AbortSignal to cancel request\n */\n signal?: AbortSignal;\n}\n\nexport const getPageview = ({\n serverURL,\n lang,\n paths,\n signal,\n}: GetPageviewOptions): Promise<GetArticleCounterResponse> =>\n getArticleCounter({\n serverURL,\n lang,\n paths,\n type: ['time'],\n signal,\n });\n\nexport interface UpdatePageviewOptions extends BaseAPIOptions {\n /**\n * 待更新页面的 path\n *\n * Path of pages\n */\n path: string;\n}\n\nexport const updatePageview = (\n options: UpdatePageviewOptions,\n): Promise<GetArticleCounterResponse> =>\n updateArticleCounter({\n ...options,\n type: 'time',\n action: 'inc',\n });\n","import type { BaseWalineResponseComment } from './typings.js';\nimport type { BaseAPIOptions } from './utils.js';\nimport { getFetchPrefix } from './utils.js';\n\nexport interface GetRecentCommentOptions extends BaseAPIOptions {\n /**\n * 获取评论的数量\n *\n * Comment number to be fetched\n */\n count: number;\n\n /**\n * 取消请求的信号\n *\n * AbortSignal to cancel request\n */\n signal?: AbortSignal;\n\n /**\n * 用户令牌\n *\n * User token\n */\n token?: string;\n}\n\nexport interface RecentCommentData extends BaseWalineResponseComment {\n /**\n * Page url where comment locales\n *\n * 评论所在页面地址\n */\n url: string;\n}\n\nexport const getRecentComment = ({\n serverURL,\n lang,\n count,\n signal,\n token,\n}: GetRecentCommentOptions): Promise<RecentCommentData[]> => {\n const headers: Record<string, string> = {};\n\n if (token) headers.Authorization = `Bearer ${token}`;\n\n return fetch(\n `${getFetchPrefix(\n serverURL,\n )}comment?type=recent&count=${count}&lang=${lang}`,\n {\n signal,\n headers,\n },\n ).then((resp) => resp.json() as Promise<RecentCommentData[]>);\n};\n","import type { WalineComment } from './typings.js';\nimport type { BaseAPIOptions, ErrorStatusResponse } from './utils.js';\nimport { errorCheck, getFetchPrefix } from './utils.js';\n\nexport interface GetUserListOptions extends BaseAPIOptions {\n /**\n * 每页个数\n *\n * Number per page\n */\n pageSize: number;\n\n /**\n * 取消请求的信号\n *\n * AbortSignal to cancel request\n */\n signal?: AbortSignal;\n}\n\nexport interface WalineUser\n extends Pick<WalineComment, 'nick' | 'link' | 'avatar' | 'label' | 'level'> {\n count: number;\n}\n\nexport interface GetUserListResponse extends ErrorStatusResponse {\n data: WalineUser[];\n}\n\nexport const getUserList = ({\n serverURL,\n signal,\n pageSize,\n lang,\n}: GetUserListOptions): Promise<WalineUser[]> =>\n fetch(`${getFetchPrefix(serverURL)}user?pageSize=${pageSize}&lang=${lang}`, {\n signal,\n })\n .then((resp) => resp.json() as Promise<GetUserListResponse>)\n .then((resp) => errorCheck(resp, 'user list'))\n .then((resp) => resp.data);\n"],"names":["JSON_HEADERS","getFetchPrefix","serverURL","errorCheck","data","name","getArticleCounter","lang","paths","type","signal","resp","updateArticleCounter","path","action","getComment","page","pageSize","sortBy","token","headers","addComment","comment","deleteComment","objectId","updateComment","fetchCommentCount","login","left","top","handler","resolve","receiver","getPageview","updatePageview","options","getRecentComment","count","getUserList"],"mappings":"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"}