mirror of
https://github.com/hellodigua/ChatLab.git
synced 2026-10-25 17:54:34 +08:00
feat(core): init @openchatlab/core package with abstract interfaces
Phase 1.1 of CLI/Web transformation: create the platform-agnostic core package with DatabaseAdapter, PathProvider, NotificationBus interfaces and query filter utilities extracted from worker/core/dbCore.ts.
This commit is contained in:
1 parent
24bdcc0a0e
commit
d1e160fe23
9 files changed
+217
-1
No files matched your search
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "@openchatlab/core",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"description": "ChatLab 平台无关的共享核心:抽象接口、查询逻辑、分析算法",
|
||||
"main": "./src/index.ts",
|
||||
"types": "./src/index.ts"
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* @openchatlab/core
|
||||
*
|
||||
* 平台无关的 ChatLab 共享核心。
|
||||
* 提供抽象接口、查询工具、分析算法,不依赖任何特定运行时(Electron / Node / 浏览器)。
|
||||
*/
|
||||
|
||||
// 抽象接口
|
||||
export type {
|
||||
DatabaseAdapter,
|
||||
PreparedStatement,
|
||||
RunResult,
|
||||
PathProvider,
|
||||
NotificationBus,
|
||||
NotificationPayload,
|
||||
} from './interfaces'
|
||||
|
||||
// 查询工具
|
||||
export { buildTimeFilter, buildSystemMessageFilter } from './query'
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* 数据库适配器抽象接口
|
||||
*
|
||||
* 定义平台无关的 SQLite 数据库访问契约。
|
||||
* 接口设计贴合 better-sqlite3 API(因为现有查询代码基于此编写),
|
||||
* sql.js 等其他实现只需编写薄适配层。
|
||||
*/
|
||||
|
||||
/**
|
||||
* 预编译语句接口
|
||||
*/
|
||||
export interface PreparedStatement {
|
||||
/**
|
||||
* 执行查询并返回第一行结果
|
||||
*/
|
||||
get(...params: unknown[]): Record<string, unknown> | undefined
|
||||
|
||||
/**
|
||||
* 执行查询并返回所有行
|
||||
*/
|
||||
all(...params: unknown[]): Record<string, unknown>[]
|
||||
|
||||
/**
|
||||
* 执行写操作(INSERT / UPDATE / DELETE)
|
||||
*/
|
||||
run(...params: unknown[]): RunResult
|
||||
}
|
||||
|
||||
/**
|
||||
* 写操作的返回结果
|
||||
*/
|
||||
export interface RunResult {
|
||||
changes: number
|
||||
lastInsertRowid?: number | bigint
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据库适配器接口
|
||||
*
|
||||
* 调用方通过此接口操作 SQLite 数据库,不关心底层使用
|
||||
* better-sqlite3(Node.js)还是 sql.js(浏览器 WASM)。
|
||||
*/
|
||||
export interface DatabaseAdapter {
|
||||
/**
|
||||
* 执行原始 SQL(不返回结果,用于 DDL 或批量语句)
|
||||
*/
|
||||
exec(sql: string): void
|
||||
|
||||
/**
|
||||
* 预编译 SQL 语句
|
||||
*/
|
||||
prepare(sql: string): PreparedStatement
|
||||
|
||||
/**
|
||||
* 在事务中执行操作
|
||||
*/
|
||||
transaction<T>(fn: () => T): T
|
||||
|
||||
/**
|
||||
* 关闭数据库连接
|
||||
*/
|
||||
close(): void
|
||||
|
||||
/**
|
||||
* 数据库是否处于只读模式
|
||||
*/
|
||||
readonly?: boolean
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export type { DatabaseAdapter, PreparedStatement, RunResult } from './database-adapter'
|
||||
export type { PathProvider } from './path-provider'
|
||||
export type { NotificationBus, NotificationPayload } from './notification-bus'
|
||||
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* 通知总线抽象接口
|
||||
*
|
||||
* 统一不同运行环境下的异步事件通知方式:
|
||||
* - Electron:通过 BrowserWindow.webContents.send(IPC)通知前端
|
||||
* - Node 独立运行:通过 EventEmitter 或 SSE 通知消费者
|
||||
* - 浏览器:通过 postMessage / CustomEvent 通知 UI
|
||||
*/
|
||||
|
||||
export type NotificationPayload = Record<string, unknown>
|
||||
|
||||
export interface NotificationBus {
|
||||
/** 发送通知事件 */
|
||||
emit(event: string, payload?: NotificationPayload): void
|
||||
|
||||
/** 监听通知事件 */
|
||||
on(event: string, handler: (payload?: NotificationPayload) => void): void
|
||||
|
||||
/** 取消监听 */
|
||||
off(event: string, handler: (payload?: NotificationPayload) => void): void
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* 路径提供器抽象接口
|
||||
*
|
||||
* 统一不同运行环境下的目录路径获取方式:
|
||||
* - Electron:通过 app.getPath('userData') 驱动
|
||||
* - Node 独立运行:通过 ~/.chatlab/ 或 CHATLAB_DATA_DIR 环境变量驱动
|
||||
*
|
||||
* 子目录结构在所有环境下保持一致:
|
||||
* {dataDir}/
|
||||
* ├── databases/ 聊天记录 SQLite 文件({uuid}.db)
|
||||
* ├── ai/ AI 对话历史、LLM 配置
|
||||
* ├── settings/ 用户设置
|
||||
* ├── cache/ 派生数据缓存(可再生)
|
||||
* ├── temp/ 临时文件
|
||||
* └── logs/ 日志
|
||||
*/
|
||||
export interface PathProvider {
|
||||
/** 数据根目录 */
|
||||
getDataDir(): string
|
||||
|
||||
/** 数据库文件目录(存放 {uuid}.db) */
|
||||
getDatabaseDir(): string
|
||||
|
||||
/** AI 数据目录(对话历史、LLM 配置) */
|
||||
getAiDataDir(): string
|
||||
|
||||
/** 设置目录 */
|
||||
getSettingsDir(): string
|
||||
|
||||
/** 缓存目录(存放可再生的派生数据) */
|
||||
getCacheDir(): string
|
||||
|
||||
/** 临时文件目录 */
|
||||
getTempDir(): string
|
||||
|
||||
/** 日志目录 */
|
||||
getLogsDir(): string
|
||||
|
||||
/** 下载目录(导出文件的默认保存位置) */
|
||||
getDownloadsDir(): string
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* SQL 查询过滤条件构建工具
|
||||
*
|
||||
* 平台无关的 WHERE 子句构建器,供所有查询模块复用。
|
||||
*/
|
||||
|
||||
import type { TimeFilter } from '@openchatlab/shared-types'
|
||||
|
||||
/**
|
||||
* 构建时间过滤 WHERE 子句
|
||||
* @param filter 时间过滤器(包含时间范围和成员筛选)
|
||||
* @param tableAlias 表别名,用于多表 JOIN 场景避免列名歧义(如 'msg')
|
||||
*/
|
||||
export function buildTimeFilter(
|
||||
filter?: TimeFilter,
|
||||
tableAlias?: string
|
||||
): { clause: string; params: (number | string)[] } {
|
||||
const conditions: string[] = []
|
||||
const params: (number | string)[] = []
|
||||
|
||||
const tsColumn = tableAlias ? `${tableAlias}.ts` : 'ts'
|
||||
const senderIdColumn = tableAlias ? `${tableAlias}.sender_id` : 'sender_id'
|
||||
|
||||
if (filter?.startTs !== undefined) {
|
||||
conditions.push(`${tsColumn} >= ?`)
|
||||
params.push(filter.startTs)
|
||||
}
|
||||
if (filter?.endTs !== undefined) {
|
||||
conditions.push(`${tsColumn} <= ?`)
|
||||
params.push(filter.endTs)
|
||||
}
|
||||
if (filter?.memberId !== undefined && filter?.memberId !== null) {
|
||||
conditions.push(`${senderIdColumn} = ?`)
|
||||
params.push(filter.memberId)
|
||||
}
|
||||
|
||||
return {
|
||||
clause: conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : '',
|
||||
params,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建排除系统消息的过滤条件
|
||||
*/
|
||||
export function buildSystemMessageFilter(existingClause: string): string {
|
||||
const systemFilter = "COALESCE(m.account_name, '') != '系统消息'"
|
||||
|
||||
if (existingClause.includes('WHERE')) {
|
||||
return existingClause + ' AND ' + systemFilter
|
||||
} else {
|
||||
return ' WHERE ' + systemFilter
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { buildTimeFilter, buildSystemMessageFilter } from './filters'
|
||||
+2
-1
@@ -7,7 +7,8 @@
|
||||
"electron/preload/**/*",
|
||||
"electron/shared/**/*",
|
||||
"src/types/**/*",
|
||||
"packages/shared-types/**/*"
|
||||
"packages/shared-types/**/*",
|
||||
"packages/core/**/*"
|
||||
],
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
|
||||
Reference in new issue
Block a user