UNPKG

@agentkai/node

Version:

AgentKai的Node.js环境特定实现

202 lines (201 loc) 6.98 kB
import { StorageProvider } from '@agentkai/core'; import { platform } from '../platform'; /** * 文件系统存储实现 * 数据以JSON文件形式存储在指定目录 */ export class FileSystemStorage extends StorageProvider { /** * 创建文件系统存储 * @param basePath 数据存储的基础路径 * @param name 存储名称(用于日志) */ constructor(basePath = 'data', name = 'FileStorage') { super(basePath, name); Object.defineProperty(this, "fs", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "pathUtils", { enumerable: true, configurable: true, writable: true, value: void 0 }); this.fs = platform.fs; this.pathUtils = platform.path; this.ensureDirectoryExists(this.basePath); this.logger.info(`文件系统存储已初始化,路径: ${this.basePath}`); } /** * 保存数据 */ async saveData(data) { try { this.logger.debug(`保存数据 ID: ${data.id}`); const filePath = this.getFilePath(data.id); const jsonData = JSON.stringify(data, null, 2); await this.fs.writeFile(filePath, jsonData); this.logger.debug(`数据已保存到 ${filePath}`); } catch (error) { this.logger.error(`保存数据失败 ID: ${data.id}:`, error); throw error; } } /** * 获取数据 * @param id 数据ID * @returns 获取的数据,不存在则返回null */ async get(id) { try { this.logger.debug(`获取数据 ID: ${id}`); const filePath = this.getFilePath(id); if (!(await this.fs.exists(filePath))) { this.logger.debug(`数据不存在 ID: ${id}`); return null; } const rawData = await this.fs.readFile(filePath); return JSON.parse(rawData); } catch (error) { this.logger.error(`获取数据失败 ID: ${id}:`, error); throw error; } } /** * 删除数据 * @param id 数据ID */ async delete(id) { try { this.logger.debug(`删除数据 ID: ${id}`); const filePath = this.getFilePath(id); if (!(await this.fs.exists(filePath))) { this.logger.debug(`数据不存在,无需删除 ID: ${id}`); return; } await this.fs.unlink(filePath); this.logger.debug(`数据已删除 ID: ${id}`); } catch (error) { this.logger.error(`删除数据失败 ID: ${id}:`, error); throw error; } } /** * 列出所有数据 * @returns 所有数据的数组 */ async list() { try { this.logger.debug('列出所有数据'); // 确保目录存在 this.ensureDirectoryExists(this.basePath); // 读取目录中的所有文件 const files = await this.fs.readdir(this.basePath); const jsonFiles = files.filter((file) => file.endsWith('.json')); this.logger.debug(`找到 ${jsonFiles.length} 个数据文件`); // 读取所有文件内容 const dataPromises = jsonFiles.map(async (file) => { const filePath = this.pathUtils.join(this.basePath, file); const rawData = await this.fs.readFile(filePath); return JSON.parse(rawData); }); return await Promise.all(dataPromises); } catch (error) { this.logger.error('列出数据失败:', error); throw error; } } /** * 查询数据 * @param options 查询选项 * @returns 符合条件的数据数组 */ async query(options) { try { this.logger.debug('查询数据', { options }); // 获取所有数据 const allData = await this.list(); // 如果没有过滤条件,返回所有数据 if (!options.filter || Object.keys(options.filter).length === 0) { return allData; } // 根据过滤条件筛选数据 const filteredData = allData.filter((item) => { return Object.entries(options.filter || {}).every(([key, value]) => { // 处理嵌套属性,如 'metadata.type' if (key.includes('.')) { const parts = key.split('.'); let current = item; for (const part of parts) { if (current === undefined || current === null) { return false; } current = current[part]; } return current === value; } return item[key] === value; }); }); return filteredData; } catch (error) { this.logger.error('查询数据失败:', error); throw error; } } /** * 清空所有数据 */ async clear() { try { this.logger.warn('清空所有数据'); // 确保目录存在 this.ensureDirectoryExists(this.basePath); // 读取目录中的所有文件 const files = await this.fs.readdir(this.basePath); const jsonFiles = files.filter((file) => file.endsWith('.json')); // 删除所有JSON文件 for (const file of jsonFiles) { const filePath = this.pathUtils.join(this.basePath, file); await this.fs.unlink(filePath); this.logger.debug(`已删除文件: ${filePath}`); } this.logger.info(`已清空所有数据,共删除 ${jsonFiles.length} 个文件`); } catch (error) { this.logger.error('清空数据失败:', error); throw error; } } /** * 确保目录存在 */ async ensureDirectoryExists(dirPath) { try { if (!(await this.fs.exists(dirPath))) { this.logger.debug(`创建目录: ${dirPath}`); await this.fs.mkdir(dirPath, { recursive: true }); } } catch (error) { this.logger.error(`创建目录失败: ${dirPath}:`, error); throw error; } } /** * 获取文件路径 */ getFilePath(id) { // 清理ID,确保是安全的文件名 const safeId = id.replace(/[/\\?%*:|"<>]/g, '-'); return this.pathUtils.join(this.basePath, `${safeId}.json`); } }