184 lines
4.9 KiB
TypeScript
184 lines
4.9 KiB
TypeScript
import PocketBase, {
|
||
CommonOptions,
|
||
RecordFullListOptions,
|
||
RecordListOptions,
|
||
RecordModel,
|
||
RecordOptions,
|
||
} from "pocketbase"
|
||
import { Logger } from "winston"
|
||
|
||
/**
|
||
* 用于扩展记录模型的接口,添加展开字段功能
|
||
* @template T 基础对象类型
|
||
*/
|
||
export interface WithExpand<T extends { [key: string]: any } | undefined> {
|
||
expand: T
|
||
}
|
||
|
||
/**
|
||
* PocketBase 数据操作基础类
|
||
* 提供通用的 CRUD 操作方法,自动处理错误和日志
|
||
*
|
||
* @template T 继承自 RecordModel 的类型,表示数据库记录模型
|
||
*/
|
||
class PbToolBase<T extends RecordModel> {
|
||
/** PocketBase 集合名称 */
|
||
protected dbName: string
|
||
/** PocketBase 客户端实例 */
|
||
protected pbClient: PocketBase
|
||
/** 日志记录器实例 */
|
||
protected logger: Logger
|
||
|
||
/**
|
||
* 创建 PbToolBase 实例
|
||
*
|
||
* @param dbName - PocketBase 集合名称
|
||
* @param pbClient - PocketBase 客户端实例
|
||
* @param logger - 日志记录器实例
|
||
*/
|
||
constructor(dbName: string, pbClient: PocketBase, logger: Logger) {
|
||
this.dbName = dbName
|
||
this.pbClient = pbClient
|
||
this.logger = logger
|
||
}
|
||
|
||
/**
|
||
* 错误处理包装函数,捕获并记录 PocketBase 操作中的错误
|
||
*
|
||
* @template R - 返回结果类型
|
||
* @param fn - 需要执行的异步函数
|
||
* @returns 成功时返回执行结果,失败时返回 null 并记录错误
|
||
*/
|
||
protected managePbError = async <R>(fn: () => Promise<R>) => {
|
||
try {
|
||
return await fn()
|
||
} catch (err: any) {
|
||
this.logger.error(`pocketbase error: ${err.message}`)
|
||
return null
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 创建新记录
|
||
*
|
||
* @param data - 要创建的记录数据
|
||
* @returns 成功时返回创建的记录,失败时返回 null
|
||
*
|
||
* @example
|
||
* ```typescript
|
||
* const record = await pbTool.create({ name: "示例", value: 100 });
|
||
* ```
|
||
*/
|
||
public create = async (data: Partial<T>) => {
|
||
return this.managePbError<T>(() =>
|
||
this.pbClient.collection(this.dbName).create(data)
|
||
)
|
||
}
|
||
|
||
/**
|
||
* 获取指定 ID 的记录
|
||
*
|
||
* @template R - 返回记录的类型,默认为 T
|
||
* @param id - 记录 ID
|
||
* @param options - 获取记录的选项参数
|
||
* @returns 成功时返回查询到的记录,失败时返回 null
|
||
*
|
||
* @example
|
||
* ```typescript
|
||
* const record = await pbTool.get("record123", { expand: "relation_field" });
|
||
* ```
|
||
*/
|
||
public get = async <R extends T = T>(id: string, options?: RecordOptions) => {
|
||
return this.managePbError<R>(() =>
|
||
this.pbClient.collection(this.dbName).getOne(id, options)
|
||
)
|
||
}
|
||
|
||
/**
|
||
* 更新指定 ID 的记录
|
||
*
|
||
* @template R - 返回记录的类型,默认为 T
|
||
* @param id - 记录 ID
|
||
* @param data - 更新的数据
|
||
* @param options - 更新记录的选项参数
|
||
* @returns 成功时返回更新后的记录,失败时返回 null
|
||
*
|
||
* @example
|
||
* ```typescript
|
||
* const updatedRecord = await pbTool.update("record123", { name: "新名称" });
|
||
* ```
|
||
*/
|
||
public update = async <R extends T = T>(
|
||
id: string,
|
||
data: Partial<T>,
|
||
options?: RecordOptions
|
||
) => {
|
||
return this.managePbError<R>(() =>
|
||
this.pbClient.collection(this.dbName).update(id, data, options)
|
||
)
|
||
}
|
||
|
||
/**
|
||
* 删除指定 ID 的记录
|
||
*
|
||
* @param id - 要删除的记录 ID
|
||
* @param options - 删除记录的选项参数
|
||
* @returns 成功时返回 true,失败时返回 null
|
||
*
|
||
* @example
|
||
* ```typescript
|
||
* const result = await pbTool.delete("record123");
|
||
* ```
|
||
*/
|
||
public delete = async (id: string, options?: CommonOptions) => {
|
||
return this.managePbError(() =>
|
||
this.pbClient.collection(this.dbName).delete(id, options)
|
||
)
|
||
}
|
||
|
||
/**
|
||
* 获取记录列表
|
||
*
|
||
* @template R - 返回记录的类型,默认为 T
|
||
* @param options - 列表查询选项,可包含排序、过滤和扩展等参数
|
||
* @returns 成功时返回记录数组,失败时返回 null
|
||
*
|
||
* @example
|
||
* ```typescript
|
||
* const records = await pbTool.list({
|
||
* sort: "-created",
|
||
* filter: "active=true"
|
||
* });
|
||
* ```
|
||
*/
|
||
public list = async <R extends T = T>(options?: RecordFullListOptions) => {
|
||
return this.managePbError<R[]>(() =>
|
||
this.pbClient.collection(this.dbName).getFullList(options)
|
||
)
|
||
}
|
||
|
||
/**
|
||
* 获取符合过滤条件的第一条记录
|
||
*
|
||
* @template R - 返回记录的类型,默认为 T
|
||
* @param filter - 过滤条件
|
||
* @param options - 查询选项
|
||
* @returns 成功时返回第一条匹配记录,失败时返回 null
|
||
*
|
||
* @example
|
||
* ```typescript
|
||
* const user = await pbTool.getFirstOne("email='test@example.com'");
|
||
* ```
|
||
*/
|
||
public getFirstOne = async <R extends T = T>(
|
||
filter: string,
|
||
options?: RecordListOptions
|
||
) => {
|
||
return this.managePbError<R>(() =>
|
||
this.pbClient.collection(this.dbName).getFirstListItem(filter, options)
|
||
)
|
||
}
|
||
}
|
||
|
||
export default PbToolBase
|