UNPKG

pocketbase-tools

Version:

1 lines 29.7 kB
{"version":3,"file":"index.cjs","sources":["../src/utils/env.ts","../src/base/client.ts","../src/base/setup.ts","../src/utils/logger.ts","../src/utils/errorHandler.ts","../src/utils/useFiles.ts","../src/services/auth.action.ts","../src/services/product.action.ts","../src/services/user.action.ts","../src/index.ts","../src/services/profile.action.ts"],"sourcesContent":["/**\n * 安全获取环境变量\n * @param key 环境变量键名\n * @param defaultValue 可选默认值\n * @returns 环境变量值或默认值\n * @throws 当没有默认值且变量未设置时抛出错误\n */\nexport function getEnvVar(key: string, defaultValue?: string): string {\n // 浏览器环境 (Vite)\n if (typeof import.meta !== \"undefined\" && import.meta.env?.[key]) {\n return (import.meta.env[key] as string) || defaultValue!;\n }\n\n // Node.js 环境 (处理SSR场景)\n if (typeof process !== \"undefined\" && process.env?.[key]) {\n return process.env[key] || defaultValue!;\n }\n\n if (defaultValue !== undefined) return defaultValue;\n\n throw new Error(`[Config Error] 必需环境变量未配置: ${key}`);\n}\n\n/**\n * 验证必需环境变量\n */\nexport function validateEnvVars(requiredVars: string[]) {\n requiredVars.forEach(key => {\n try {\n getEnvVar(key);\n } catch (err: any) {\n console.warn(`[Env Warning] ${err.message}`);\n }\n });\n}\n","import PocketBase from \"pocketbase\";\nimport { getEnvVar } from \"../utils/env\";\n\n// 单例管理\nlet globalInstance: PocketBase | null = null;\nlet customInstance: PocketBase | null = null;\n\nfunction createPBClient(baseUrl: string): PocketBase {\n return new PocketBase(baseUrl);\n}\n\nfunction initGlobalInstance(): PocketBase {\n const baseUrl = getEnvVar(\"VITE_POCKETBASE_URL\", \"http://localhost:8090\");\n globalInstance = createPBClient(baseUrl);\n return globalInstance;\n}\n\n/**\n * 获取或创建 PocketBase 客户端\n * @param options 配置选项\n * - url: 指定服务地址创建新实例\n * - instance: 直接注入实例\n * - override: 是否强制覆盖现有实例 (默认false)\n */\nexport function usePBClient(options?: {\n url?: string;\n instance?: PocketBase;\n override?: boolean;\n}): PocketBase {\n // 强制重置实例\n if (options?.override) {\n if (options.instance) {\n customInstance = options.instance;\n return customInstance;\n }\n if (options.url) {\n customInstance = createPBClient(options.url);\n return customInstance;\n }\n resetPBInstances();\n }\n\n // 1. 使用传入的实例\n if (options?.instance) {\n if (!customInstance || options.override !== false) {\n customInstance = options.instance;\n }\n return customInstance;\n }\n\n // 2. 使用传入的URL\n if (options?.url) {\n if (!customInstance || options.override !== false) {\n customInstance = createPBClient(options.url);\n }\n return customInstance;\n }\n\n // 3. 返回现有实例\n if (customInstance) return customInstance;\n if (globalInstance) return globalInstance;\n\n // 4. 初始化默认实例\n return initGlobalInstance();\n}\n\nexport function resetPBInstances() {\n globalInstance = null;\n customInstance = null;\n}\n","import { usePBClient } from \"./client\";\n\n// 导出动态集合获取函数\nconst getCollect = (name: string) => usePBClient().collection(name);\n\n// 预定义的集合实例\nconst filesCollect = getCollect(\"files\");\nconst productCollect = getCollect(\"products\");\nconst profileCollect = getCollect(\"profile\");\n\n// 内置\nconst userCollect = getCollect(\"users\");\nconst superusersCollect = getCollect(\"_superusers\");\n\nexport {\n getCollect,\n filesCollect,\n productCollect,\n profileCollect,\n superusersCollect,\n userCollect,\n};\n","// utils/logger.ts\nexport class Logger {\n private enableConsole: boolean;\n\n constructor(enableConsole?: boolean) {\n // 默认: 非生产环境输出日志,生产环境不输出\n this.enableConsole =\n typeof enableConsole === \"boolean\"\n ? enableConsole\n : process.env.NODE_ENV !== \"production\";\n }\n\n success(message: string, data?: any) {\n if (this.enableConsole) {\n console.log(`✅ 成功: ${message}`, data ? JSON.stringify(data) : \"\");\n }\n }\n\n error(message: string, error?: any) {\n if (this.enableConsole) {\n console.error(`❌ 错误: ${message}`, error ? JSON.stringify(error) : \"\");\n }\n }\n\n warn(message: string, data?: any) {\n if (this.enableConsole) {\n console.warn(`⚠️ 警告: ${message}`, data ? JSON.stringify(data) : \"\");\n }\n }\n\n info(message: string, data?: any) {\n if (this.enableConsole) {\n console.info(`ℹ️ 信息: ${message}`, data ? JSON.stringify(data) : \"\");\n }\n }\n}\n\n// 默认导出: 根据 NODE_ENV 自动判断\nexport const logger = new Logger();\n","import { logger } from \"./logger\";\n\nexport interface ApiError {\n code: string;\n message: string;\n details?: Record<string, any>;\n}\n\nexport class ErrorHandler {\n public handle(error: any): void {\n const apiError: ApiError = this.parseError(error);\n logger.error(apiError.message, apiError);\n }\n\n private parseError(error: any): ApiError {\n if (error.response) {\n return {\n code: error.response.code || \"UNKNOWN_ERROR\",\n message: error.response.message || \"未知错误\",\n details: error.response.data,\n };\n }\n\n return {\n code: \"UNKNOWN_ERROR\",\n message: error.message || \"发生未知错误\",\n details: error,\n };\n }\n}\n\n/**\n * 封装错误处理逻辑\n * @param action 当前执行的动作描述,用于日志输出\n * @param callback 要执行的操作\n * @returns 成功返回结果,失败返回 null\n */\nexport const withErrorHandling = async <T>(\n action: string,\n callback: () => Promise<T>,\n): Promise<T | null> => {\n try {\n const result = await callback();\n logger.success(action, result);\n return result;\n } catch (error: any) {\n const message = error.response?.data?.message || error.message;\n logger.error(action, message);\n return null;\n }\n};\n","import { RecordModel } from \"pocketbase\";\nimport { usePBClient } from \"../base/client\";\n\ninterface IFilesAPI {\n /**\n * 获取文件访问令牌\n * @returns Promise<string> 返回文件访问令牌\n */\n getTokenPayload(): Promise<string>;\n /**\n * 获取指定 record 下文件的下载 URL\n * @param record RecordModel 记录\n * @param fileFiled 需要下载的文件字段\n * @returns url 文件下载 URL\n */\n getAbsoluteURL(record: RecordModel, fileFiled: string): string;\n}\n\nconst getInstance = () => usePBClient();\n\nexport const useFiles: IFilesAPI = {\n getTokenPayload: async (): Promise<string> => {\n return await getInstance().files.getToken();\n },\n getAbsoluteURL: (record: RecordModel, fileFiled: string): string => {\n return getInstance().files.getURL(record, fileFiled);\n },\n};\n","import PocketBase, { RecordAuthResponse, RecordModel } from \"pocketbase\";\nimport { usePBClient } from \"../base/client\";\nimport { logger } from \"../utils\";\nimport { userCollect } from \"../base/setup\"; // Keep userCollect for verify function\n\nexport type Role = \"admin\" | \"user\";\n\ntype AuthType = RecordAuthResponse<RecordModel>;\ntype PromiseAuth = Promise<AuthType>;\n\nexport interface UserLogin {\n email?: string;\n username?: string;\n password?: string;\n}\n\nexport interface AuthActions {\n login: (\n role: Role,\n account: UserLogin,\n clientOptions?: { url?: string; instance?: PocketBase },\n ) => PromiseAuth;\n logout: () => void;\n\n refresh: (role: Role) => PromiseAuth;\n verify: (email: string) => Promise<boolean>;\n}\n\n// 常量定义\nconst AUTH_SUCCESS = \"认证成功\";\nconst LOGOUT_SUCCESS = \"已登出\";\nconst REFRESH_SUCCESS = \"获取信息成功\";\nconst VERIFY_EMAIL = \"验证邮箱\";\n\n// 日志记录辅助函数\nconst logSuccess = (action: string, message: string, data?: any) =>\n logger.success(`${action} ${message}`, data);\n\n// 获取 PocketBase 客户端实例\nconst getPBClient = (options?: { url?: string; instance?: PocketBase }) =>\n usePBClient(options);\n\n// 获取正确的集合名称\nconst getCollectionName = (role: Role) =>\n role === \"admin\" ? \"_superusers\" : \"users\";\n\n// 获取正确的标识符字段\nconst getIdentifierField = (role: Role) =>\n role === \"admin\" ? \"email\" : \"username\";\n\n// 登录函数\nconst login = async (\n role: Role,\n account: UserLogin,\n clientOptions?: { url?: string; instance?: PocketBase },\n): PromiseAuth => {\n const { password } = account;\n if (!password) throw new Error(\"缺少密码\");\n\n const pb = getPBClient(clientOptions); // Use the provided client options\n const collectionName = getCollectionName(role); // Get the collection name\n const identifierField = getIdentifierField(role);\n const identifier = account[identifierField];\n\n if (!identifier)\n throw new Error(`缺少${identifierField === \"email\" ? \"邮箱\" : \"用户名\"}`);\n\n // Use the specific PocketBase instance for authentication\n const authData = await pb\n .collection(collectionName)\n .authWithPassword(identifier, password);\n logSuccess(role, AUTH_SUCCESS);\n return authData;\n};\n\n// 登出函数\nconst logout = (): void => {\n const pb = getPBClient();\n if (pb.authStore.isValid) {\n pb.authStore.clear();\n }\n logSuccess(\"\", LOGOUT_SUCCESS);\n};\n\n// 刷新认证信息函数\nconst refresh = async (\n role: Role,\n clientOptions?: { url?: string; instance?: PocketBase },\n): PromiseAuth => {\n const pb = getPBClient(clientOptions);\n const collectionName = getCollectionName(role);\n const data = await pb.collection(collectionName).authRefresh();\n logSuccess(role, REFRESH_SUCCESS, data);\n return data;\n};\n\n// 邮箱验证函数\nconst verify = async (email: string): Promise<boolean> => {\n const result = await userCollect.requestVerification(email);\n logSuccess(email, VERIFY_EMAIL);\n return result;\n};\n\n// 实现接口\nexport const useAuth: AuthActions = {\n login,\n logout,\n refresh,\n verify,\n};\n","import { productCollect } from \"../base/setup\";\nimport { Product } from \"../types\";\nimport { logger, withErrorHandling } from \"../utils\";\n\nfunction toProduct(record: any): Product {\n return {\n id: record.id,\n title: record.title,\n desc: record.desc,\n img: record.img,\n video: record.video,\n addtime: record.addtime,\n created: record.created,\n updated: record.updated,\n };\n}\n\n/**\n * 添加产品\n */\nexport async function addProduct(\n titleOrProduct: string | Partial<Product>,\n desc?: string,\n img?: string,\n video?: string,\n): Promise<Product | null> {\n return withErrorHandling(\"添加产品\", async () => {\n let productData: Partial<Product>;\n if (typeof titleOrProduct === \"object\") {\n productData = titleOrProduct;\n } else {\n productData = {\n title: titleOrProduct,\n desc: desc || \"\",\n img: img || \"\",\n video: video || \"\",\n addtime: new Date().toISOString(),\n };\n }\n const result = await productCollect.create(productData);\n logger.success(\"添加产品成功\", result);\n return toProduct(result);\n });\n}\n\n/**\n * 更新产品\n */\nexport async function updateProduct(\n id: string,\n updatedFields: Partial<Product>,\n): Promise<Product | null> {\n return withErrorHandling(`更新产品 (ID: ${id})`, async () => {\n const updatedRecord = await productCollect.update(id, updatedFields);\n logger.success(`产品更新成功: ${updatedRecord.title}`);\n return toProduct(updatedRecord);\n });\n}\n\n/**\n * 创建 products 表结构\n */\nexport async function createProductsCollection() {\n return withErrorHandling(\"创建 products 表\", async () => {\n const collection = await productCollect.client.collections.create({\n name: \"products\",\n type: \"base\",\n listRule: null,\n viewRule: null,\n createRule: \"\",\n updateRule: \"\",\n deleteRule: \"\",\n fields: [\n {\n name: \"title\",\n type: \"text\",\n required: true,\n },\n {\n name: \"desc\",\n type: \"text\",\n required: false,\n },\n {\n name: \"images\",\n type: \"file\",\n required: false,\n maxSelect: 5,\n maxSize: 5 * 1024 * 1024,\n mimeTypes: [\n \"image/png\",\n \"image/jpeg\",\n \"image/gif\",\n \"image/webp\",\n \"application/octet-stream\",\n ],\n protected: true,\n },\n {\n name: \"video\",\n type: \"file\",\n required: false,\n maxSelect: 1,\n maxSize: 100 * 1024 * 1024,\n mimeTypes: [\"video/mp4\", \"video/gif\"],\n protected: true,\n },\n {\n name: \"addtime\",\n type: \"date\",\n required: false,\n },\n ],\n });\n logger.success(\"products 表创建成功\", collection);\n return collection;\n });\n}\n\n/**\n * 删除产品\n */\nexport async function deleteProduct(id: string): Promise<boolean | null> {\n return withErrorHandling(`删除产品 (ID: ${id})`, async () => {\n await productCollect.delete(id);\n logger.success(`产品删除成功: ${id}`);\n return true;\n });\n}\n\n/**\n * 获取所有产品\n */\nexport async function getAllProducts(options?: {\n filter?: string;\n sort?: string;\n expand?: string[];\n}): Promise<Product[] | null> {\n return withErrorHandling(\"获取所有产品列表\", async () => {\n const records = await productCollect.getFullList({\n filter: options?.filter,\n sort: options?.sort || undefined,\n expand: options?.expand?.join(\",\"),\n });\n logger.success(`成功获取到 ${records.length} 个产品`);\n return records.map(toProduct);\n });\n}\n\n/**\n * 获取单个产品 by ID\n */\nexport async function getProductById(id: string): Promise<Product | null> {\n return withErrorHandling(`获取产品详情 (ID: ${id})`, async () => {\n const record = await productCollect.getOne(id);\n logger.success(`成功获取产品: ${record.title}`);\n return toProduct(record);\n });\n}\n","import { usePBClient } from \"../base/client\";\nimport { User, UserCreate, UserUpdate } from \"../types\";\nimport { logger, withErrorHandling } from \"../utils\";\n\nfunction toUser(record: any): User {\n // 自动映射所有 User 字段,防止遗漏,并为 undefined 字段提供默认值\n return {\n collectionId: record.collectionId ?? undefined,\n collectionName: record.collectionName ?? undefined,\n id: record.id ?? undefined,\n email: record.email ?? \"\",\n name: record.name ?? undefined,\n emailVisibility: record.emailVisibility ?? undefined,\n avatar: record.avatar ?? undefined,\n verified: record.verified ?? undefined,\n created: record.created ?? undefined,\n updated: record.updated ?? undefined,\n };\n}\n\n/**\n * 获取所有用户列表\n * @param options 可选过滤\n */\nexport async function getAllUsers(\n options: {\n filter?: string;\n sort?: string;\n expand?: string[];\n } = {},\n): Promise<User[] | null> {\n return withErrorHandling(\"获取所有用户列表\", async () => {\n const pb = usePBClient();\n const userCollect = pb.collection(\"users\");\n const users = await userCollect.getFullList({\n filter: options.filter,\n sort: options.sort || \"-created\",\n expand: options.expand?.join(\",\"),\n });\n logger.success(`成功获取用户列表`, {\n total: users.length,\n filter: options.filter,\n });\n return users.map(toUser);\n });\n}\n\n/**\n * 添加用户\n */\nexport async function addUser(user: Partial<UserCreate>): Promise<User | null> {\n return withErrorHandling(\"添加用户\", async () => {\n const pb = usePBClient();\n const userCollect = pb.collection(\"users\");\n const result = await userCollect.create(user);\n logger.success(\"添加用户成功\", result);\n return toUser(result);\n });\n}\n\n/**\n * 更新用户\n */\nexport async function updateUser(\n id: string,\n updatedFields: Partial<UserUpdate>,\n): Promise<User | null> {\n return withErrorHandling(\"更新用户\", async () => {\n const pb = usePBClient();\n const userCollect = pb.collection(\"users\");\n const updated = await userCollect.update(id, updatedFields);\n logger.success(\"用户更新成功\", updated);\n return toUser(updated);\n });\n}\n\n/**\n * 删除用户\n */\nexport async function deleteUser(id: string): Promise<boolean | null> {\n return withErrorHandling(\"删除用户\", async () => {\n const pb = usePBClient();\n const userCollect = pb.collection(\"users\");\n const deleted = await userCollect.delete(id);\n logger.success(\"用户删除成功\", deleted);\n return !!deleted;\n });\n}\n","import { usePBClient } from \"./base/client\";\n\n// 基础模块导出\nexport * from \"./base/client\";\nexport * from \"./base/setup\";\n\n// 类型定义导出\nexport * from \"./types\";\n\n// 工具函数导出\nexport * from \"./utils\";\n\n// 服务模块导出\nexport * from \"./services/auth.action\";\nexport * from \"./services/product.action\";\nexport * from \"./services/profile.action\";\nexport * from \"./services/user.action\";\n\n// const pb = usePBClient();\n\nexport default usePBClient();\n","import { usePBClient } from \"../base/client\";\nimport { profileCollect } from \"../base/setup\";\nimport { ProfileCollection } from \"../types\";\nimport { withErrorHandling } from \"../utils\";\n\n// 获取所有公司资料\nexport async function listAllCompanyProfiles() {\n return withErrorHandling(\"列出所有记录\", async () => {\n return await profileCollect.getFullList();\n });\n}\n\n// 检查 profile 表是否存在\nexport async function checkProfileCollectionExists() {\n return withErrorHandling(\"检查 profile 表是否存在\", async () => {\n const pb = usePBClient();\n const collections = await pb.collections.getFullList();\n return !!collections.find(collection => collection.name === \"profile\");\n });\n}\n\n// 创建 profile 表结构\nexport async function createProfileCollection() {\n return withErrorHandling(\"创建 profile 表结构\", async () => {\n const pb = usePBClient();\n return await pb.collections.create({\n name: \"profile\",\n type: \"base\",\n listRule: '@request.auth.id != \"\"',\n fields: [\n { name: \"companyName\", type: \"text\", required: true },\n { name: \"contactEmail\", type: \"text\", required: true },\n { name: \"contactPhone\", type: \"text\", required: true },\n { name: \"companyAddress\", type: \"text\", required: true },\n { name: \"allowRegistration\", type: \"bool\", required: true },\n ],\n });\n });\n}\n\n// 添加公司资料\nexport function addCompanyProfile(\n companyNameOrProfile: string | ProfileCollection,\n contactEmail?: string,\n contactPhone?: string,\n companyAddress?: string,\n allowRegistration?: boolean,\n) {\n return withErrorHandling(\"添加公司数据\", async () => {\n let profile: ProfileCollection;\n if (typeof companyNameOrProfile === \"object\") {\n profile = companyNameOrProfile;\n } else {\n profile = {\n companyName: companyNameOrProfile,\n contactEmail: contactEmail!,\n contactPhone: contactPhone!,\n companyAddress: companyAddress!,\n allowRegistration: allowRegistration!,\n };\n }\n return await profileCollect.create(profile);\n });\n}\n\n// 更新公司资料\nexport async function updateCompanyProfile(\n recordId: string,\n updatedFields: Partial<ProfileCollection>,\n) {\n return withErrorHandling(\"更新记录\", async () => {\n return await profileCollect.update(recordId, updatedFields);\n });\n}\n\n// 删除公司资料\nexport async function deleteCompanyProfile(recordId: string) {\n return withErrorHandling(\"删除记录\", async () => {\n return await profileCollect.delete(recordId);\n });\n}\n"],"names":["getEnvVar","key","defaultValue","url","document","require","pathToFileURL","__filename","href","_documentCurrentScript","tagName","toUpperCase","src","URL","baseURI","__vite_import_meta_env__","process","env","Error","globalInstance","customInstance","createPBClient","baseUrl","PocketBase","usePBClient","options","override","instance","resetPBInstances","initGlobalInstance","getCollect","name","collection","filesCollect","productCollect","profileCollect","userCollect","superusersCollect","Logger","constructor","enableConsole","this","NODE_ENV","success","message","data","error","warn","info","logger","withErrorHandling","async","action","callback","result","response","getInstance","useFiles","getTokenPayload","files","getToken","getAbsoluteURL","record","fileFiled","getURL","logSuccess","getPBClient","getCollectionName","role","useAuth","login","account","clientOptions","password","pb","collectionName","identifierField","getIdentifierField","identifier","authData","authWithPassword","logout","authStore","isValid","clear","refresh","authRefresh","verify","email","requestVerification","toProduct","id","title","desc","img","video","addtime","created","updated","toUser","collectionId","emailVisibility","avatar","verified","index","exports","ErrorHandler","handle","apiError","parseError","code","details","addCompanyProfile","companyNameOrProfile","contactEmail","contactPhone","companyAddress","allowRegistration","profile","companyName","create","addProduct","titleOrProduct","productData","Date","toISOString","addUser","user","checkProfileCollectionExists","collections","getFullList","find","createProductsCollection","client","type","listRule","viewRule","createRule","updateRule","deleteRule","fields","required","maxSelect","maxSize","mimeTypes","protected","createProfileCollection","default","deleteCompanyProfile","recordId","delete","deleteProduct","deleteUser","deleted","getAllProducts","records","filter","sort","expand","join","length","map","getAllUsers","users","total","getProductById","getOne","listAllCompanyProfiles","updateCompanyProfile","updatedFields","update","updateProduct","updatedRecord","updateUser","validateEnvVars","requiredVars","forEach","err"],"mappings":"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"}