aicodeswitch 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +176 -0
- package/bin/cli.js +29 -0
- package/bin/restart.js +232 -0
- package/bin/start.js +166 -0
- package/bin/stop.js +90 -0
- package/dist/server/auth.js +77 -0
- package/dist/server/database.js +480 -0
- package/dist/server/main.js +382 -0
- package/dist/server/proxy-server.js +889 -0
- package/dist/server/transformers/chunk-collector.js +39 -0
- package/dist/server/transformers/claude-openai.js +231 -0
- package/dist/server/transformers/openai-responses.js +392 -0
- package/dist/server/transformers/streaming.js +888 -0
- package/dist/types/index.js +2 -0
- package/dist/ui/assets/index-BN77E7-U.js +259 -0
- package/dist/ui/assets/index-CaNSVfpD.css +1 -0
- package/dist/ui/index.html +13 -0
- package/package.json +59 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.isAuthEnabled = isAuthEnabled;
|
|
7
|
+
exports.verifyAuthCode = verifyAuthCode;
|
|
8
|
+
exports.generateToken = generateToken;
|
|
9
|
+
exports.verifyToken = verifyToken;
|
|
10
|
+
exports.authMiddleware = authMiddleware;
|
|
11
|
+
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
12
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
13
|
+
const AUTH_CODE = process.env.AUTH || '';
|
|
14
|
+
const JWT_SECRET = process.env.JWT_SECRET || (AUTH_CODE ? crypto_1.default.createHash('sha256').update(AUTH_CODE).digest('hex') : '');
|
|
15
|
+
const TOKEN_EXPIRY = '7d'; // 7天有效期
|
|
16
|
+
/**
|
|
17
|
+
* 检查是否启用鉴权
|
|
18
|
+
*/
|
|
19
|
+
function isAuthEnabled() {
|
|
20
|
+
return AUTH_CODE.trim().length > 0;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* 验证鉴权码
|
|
24
|
+
*/
|
|
25
|
+
function verifyAuthCode(authCode) {
|
|
26
|
+
if (!isAuthEnabled()) {
|
|
27
|
+
return true; // 未启用鉴权,直接通过
|
|
28
|
+
}
|
|
29
|
+
return authCode === AUTH_CODE;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 生成 JWT Token
|
|
33
|
+
*/
|
|
34
|
+
function generateToken() {
|
|
35
|
+
const payload = {
|
|
36
|
+
authenticated: true,
|
|
37
|
+
};
|
|
38
|
+
return jsonwebtoken_1.default.sign(payload, JWT_SECRET, { expiresIn: TOKEN_EXPIRY });
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 验证 JWT Token
|
|
42
|
+
*/
|
|
43
|
+
function verifyToken(token) {
|
|
44
|
+
try {
|
|
45
|
+
jsonwebtoken_1.default.verify(token, JWT_SECRET);
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Express 中间件: 验证 JWT Token
|
|
54
|
+
*
|
|
55
|
+
* 如果未启用鉴权,直接放行
|
|
56
|
+
* 如果启用鉴权但 token 无效,返回 401
|
|
57
|
+
*/
|
|
58
|
+
function authMiddleware(req, res, next) {
|
|
59
|
+
// 如果未启用鉴权,直接放行
|
|
60
|
+
if (!isAuthEnabled()) {
|
|
61
|
+
next();
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
// 从 Authorization header 中提取 token
|
|
65
|
+
const authHeader = req.headers.authorization;
|
|
66
|
+
if (!authHeader || !authHeader.startsWith('Bearer ')) {
|
|
67
|
+
res.status(401).json({ error: 'Unauthorized: Missing or invalid token' });
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const token = authHeader.substring(7); // 移除 "Bearer " 前缀
|
|
71
|
+
if (verifyToken(token)) {
|
|
72
|
+
next();
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
res.status(401).json({ error: 'Unauthorized: Invalid or expired token' });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
12
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
13
|
+
var m = o[Symbol.asyncIterator], i;
|
|
14
|
+
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
15
|
+
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
16
|
+
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
17
|
+
};
|
|
18
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
19
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
20
|
+
};
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
exports.DatabaseManager = void 0;
|
|
23
|
+
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
|
|
24
|
+
const level_1 = require("level");
|
|
25
|
+
const path_1 = __importDefault(require("path"));
|
|
26
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
27
|
+
const crypto_js_1 = __importDefault(require("crypto-js"));
|
|
28
|
+
class DatabaseManager {
|
|
29
|
+
constructor(dataPath) {
|
|
30
|
+
Object.defineProperty(this, "db", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
configurable: true,
|
|
33
|
+
writable: true,
|
|
34
|
+
value: void 0
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(this, "logDb", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
configurable: true,
|
|
39
|
+
writable: true,
|
|
40
|
+
value: void 0
|
|
41
|
+
});
|
|
42
|
+
Object.defineProperty(this, "accessLogDb", {
|
|
43
|
+
enumerable: true,
|
|
44
|
+
configurable: true,
|
|
45
|
+
writable: true,
|
|
46
|
+
value: void 0
|
|
47
|
+
});
|
|
48
|
+
Object.defineProperty(this, "errorLogDb", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
configurable: true,
|
|
51
|
+
writable: true,
|
|
52
|
+
value: void 0
|
|
53
|
+
});
|
|
54
|
+
this.db = new better_sqlite3_1.default(path_1.default.join(dataPath, 'app.db'));
|
|
55
|
+
this.logDb = new level_1.Level(path_1.default.join(dataPath, 'logs'), { valueEncoding: 'json' });
|
|
56
|
+
this.accessLogDb = new level_1.Level(path_1.default.join(dataPath, 'access-logs'), { valueEncoding: 'json' });
|
|
57
|
+
this.errorLogDb = new level_1.Level(path_1.default.join(dataPath, 'error-logs'), { valueEncoding: 'json' });
|
|
58
|
+
}
|
|
59
|
+
initialize() {
|
|
60
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
61
|
+
this.createTables();
|
|
62
|
+
yield this.ensureDefaultConfig();
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
createTables() {
|
|
66
|
+
this.db.exec(`
|
|
67
|
+
CREATE TABLE IF NOT EXISTS vendors (
|
|
68
|
+
id TEXT PRIMARY KEY,
|
|
69
|
+
name TEXT NOT NULL,
|
|
70
|
+
description TEXT,
|
|
71
|
+
created_at INTEGER NOT NULL,
|
|
72
|
+
updated_at INTEGER NOT NULL
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
CREATE TABLE IF NOT EXISTS api_services (
|
|
76
|
+
id TEXT PRIMARY KEY,
|
|
77
|
+
vendor_id TEXT NOT NULL,
|
|
78
|
+
name TEXT NOT NULL,
|
|
79
|
+
api_url TEXT NOT NULL,
|
|
80
|
+
api_key TEXT NOT NULL,
|
|
81
|
+
timeout INTEGER,
|
|
82
|
+
source_type TEXT,
|
|
83
|
+
supported_models TEXT,
|
|
84
|
+
created_at INTEGER NOT NULL,
|
|
85
|
+
updated_at INTEGER NOT NULL,
|
|
86
|
+
FOREIGN KEY (vendor_id) REFERENCES vendors(id) ON DELETE CASCADE
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
CREATE TABLE IF NOT EXISTS routes (
|
|
90
|
+
id TEXT PRIMARY KEY,
|
|
91
|
+
name TEXT NOT NULL,
|
|
92
|
+
description TEXT,
|
|
93
|
+
target_type TEXT NOT NULL CHECK(target_type IN ('claude-code', 'codex')),
|
|
94
|
+
is_active INTEGER DEFAULT 0,
|
|
95
|
+
created_at INTEGER NOT NULL,
|
|
96
|
+
updated_at INTEGER NOT NULL
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
CREATE TABLE IF NOT EXISTS rules (
|
|
100
|
+
id TEXT PRIMARY KEY,
|
|
101
|
+
route_id TEXT NOT NULL,
|
|
102
|
+
content_type TEXT NOT NULL CHECK(content_type IN ('default', 'background', 'thinking', 'long-context', 'image-understanding')),
|
|
103
|
+
target_service_id TEXT NOT NULL,
|
|
104
|
+
target_model TEXT,
|
|
105
|
+
created_at INTEGER NOT NULL,
|
|
106
|
+
updated_at INTEGER NOT NULL,
|
|
107
|
+
FOREIGN KEY (route_id) REFERENCES routes(id) ON DELETE CASCADE,
|
|
108
|
+
FOREIGN KEY (target_service_id) REFERENCES api_services(id) ON DELETE CASCADE,
|
|
109
|
+
UNIQUE(route_id, content_type)
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
CREATE TABLE IF NOT EXISTS config (
|
|
113
|
+
key TEXT PRIMARY KEY,
|
|
114
|
+
value TEXT NOT NULL
|
|
115
|
+
);
|
|
116
|
+
`);
|
|
117
|
+
}
|
|
118
|
+
ensureDefaultConfig() {
|
|
119
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
120
|
+
const config = this.db.prepare('SELECT * FROM config WHERE key = ?').get('app_config');
|
|
121
|
+
if (!config) {
|
|
122
|
+
const defaultConfig = {
|
|
123
|
+
enableLogging: true,
|
|
124
|
+
logRetentionDays: 7,
|
|
125
|
+
maxLogSize: 1000,
|
|
126
|
+
apiKey: '',
|
|
127
|
+
};
|
|
128
|
+
this.db.prepare('INSERT INTO config (key, value) VALUES (?, ?)').run('app_config', JSON.stringify(defaultConfig));
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
// Vendor operations
|
|
133
|
+
getVendors() {
|
|
134
|
+
const rows = this.db.prepare('SELECT * FROM vendors ORDER BY created_at DESC').all();
|
|
135
|
+
return rows.map((row) => ({
|
|
136
|
+
id: row.id,
|
|
137
|
+
name: row.name,
|
|
138
|
+
description: row.description,
|
|
139
|
+
createdAt: row.created_at,
|
|
140
|
+
updatedAt: row.updated_at,
|
|
141
|
+
}));
|
|
142
|
+
}
|
|
143
|
+
createVendor(vendor) {
|
|
144
|
+
const id = crypto_1.default.randomUUID();
|
|
145
|
+
const now = Date.now();
|
|
146
|
+
this.db
|
|
147
|
+
.prepare('INSERT INTO vendors (id, name, description, created_at, updated_at) VALUES (?, ?, ?, ?, ?)')
|
|
148
|
+
.run(id, vendor.name, vendor.description || null, now, now);
|
|
149
|
+
return Object.assign(Object.assign({}, vendor), { id, createdAt: now, updatedAt: now });
|
|
150
|
+
}
|
|
151
|
+
updateVendor(id, vendor) {
|
|
152
|
+
const now = Date.now();
|
|
153
|
+
const result = this.db
|
|
154
|
+
.prepare('UPDATE vendors SET name = ?, description = ?, updated_at = ? WHERE id = ?')
|
|
155
|
+
.run(vendor.name, vendor.description || null, now, id);
|
|
156
|
+
return result.changes > 0;
|
|
157
|
+
}
|
|
158
|
+
deleteVendor(id) {
|
|
159
|
+
const result = this.db.prepare('DELETE FROM vendors WHERE id = ?').run(id);
|
|
160
|
+
return result.changes > 0;
|
|
161
|
+
}
|
|
162
|
+
// API Service operations
|
|
163
|
+
getAPIServices(vendorId) {
|
|
164
|
+
const query = vendorId
|
|
165
|
+
? 'SELECT * FROM api_services WHERE vendor_id = ? ORDER BY created_at DESC'
|
|
166
|
+
: 'SELECT * FROM api_services ORDER BY created_at DESC';
|
|
167
|
+
const stmt = vendorId ? this.db.prepare(query).bind(vendorId) : this.db.prepare(query);
|
|
168
|
+
const rows = stmt.all();
|
|
169
|
+
return rows.map((row) => ({
|
|
170
|
+
id: row.id,
|
|
171
|
+
vendorId: row.vendor_id,
|
|
172
|
+
name: row.name,
|
|
173
|
+
apiUrl: row.api_url,
|
|
174
|
+
apiKey: row.api_key,
|
|
175
|
+
timeout: row.timeout,
|
|
176
|
+
sourceType: row.source_type,
|
|
177
|
+
supportedModels: row.supported_models ? row.supported_models.split(',').map((model) => model.trim()).filter((model) => model.length > 0) : undefined,
|
|
178
|
+
createdAt: row.created_at,
|
|
179
|
+
updatedAt: row.updated_at,
|
|
180
|
+
}));
|
|
181
|
+
}
|
|
182
|
+
createAPIService(service) {
|
|
183
|
+
const id = crypto_1.default.randomUUID();
|
|
184
|
+
const now = Date.now();
|
|
185
|
+
this.db
|
|
186
|
+
.prepare('INSERT INTO api_services (id, vendor_id, name, api_url, api_key, timeout, source_type, supported_models, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)')
|
|
187
|
+
.run(id, service.vendorId, service.name, service.apiUrl, service.apiKey, service.timeout || null, service.sourceType || null, service.supportedModels ? service.supportedModels.join(',') : null, now, now);
|
|
188
|
+
return Object.assign(Object.assign({}, service), { id, createdAt: now, updatedAt: now });
|
|
189
|
+
}
|
|
190
|
+
updateAPIService(id, service) {
|
|
191
|
+
const now = Date.now();
|
|
192
|
+
const result = this.db
|
|
193
|
+
.prepare('UPDATE api_services SET name = ?, api_url = ?, api_key = ?, timeout = ?, source_type = ?, supported_models = ?, updated_at = ? WHERE id = ?')
|
|
194
|
+
.run(service.name, service.apiUrl, service.apiKey, service.timeout || null, service.sourceType || null, service.supportedModels ? service.supportedModels.join(',') : null, now, id);
|
|
195
|
+
return result.changes > 0;
|
|
196
|
+
}
|
|
197
|
+
deleteAPIService(id) {
|
|
198
|
+
const result = this.db.prepare('DELETE FROM api_services WHERE id = ?').run(id);
|
|
199
|
+
return result.changes > 0;
|
|
200
|
+
}
|
|
201
|
+
// Route operations
|
|
202
|
+
getRoutes() {
|
|
203
|
+
const rows = this.db.prepare('SELECT * FROM routes ORDER BY created_at DESC').all();
|
|
204
|
+
return rows.map((row) => ({
|
|
205
|
+
id: row.id,
|
|
206
|
+
name: row.name,
|
|
207
|
+
description: row.description,
|
|
208
|
+
targetType: row.target_type,
|
|
209
|
+
isActive: row.is_active === 1,
|
|
210
|
+
createdAt: row.created_at,
|
|
211
|
+
updatedAt: row.updated_at,
|
|
212
|
+
}));
|
|
213
|
+
}
|
|
214
|
+
createRoute(route) {
|
|
215
|
+
const id = crypto_1.default.randomUUID();
|
|
216
|
+
const now = Date.now();
|
|
217
|
+
this.db
|
|
218
|
+
.prepare('INSERT INTO routes (id, name, description, target_type, is_active, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)')
|
|
219
|
+
.run(id, route.name, route.description || null, route.targetType, route.isActive ? 1 : 0, now, now);
|
|
220
|
+
return Object.assign(Object.assign({}, route), { id, createdAt: now, updatedAt: now });
|
|
221
|
+
}
|
|
222
|
+
updateRoute(id, route) {
|
|
223
|
+
const now = Date.now();
|
|
224
|
+
const result = this.db
|
|
225
|
+
.prepare('UPDATE routes SET name = ?, description = ?, target_type = ?, updated_at = ? WHERE id = ?')
|
|
226
|
+
.run(route.name, route.description || null, route.targetType, now, id);
|
|
227
|
+
return result.changes > 0;
|
|
228
|
+
}
|
|
229
|
+
deleteRoute(id) {
|
|
230
|
+
const result = this.db.prepare('DELETE FROM routes WHERE id = ?').run(id);
|
|
231
|
+
return result.changes > 0;
|
|
232
|
+
}
|
|
233
|
+
activateRoute(id) {
|
|
234
|
+
const route = this.getRoutes().find(r => r.id === id);
|
|
235
|
+
if (route) {
|
|
236
|
+
this.db.prepare('UPDATE routes SET is_active = 0 WHERE target_type = ?').run(route.targetType);
|
|
237
|
+
const result = this.db.prepare('UPDATE routes SET is_active = 1 WHERE id = ?').run(id);
|
|
238
|
+
return result.changes > 0;
|
|
239
|
+
}
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
deactivateRoute(id) {
|
|
243
|
+
const result = this.db.prepare('UPDATE routes SET is_active = 0 WHERE id = ?').run(id);
|
|
244
|
+
return result.changes > 0;
|
|
245
|
+
}
|
|
246
|
+
// Rule operations
|
|
247
|
+
getRules(routeId) {
|
|
248
|
+
const query = routeId
|
|
249
|
+
? 'SELECT * FROM rules WHERE route_id = ? ORDER BY created_at DESC'
|
|
250
|
+
: 'SELECT * FROM rules ORDER BY created_at DESC';
|
|
251
|
+
const stmt = routeId ? this.db.prepare(query).bind(routeId) : this.db.prepare(query);
|
|
252
|
+
const rows = stmt.all();
|
|
253
|
+
return rows.map((row) => ({
|
|
254
|
+
id: row.id,
|
|
255
|
+
routeId: row.route_id,
|
|
256
|
+
contentType: row.content_type,
|
|
257
|
+
targetServiceId: row.target_service_id,
|
|
258
|
+
targetModel: row.target_model,
|
|
259
|
+
createdAt: row.created_at,
|
|
260
|
+
updatedAt: row.updated_at,
|
|
261
|
+
}));
|
|
262
|
+
}
|
|
263
|
+
createRule(route) {
|
|
264
|
+
const id = crypto_1.default.randomUUID();
|
|
265
|
+
const now = Date.now();
|
|
266
|
+
this.db
|
|
267
|
+
.prepare('INSERT INTO rules (id, route_id, content_type, target_service_id, target_model, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)')
|
|
268
|
+
.run(id, route.routeId, route.contentType, route.targetServiceId, route.targetModel || null, now, now);
|
|
269
|
+
return Object.assign(Object.assign({}, route), { id, createdAt: now, updatedAt: now });
|
|
270
|
+
}
|
|
271
|
+
updateRule(id, route) {
|
|
272
|
+
const now = Date.now();
|
|
273
|
+
const result = this.db
|
|
274
|
+
.prepare('UPDATE rules SET content_type = ?, target_service_id = ?, target_model = ?, updated_at = ? WHERE id = ?')
|
|
275
|
+
.run(route.contentType, route.targetServiceId, route.targetModel || null, now, id);
|
|
276
|
+
return result.changes > 0;
|
|
277
|
+
}
|
|
278
|
+
deleteRule(id) {
|
|
279
|
+
const result = this.db.prepare('DELETE FROM rules WHERE id = ?').run(id);
|
|
280
|
+
return result.changes > 0;
|
|
281
|
+
}
|
|
282
|
+
// Log operations
|
|
283
|
+
addLog(log) {
|
|
284
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
285
|
+
const id = crypto_1.default.randomUUID();
|
|
286
|
+
yield this.logDb.put(id, JSON.stringify(Object.assign(Object.assign({}, log), { id })));
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
getLogs() {
|
|
290
|
+
return __awaiter(this, arguments, void 0, function* (limit = 100, offset = 0) {
|
|
291
|
+
var _a, e_1, _b, _c;
|
|
292
|
+
const logs = [];
|
|
293
|
+
let count = 0;
|
|
294
|
+
try {
|
|
295
|
+
for (var _d = true, _e = __asyncValues(this.logDb.iterator({ reverse: true })), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
|
296
|
+
_c = _f.value;
|
|
297
|
+
_d = false;
|
|
298
|
+
const [, value] = _c;
|
|
299
|
+
if (count >= offset && logs.length < limit) {
|
|
300
|
+
logs.push(JSON.parse(value));
|
|
301
|
+
}
|
|
302
|
+
count++;
|
|
303
|
+
if (logs.length >= limit)
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
308
|
+
finally {
|
|
309
|
+
try {
|
|
310
|
+
if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
|
|
311
|
+
}
|
|
312
|
+
finally { if (e_1) throw e_1.error; }
|
|
313
|
+
}
|
|
314
|
+
return logs;
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
clearLogs() {
|
|
318
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
319
|
+
yield this.logDb.clear();
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
// Access log operations
|
|
323
|
+
addAccessLog(log) {
|
|
324
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
325
|
+
const id = crypto_1.default.randomUUID();
|
|
326
|
+
yield this.accessLogDb.put(id, JSON.stringify(Object.assign(Object.assign({}, log), { id })));
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
getAccessLogs() {
|
|
330
|
+
return __awaiter(this, arguments, void 0, function* (limit = 100, offset = 0) {
|
|
331
|
+
var _a, e_2, _b, _c;
|
|
332
|
+
const logs = [];
|
|
333
|
+
let count = 0;
|
|
334
|
+
try {
|
|
335
|
+
for (var _d = true, _e = __asyncValues(this.accessLogDb.iterator({ reverse: true })), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
|
336
|
+
_c = _f.value;
|
|
337
|
+
_d = false;
|
|
338
|
+
const [, value] = _c;
|
|
339
|
+
if (count >= offset && logs.length < limit) {
|
|
340
|
+
logs.push(JSON.parse(value));
|
|
341
|
+
}
|
|
342
|
+
count++;
|
|
343
|
+
if (logs.length >= limit)
|
|
344
|
+
break;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
348
|
+
finally {
|
|
349
|
+
try {
|
|
350
|
+
if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
|
|
351
|
+
}
|
|
352
|
+
finally { if (e_2) throw e_2.error; }
|
|
353
|
+
}
|
|
354
|
+
return logs;
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
clearAccessLogs() {
|
|
358
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
359
|
+
yield this.accessLogDb.clear();
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
// Error log operations
|
|
363
|
+
addErrorLog(log) {
|
|
364
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
365
|
+
const id = crypto_1.default.randomUUID();
|
|
366
|
+
yield this.errorLogDb.put(id, JSON.stringify(Object.assign(Object.assign({}, log), { id })));
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
getErrorLogs() {
|
|
370
|
+
return __awaiter(this, arguments, void 0, function* (limit = 100, offset = 0) {
|
|
371
|
+
var _a, e_3, _b, _c;
|
|
372
|
+
const logs = [];
|
|
373
|
+
let count = 0;
|
|
374
|
+
try {
|
|
375
|
+
for (var _d = true, _e = __asyncValues(this.errorLogDb.iterator({ reverse: true })), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
|
376
|
+
_c = _f.value;
|
|
377
|
+
_d = false;
|
|
378
|
+
const [, value] = _c;
|
|
379
|
+
if (count >= offset && logs.length < limit) {
|
|
380
|
+
logs.push(JSON.parse(value));
|
|
381
|
+
}
|
|
382
|
+
count++;
|
|
383
|
+
if (logs.length >= limit)
|
|
384
|
+
break;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
388
|
+
finally {
|
|
389
|
+
try {
|
|
390
|
+
if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
|
|
391
|
+
}
|
|
392
|
+
finally { if (e_3) throw e_3.error; }
|
|
393
|
+
}
|
|
394
|
+
return logs;
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
clearErrorLogs() {
|
|
398
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
399
|
+
yield this.errorLogDb.clear();
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
// Config operations
|
|
403
|
+
getConfig() {
|
|
404
|
+
const row = this.db.prepare('SELECT value FROM config WHERE key = ?').get('app_config');
|
|
405
|
+
return row ? JSON.parse(row.value) : null;
|
|
406
|
+
}
|
|
407
|
+
updateConfig(config) {
|
|
408
|
+
const result = this.db
|
|
409
|
+
.prepare('UPDATE config SET value = ? WHERE key = ?')
|
|
410
|
+
.run(JSON.stringify(config), 'app_config');
|
|
411
|
+
return result.changes > 0;
|
|
412
|
+
}
|
|
413
|
+
// Export/Import operations
|
|
414
|
+
exportData(password) {
|
|
415
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
416
|
+
const exportData = {
|
|
417
|
+
version: '1.0.0',
|
|
418
|
+
exportDate: Date.now(),
|
|
419
|
+
vendors: this.getVendors(),
|
|
420
|
+
apiServices: this.getAPIServices(),
|
|
421
|
+
routes: this.getRoutes(),
|
|
422
|
+
rules: this.getRules(),
|
|
423
|
+
config: this.getConfig(),
|
|
424
|
+
};
|
|
425
|
+
const jsonData = JSON.stringify(exportData);
|
|
426
|
+
const encrypted = crypto_js_1.default.AES.encrypt(jsonData, password).toString();
|
|
427
|
+
return encrypted;
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
importData(encryptedData, password) {
|
|
431
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
432
|
+
try {
|
|
433
|
+
const decrypted = crypto_js_1.default.AES.decrypt(encryptedData, password);
|
|
434
|
+
const jsonData = decrypted.toString(crypto_js_1.default.enc.Utf8);
|
|
435
|
+
const importData = JSON.parse(jsonData);
|
|
436
|
+
// Clear existing data
|
|
437
|
+
this.db.prepare('DELETE FROM rules').run();
|
|
438
|
+
this.db.prepare('DELETE FROM routes').run();
|
|
439
|
+
this.db.prepare('DELETE FROM api_services').run();
|
|
440
|
+
this.db.prepare('DELETE FROM vendors').run();
|
|
441
|
+
// Import vendors
|
|
442
|
+
for (const vendor of importData.vendors) {
|
|
443
|
+
this.db
|
|
444
|
+
.prepare('INSERT INTO vendors (id, name, description, created_at, updated_at) VALUES (?, ?, ?, ?, ?)')
|
|
445
|
+
.run(vendor.id, vendor.name, vendor.description || null, vendor.createdAt, vendor.updatedAt);
|
|
446
|
+
}
|
|
447
|
+
// Import API services
|
|
448
|
+
for (const service of importData.apiServices) {
|
|
449
|
+
this.db
|
|
450
|
+
.prepare('INSERT INTO api_services (id, vendor_id, name, api_url, api_key, timeout, source_type, supported_models, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)')
|
|
451
|
+
.run(service.id, service.vendorId, service.name, service.apiUrl, service.apiKey, service.timeout || null, service.sourceType || null, service.supportedModels ? service.supportedModels.join(',') : null, service.createdAt, service.updatedAt);
|
|
452
|
+
}
|
|
453
|
+
// Import routes
|
|
454
|
+
for (const route of importData.routes) {
|
|
455
|
+
this.db
|
|
456
|
+
.prepare('INSERT INTO routes (id, name, description, target_type, is_active, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?)')
|
|
457
|
+
.run(route.id, route.name, route.description || null, route.targetType, route.isActive ? 1 : 0, route.createdAt, route.updatedAt);
|
|
458
|
+
}
|
|
459
|
+
// Import rules
|
|
460
|
+
for (const rule of importData.rules) {
|
|
461
|
+
this.db
|
|
462
|
+
.prepare('INSERT INTO rules (id, route_id, content_type, target_service_id, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?)')
|
|
463
|
+
.run(rule.id, rule.routeId, rule.contentType || 'default', rule.targetServiceId, rule.createdAt, rule.updatedAt);
|
|
464
|
+
}
|
|
465
|
+
// Update config
|
|
466
|
+
this.updateConfig(importData.config);
|
|
467
|
+
return true;
|
|
468
|
+
}
|
|
469
|
+
catch (error) {
|
|
470
|
+
console.error('Import error:', error);
|
|
471
|
+
return false;
|
|
472
|
+
}
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
close() {
|
|
476
|
+
this.db.close();
|
|
477
|
+
this.logDb.close();
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
exports.DatabaseManager = DatabaseManager;
|