Files
cursornew2026/extension_clean/out/utils/sqlite.js
ccdojox-crypto 73a71f198f 蜂鸟Pro v2.0.1 - 基础框架版本 (待完善)
## 当前状态
- 插件界面已完成重命名 (cursorpro → hummingbird)
- 双账号池 UI 已实现 (Auto/Pro 卡片)
- 后端已切换到 MySQL 数据库
- 添加了 Cursor 官方用量 API 文档

## 已知问题 (待修复)
1. 激活时检查账号导致无账号时激活失败
2. 未启用无感换号时不应获取账号
3. 账号用量模块不显示 (seamless 未启用时应隐藏)
4. 积分显示为 0 (后端未正确返回)
5. Auto/Pro 双密钥逻辑混乱,状态不同步
6. 账号添加后无自动分析功能

## 下一版本计划
- 重构数据模型,优化账号状态管理
- 实现 Cursor API 自动分析账号
- 修复激活流程,不依赖账号
- 启用无感时才分配账号
- 完善账号用量实时显示

## 文件说明
- docs/系统设计文档.md - 完整架构设计
- cursor 官方用量接口.md - Cursor API 文档
- 参考计费/ - Vibeviewer 开源项目参考

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 11:21:52 +08:00

177 lines
5.0 KiB
JavaScript

'use strict';
// ============================================
// 蜂鸟Pro SQLite Utils - 反混淆版本
// ============================================
Object.defineProperty(exports, "__esModule", { value: true });
const child_process = require('child_process');
const util = require('util');
const fs = require('fs');
const path = require('path');
const os = require('os');
const execAsync = util.promisify(child_process.exec);
/**
* 转义 SQL 字符串中的单引号
*/
function escapeSqlString(value) {
if (value === null || value === undefined) {
return '';
}
return String(value).replace(/'/g, "''");
}
/**
* 执行 SQLite 命令
*/
async function execSqlite(dbPath, sql) {
const isWindows = process.platform === 'win32';
try {
if (isWindows) {
// Windows: 直接使用 sqlite3 命令
const escapedSql = sql.replace(/"/g, '\\"');
const command = `sqlite3 "${dbPath}" "${escapedSql}"`;
const { stdout, stderr } = await execAsync(command, {
encoding: 'utf-8',
maxBuffer: 10 * 1024 * 1024
});
if (stderr && !stderr.includes('-- Loading')) {
console.warn('[SQLite] stderr:', stderr);
}
return stdout.trim();
} else {
// Unix/Mac: 使用临时文件避免命令行转义问题
const tmpFile = path.join(os.tmpdir(), 'cursor_sql_' + Date.now() + '.sql');
fs.writeFileSync(tmpFile, sql, 'utf-8');
try {
const command = `sqlite3 "${dbPath}" < "${tmpFile}"`;
const { stdout, stderr } = await execAsync(command, {
encoding: 'utf-8',
maxBuffer: 10 * 1024 * 1024,
shell: '/bin/bash'
});
if (stderr && !stderr.includes('-- Loading')) {
console.warn('[SQLite] stderr:', stderr);
}
return stdout.trim();
} finally {
try {
fs.unlinkSync(tmpFile);
} catch (e) {
// 忽略删除临时文件失败
}
}
}
} catch (error) {
// 检查是否是 sqlite3 不存在的错误
if (error.code === 'ENOENT' ||
error.message?.includes('not found') ||
error.message?.includes('not recognized')) {
throw new Error('sqlite3 命令未找到,请确保已安装 sqlite3');
}
throw error;
}
}
/**
* 从 SQLite 数据库读取值
*/
async function sqliteGet(dbPath, key) {
if (!fs.existsSync(dbPath)) {
console.warn('[SQLite] 数据库文件不存在:', dbPath);
return null;
}
try {
const sql = `SELECT value FROM ItemTable WHERE key = '${escapeSqlString(key)}';`;
const result = await execSqlite(dbPath, sql);
return result || null;
} catch (error) {
console.error('[SQLite] 读取失败:', error);
return null;
}
}
exports.sqliteGet = sqliteGet;
/**
* 向 SQLite 数据库写入值
*/
async function sqliteSet(dbPath, key, value) {
if (!fs.existsSync(dbPath)) {
console.warn('[SQLite] 数据库文件不存在:', dbPath);
return false;
}
try {
const sql = `INSERT OR REPLACE INTO ItemTable (key, value) VALUES ('${escapeSqlString(key)}', '${escapeSqlString(value)}');`;
await execSqlite(dbPath, sql);
return true;
} catch (error) {
console.error('[SQLite] 写入失败:', error);
return false;
}
}
exports.sqliteSet = sqliteSet;
/**
* 批量写入 SQLite 数据库
*/
async function sqliteSetBatch(dbPath, entries) {
if (!fs.existsSync(dbPath)) {
console.warn('[SQLite] 数据库文件不存在:', dbPath);
return false;
}
if (entries.length === 0) {
return true;
}
try {
const statements = entries.map(([key, value]) =>
`INSERT OR REPLACE INTO ItemTable (key, value) VALUES ('${escapeSqlString(key)}', '${escapeSqlString(value)}');`
);
const sql = 'BEGIN; ' + statements.join(' ') + ' COMMIT;';
await execSqlite(dbPath, sql);
return true;
} catch (error) {
console.error('[SQLite] 批量写入失败:', error);
return false;
}
}
exports.sqliteSetBatch = sqliteSetBatch;
/**
* 批量读取 SQLite 数据库
*/
async function sqliteGetBatch(dbPath, keys) {
const result = new Map();
if (!fs.existsSync(dbPath)) {
console.warn('[SQLite] 数据库文件不存在:', dbPath);
keys.forEach(key => result.set(key, null));
return result;
}
try {
for (const key of keys) {
const value = await sqliteGet(dbPath, key);
result.set(key, value);
}
return result;
} catch (error) {
console.error('[SQLite] 批量读取失败:', error);
keys.forEach(key => result.set(key, null));
return result;
}
}
exports.sqliteGetBatch = sqliteGetBatch;