aicodeswitch 3.0.3 → 3.0.5
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 +1 -0
- package/dist/server/fs-database.js +246 -44
- package/dist/server/main.js +60 -21
- package/dist/server/proxy-server.js +247 -6
- package/dist/server/transformers/gemini.js +625 -0
- package/dist/server/transformers/streaming.js +563 -7
- package/dist/types/index.js +1 -0
- package/dist/ui/assets/{index-DgBQpyCC.js → index-DYkQE3fV.js} +81 -76
- package/dist/ui/index.html +1 -1
- package/package.json +1 -1
- package/schema/gemini.schema.md +11 -0
package/README.md
CHANGED
|
@@ -181,6 +181,16 @@ class FileSystemDatabaseManager {
|
|
|
181
181
|
writable: true,
|
|
182
182
|
value: 30
|
|
183
183
|
});
|
|
184
|
+
// Export/Import operations
|
|
185
|
+
/**
|
|
186
|
+
* 当前支持的导出数据版本
|
|
187
|
+
*/
|
|
188
|
+
Object.defineProperty(this, "CURRENT_EXPORT_VERSION", {
|
|
189
|
+
enumerable: true,
|
|
190
|
+
configurable: true,
|
|
191
|
+
writable: true,
|
|
192
|
+
value: '3.0.0'
|
|
193
|
+
});
|
|
184
194
|
this.dataPath = dataPath;
|
|
185
195
|
}
|
|
186
196
|
initialize() {
|
|
@@ -738,7 +748,7 @@ class FileSystemDatabaseManager {
|
|
|
738
748
|
const serviceIds = (vendor.services || []).map(s => s.id);
|
|
739
749
|
const rulesUsingServices = this.rules.filter(r => serviceIds.includes(r.targetServiceId));
|
|
740
750
|
if (rulesUsingServices.length > 0) {
|
|
741
|
-
throw new Error(`无法删除供应商:有 ${rulesUsingServices.length}
|
|
751
|
+
throw new Error(`无法删除供应商:有 ${rulesUsingServices.length} 个路由规则正在使用该供应商的服务`);
|
|
742
752
|
}
|
|
743
753
|
this.vendors.splice(index, 1);
|
|
744
754
|
yield this.saveVendors();
|
|
@@ -847,7 +857,7 @@ class FileSystemDatabaseManager {
|
|
|
847
857
|
// 检查是否有规则正在使用此服务
|
|
848
858
|
const rulesUsingService = this.rules.filter(r => r.targetServiceId === id);
|
|
849
859
|
if (rulesUsingService.length > 0) {
|
|
850
|
-
throw new Error(`无法删除服务:有 ${rulesUsingService.length}
|
|
860
|
+
throw new Error(`无法删除服务:有 ${rulesUsingService.length} 个路由规则正在使用此服务`);
|
|
851
861
|
}
|
|
852
862
|
vendor.services.splice(index, 1);
|
|
853
863
|
// 更新供应商的 updatedAt 时间
|
|
@@ -1362,23 +1372,153 @@ class FileSystemDatabaseManager {
|
|
|
1362
1372
|
return true;
|
|
1363
1373
|
});
|
|
1364
1374
|
}
|
|
1365
|
-
|
|
1375
|
+
/**
|
|
1376
|
+
* 验证供应商数据格式
|
|
1377
|
+
*/
|
|
1378
|
+
validateVendor(vendor, index) {
|
|
1379
|
+
if (!vendor || typeof vendor !== 'object') {
|
|
1380
|
+
return { valid: false, error: `供应商[${index}] 不是有效的对象` };
|
|
1381
|
+
}
|
|
1382
|
+
if (!vendor.id || typeof vendor.id !== 'string') {
|
|
1383
|
+
return { valid: false, error: `供应商[${index}] 缺少有效的 id 字段` };
|
|
1384
|
+
}
|
|
1385
|
+
if (!vendor.name || typeof vendor.name !== 'string') {
|
|
1386
|
+
return { valid: false, error: `供应商[${index}](${vendor.id}) 缺少有效的 name 字段` };
|
|
1387
|
+
}
|
|
1388
|
+
if (!Array.isArray(vendor.services)) {
|
|
1389
|
+
return { valid: false, error: `供应商[${index}](${vendor.id}) 的 services 不是数组` };
|
|
1390
|
+
}
|
|
1391
|
+
for (let i = 0; i < vendor.services.length; i++) {
|
|
1392
|
+
const service = vendor.services[i];
|
|
1393
|
+
if (!service || typeof service !== 'object') {
|
|
1394
|
+
return { valid: false, error: `供应商[${index}](${vendor.id}) 的服务[${i}] 不是有效的对象` };
|
|
1395
|
+
}
|
|
1396
|
+
if (!service.id || typeof service.id !== 'string') {
|
|
1397
|
+
return { valid: false, error: `供应商[${index}](${vendor.id}) 的服务[${i}] 缺少有效的 id 字段` };
|
|
1398
|
+
}
|
|
1399
|
+
if (!service.name || typeof service.name !== 'string') {
|
|
1400
|
+
return { valid: false, error: `供应商[${index}](${vendor.id}) 的服务[${i}] 缺少有效的 name 字段` };
|
|
1401
|
+
}
|
|
1402
|
+
if (!service.apiUrl || typeof service.apiUrl !== 'string') {
|
|
1403
|
+
return { valid: false, error: `供应商[${index}](${vendor.id}) 的服务[${i}] 缺少有效的 apiUrl 字段` };
|
|
1404
|
+
}
|
|
1405
|
+
if (!service.apiKey || typeof service.apiKey !== 'string') {
|
|
1406
|
+
return { valid: false, error: `供应商[${index}](${vendor.id}) 的服务[${i}] 缺少有效的 apiKey 字段` };
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
return { valid: true };
|
|
1410
|
+
}
|
|
1411
|
+
/**
|
|
1412
|
+
* 验证路由数据格式
|
|
1413
|
+
*/
|
|
1414
|
+
validateRoute(route, index) {
|
|
1415
|
+
if (!route || typeof route !== 'object') {
|
|
1416
|
+
return { valid: false, error: `路由[${index}] 不是有效的对象` };
|
|
1417
|
+
}
|
|
1418
|
+
if (!route.id || typeof route.id !== 'string') {
|
|
1419
|
+
return { valid: false, error: `路由[${index}] 缺少有效的 id 字段` };
|
|
1420
|
+
}
|
|
1421
|
+
if (!route.name || typeof route.name !== 'string') {
|
|
1422
|
+
return { valid: false, error: `路由[${index}](${route.id}) 缺少有效的 name 字段` };
|
|
1423
|
+
}
|
|
1424
|
+
if (!route.targetType || !['claude-code', 'codex'].includes(route.targetType)) {
|
|
1425
|
+
return { valid: false, error: `路由[${index}](${route.id}) 的 targetType 必须是 'claude-code' 或 'codex'` };
|
|
1426
|
+
}
|
|
1427
|
+
if (typeof route.isActive !== 'boolean') {
|
|
1428
|
+
return { valid: false, error: `路由[${index}](${route.id}) 的 isActive 必须是布尔值` };
|
|
1429
|
+
}
|
|
1430
|
+
return { valid: true };
|
|
1431
|
+
}
|
|
1432
|
+
/**
|
|
1433
|
+
* 验证规则数据格式
|
|
1434
|
+
*/
|
|
1435
|
+
validateRule(rule, index) {
|
|
1436
|
+
if (!rule || typeof rule !== 'object') {
|
|
1437
|
+
return { valid: false, error: `规则[${index}] 不是有效的对象` };
|
|
1438
|
+
}
|
|
1439
|
+
if (!rule.id || typeof rule.id !== 'string') {
|
|
1440
|
+
return { valid: false, error: `规则[${index}] 缺少有效的 id 字段` };
|
|
1441
|
+
}
|
|
1442
|
+
if (!rule.routeId || typeof rule.routeId !== 'string') {
|
|
1443
|
+
return { valid: false, error: `规则[${index}](${rule.id}) 缺少有效的 routeId 字段` };
|
|
1444
|
+
}
|
|
1445
|
+
if (!rule.targetServiceId || typeof rule.targetServiceId !== 'string') {
|
|
1446
|
+
return { valid: false, error: `规则[${index}](${rule.id}) 缺少有效的 targetServiceId 字段` };
|
|
1447
|
+
}
|
|
1448
|
+
const validContentTypes = ['default', 'background', 'thinking', 'long-context', 'image-understanding', 'model-mapping'];
|
|
1449
|
+
if (!rule.contentType || !validContentTypes.includes(rule.contentType)) {
|
|
1450
|
+
return { valid: false, error: `规则[${index}](${rule.id}) 的 contentType 无效` };
|
|
1451
|
+
}
|
|
1452
|
+
return { valid: true };
|
|
1453
|
+
}
|
|
1454
|
+
/**
|
|
1455
|
+
* 验证配置数据格式
|
|
1456
|
+
*/
|
|
1457
|
+
validateConfig(config) {
|
|
1458
|
+
if (!config || typeof config !== 'object') {
|
|
1459
|
+
return { valid: false, error: 'config 不是有效的对象' };
|
|
1460
|
+
}
|
|
1461
|
+
return { valid: true };
|
|
1462
|
+
}
|
|
1463
|
+
/**
|
|
1464
|
+
* 验证导出数据格式(严格校验)
|
|
1465
|
+
*/
|
|
1466
|
+
validateExportData(data) {
|
|
1467
|
+
if (!data || typeof data !== 'object') {
|
|
1468
|
+
return { valid: false, error: '数据不是有效的对象' };
|
|
1469
|
+
}
|
|
1470
|
+
// 检查必需字段是否存在
|
|
1471
|
+
if (!data.version || typeof data.version !== 'string') {
|
|
1472
|
+
return { valid: false, error: '缺少有效的 version 字段' };
|
|
1473
|
+
}
|
|
1474
|
+
// 检查版本是否匹配当前版本
|
|
1475
|
+
if (data.version !== this.CURRENT_EXPORT_VERSION) {
|
|
1476
|
+
return { valid: false, error: `数据版本 ${data.version} 与当前支持的版本 ${this.CURRENT_EXPORT_VERSION} 不匹配。请使用相同版本的系统导出数据。` };
|
|
1477
|
+
}
|
|
1478
|
+
if (!data.exportDate || typeof data.exportDate !== 'number') {
|
|
1479
|
+
return { valid: false, error: '缺少有效的 exportDate 字段' };
|
|
1480
|
+
}
|
|
1481
|
+
// 检查 vendors
|
|
1482
|
+
if (!Array.isArray(data.vendors)) {
|
|
1483
|
+
return { valid: false, error: 'vendors 不是数组' };
|
|
1484
|
+
}
|
|
1485
|
+
for (let i = 0; i < data.vendors.length; i++) {
|
|
1486
|
+
const result = this.validateVendor(data.vendors[i], i);
|
|
1487
|
+
if (!result.valid)
|
|
1488
|
+
return result;
|
|
1489
|
+
}
|
|
1490
|
+
// 检查 routes
|
|
1491
|
+
if (!Array.isArray(data.routes)) {
|
|
1492
|
+
return { valid: false, error: 'routes 不是数组' };
|
|
1493
|
+
}
|
|
1494
|
+
for (let i = 0; i < data.routes.length; i++) {
|
|
1495
|
+
const result = this.validateRoute(data.routes[i], i);
|
|
1496
|
+
if (!result.valid)
|
|
1497
|
+
return result;
|
|
1498
|
+
}
|
|
1499
|
+
// 检查 rules
|
|
1500
|
+
if (!Array.isArray(data.rules)) {
|
|
1501
|
+
return { valid: false, error: 'rules 不是数组' };
|
|
1502
|
+
}
|
|
1503
|
+
for (let i = 0; i < data.rules.length; i++) {
|
|
1504
|
+
const result = this.validateRule(data.rules[i], i);
|
|
1505
|
+
if (!result.valid)
|
|
1506
|
+
return result;
|
|
1507
|
+
}
|
|
1508
|
+
// 检查 config
|
|
1509
|
+
const configResult = this.validateConfig(data.config);
|
|
1510
|
+
if (!configResult.valid)
|
|
1511
|
+
return configResult;
|
|
1512
|
+
return { valid: true };
|
|
1513
|
+
}
|
|
1366
1514
|
exportData(password) {
|
|
1367
1515
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1368
|
-
//
|
|
1369
|
-
const allServices = [];
|
|
1370
|
-
for (const vendor of this.vendors) {
|
|
1371
|
-
if (vendor.services) {
|
|
1372
|
-
// 为每个服务添加 vendorId(兼容旧格式)
|
|
1373
|
-
const servicesWithVendorId = vendor.services.map(s => (Object.assign(Object.assign({}, s), { vendorId: vendor.id })));
|
|
1374
|
-
allServices.push(...servicesWithVendorId);
|
|
1375
|
-
}
|
|
1376
|
-
}
|
|
1516
|
+
// 只导出当前格式,不再兼容旧格式
|
|
1377
1517
|
const exportData = {
|
|
1378
|
-
version:
|
|
1518
|
+
version: this.CURRENT_EXPORT_VERSION,
|
|
1379
1519
|
exportDate: Date.now(),
|
|
1380
1520
|
vendors: this.vendors,
|
|
1381
|
-
apiServices:
|
|
1521
|
+
apiServices: [], // 保留字段以兼容类型定义,但内容为空
|
|
1382
1522
|
routes: this.routes,
|
|
1383
1523
|
rules: this.rules,
|
|
1384
1524
|
config: this.config,
|
|
@@ -1388,49 +1528,111 @@ class FileSystemDatabaseManager {
|
|
|
1388
1528
|
return encrypted;
|
|
1389
1529
|
});
|
|
1390
1530
|
}
|
|
1391
|
-
|
|
1531
|
+
/**
|
|
1532
|
+
* 预览导入数据
|
|
1533
|
+
*/
|
|
1534
|
+
previewImportData(encryptedData, password) {
|
|
1392
1535
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1393
1536
|
try {
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1537
|
+
// 解密
|
|
1538
|
+
let jsonData;
|
|
1539
|
+
try {
|
|
1540
|
+
const decrypted = crypto_js_1.default.AES.decrypt(encryptedData, password);
|
|
1541
|
+
jsonData = decrypted.toString(crypto_js_1.default.enc.Utf8);
|
|
1542
|
+
if (!jsonData) {
|
|
1543
|
+
return { success: false, message: '解密失败:密码错误或数据损坏' };
|
|
1544
|
+
}
|
|
1402
1545
|
}
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1546
|
+
catch (error) {
|
|
1547
|
+
return { success: false, message: '解密失败:密码错误或数据格式错误' };
|
|
1548
|
+
}
|
|
1549
|
+
// 解析 JSON
|
|
1550
|
+
let importData;
|
|
1551
|
+
try {
|
|
1552
|
+
importData = JSON.parse(jsonData);
|
|
1553
|
+
}
|
|
1554
|
+
catch (error) {
|
|
1555
|
+
return { success: false, message: '数据解析失败:不是有效的 JSON 格式' };
|
|
1556
|
+
}
|
|
1557
|
+
// 验证数据格式
|
|
1558
|
+
const validation = this.validateExportData(importData);
|
|
1559
|
+
if (!validation.valid) {
|
|
1560
|
+
return { success: false, message: `数据验证失败:${validation.error}` };
|
|
1561
|
+
}
|
|
1562
|
+
// 计算服务数量
|
|
1563
|
+
const servicesCount = importData.vendors.reduce((sum, v) => { var _a; return sum + (((_a = v.services) === null || _a === void 0 ? void 0 : _a.length) || 0); }, 0);
|
|
1564
|
+
return {
|
|
1565
|
+
success: true,
|
|
1566
|
+
data: {
|
|
1567
|
+
vendors: importData.vendors.length,
|
|
1568
|
+
services: servicesCount,
|
|
1569
|
+
routes: importData.routes.length,
|
|
1570
|
+
rules: importData.rules.length,
|
|
1571
|
+
exportDate: importData.exportDate,
|
|
1572
|
+
version: importData.version,
|
|
1573
|
+
}
|
|
1574
|
+
};
|
|
1575
|
+
}
|
|
1576
|
+
catch (error) {
|
|
1577
|
+
console.error('Preview import error:', error);
|
|
1578
|
+
return { success: false, message: `预览失败:${error instanceof Error ? error.message : '未知错误'}` };
|
|
1579
|
+
}
|
|
1580
|
+
});
|
|
1581
|
+
}
|
|
1582
|
+
importData(encryptedData, password) {
|
|
1583
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1584
|
+
try {
|
|
1585
|
+
// 解密
|
|
1586
|
+
let jsonData;
|
|
1587
|
+
try {
|
|
1588
|
+
const decrypted = crypto_js_1.default.AES.decrypt(encryptedData, password);
|
|
1589
|
+
jsonData = decrypted.toString(crypto_js_1.default.enc.Utf8);
|
|
1590
|
+
if (!jsonData) {
|
|
1591
|
+
return { success: false, message: '导入失败', details: '解密失败:密码错误或数据损坏' };
|
|
1416
1592
|
}
|
|
1417
|
-
// 合并到 vendors
|
|
1418
|
-
this.vendors = vendors.map((vendor) => (Object.assign(Object.assign({}, vendor), { services: servicesByVendor.get(vendor.id) || [] })));
|
|
1419
1593
|
}
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1594
|
+
catch (error) {
|
|
1595
|
+
return { success: false, message: '导入失败', details: '解密失败:密码错误或数据格式错误' };
|
|
1596
|
+
}
|
|
1597
|
+
// 解析 JSON
|
|
1598
|
+
let importData;
|
|
1599
|
+
try {
|
|
1600
|
+
importData = JSON.parse(jsonData);
|
|
1601
|
+
}
|
|
1602
|
+
catch (error) {
|
|
1603
|
+
return { success: false, message: '导入失败', details: '数据解析失败:不是有效的 JSON 格式' };
|
|
1604
|
+
}
|
|
1605
|
+
// 验证数据格式
|
|
1606
|
+
const validation = this.validateExportData(importData);
|
|
1607
|
+
if (!validation.valid) {
|
|
1608
|
+
return { success: false, message: '导入失败', details: `数据验证失败:${validation.error}` };
|
|
1609
|
+
}
|
|
1610
|
+
// 导入数据(更新 updatedAt)
|
|
1611
|
+
const now = Date.now();
|
|
1612
|
+
this.vendors = importData.vendors.map((v) => (Object.assign(Object.assign({}, v), { updatedAt: now })));
|
|
1613
|
+
this.routes = importData.routes.map((r) => (Object.assign(Object.assign({}, r), { updatedAt: now })));
|
|
1614
|
+
this.rules = importData.rules.map((r) => (Object.assign(Object.assign({}, r), { updatedAt: now })));
|
|
1615
|
+
this.config = Object.assign(Object.assign({}, importData.config), { updatedAt: now });
|
|
1616
|
+
// 保存数据
|
|
1423
1617
|
yield Promise.all([
|
|
1424
1618
|
this.saveVendors(),
|
|
1425
|
-
// 删除: this.saveServices(),
|
|
1426
1619
|
this.saveRoutes(),
|
|
1427
1620
|
this.saveConfig(),
|
|
1428
1621
|
]);
|
|
1429
|
-
return
|
|
1622
|
+
const servicesCount = this.vendors.reduce((sum, v) => { var _a; return sum + (((_a = v.services) === null || _a === void 0 ? void 0 : _a.length) || 0); }, 0);
|
|
1623
|
+
return {
|
|
1624
|
+
success: true,
|
|
1625
|
+
message: '导入成功',
|
|
1626
|
+
details: `已导入 ${this.vendors.length} 个供应商、${servicesCount} 个服务、${this.routes.length} 个路由、${this.rules.length} 个规则`
|
|
1627
|
+
};
|
|
1430
1628
|
}
|
|
1431
1629
|
catch (error) {
|
|
1432
1630
|
console.error('Import error:', error);
|
|
1433
|
-
return
|
|
1631
|
+
return {
|
|
1632
|
+
success: false,
|
|
1633
|
+
message: '导入失败',
|
|
1634
|
+
details: error instanceof Error ? error.message : '未知错误'
|
|
1635
|
+
};
|
|
1434
1636
|
}
|
|
1435
1637
|
});
|
|
1436
1638
|
}
|
package/dist/server/main.js
CHANGED
|
@@ -76,7 +76,10 @@ app.use((0, cors_1.default)());
|
|
|
76
76
|
app.use(express_1.default.json({ limit: 'Infinity' }));
|
|
77
77
|
app.use(express_1.default.urlencoded({ extended: true, limit: 'Infinity' }));
|
|
78
78
|
const asyncHandler = (handler) => (req, res, next) => {
|
|
79
|
-
Promise.resolve(handler(req, res, next)).catch(
|
|
79
|
+
Promise.resolve(handler(req, res, next)).catch((err) => {
|
|
80
|
+
console.error('[asyncHandler] Caught error:', err);
|
|
81
|
+
next(err);
|
|
82
|
+
});
|
|
80
83
|
};
|
|
81
84
|
const writeClaudeConfig = (dbManager) => __awaiter(void 0, void 0, void 0, function* () {
|
|
82
85
|
try {
|
|
@@ -728,25 +731,48 @@ const registerRoutes = (dbManager, proxyServer) => {
|
|
|
728
731
|
}
|
|
729
732
|
});
|
|
730
733
|
app.get('/api/vendors', (_req, res) => res.json(dbManager.getVendors()));
|
|
731
|
-
app.post('/api/vendors', (req, res) => __awaiter(void 0, void 0, void 0, function* () { return res.json(yield dbManager.createVendor(req.body)); }));
|
|
732
|
-
app.put('/api/vendors/:id', (req, res) => __awaiter(void 0, void 0, void 0, function* () { return res.json(yield dbManager.updateVendor(req.params.id, req.body)); }));
|
|
733
|
-
app.delete('/api/vendors/:id', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
|
734
|
+
app.post('/api/vendors', asyncHandler((req, res) => __awaiter(void 0, void 0, void 0, function* () { return res.json(yield dbManager.createVendor(req.body)); })));
|
|
735
|
+
app.put('/api/vendors/:id', asyncHandler((req, res) => __awaiter(void 0, void 0, void 0, function* () { return res.json(yield dbManager.updateVendor(req.params.id, req.body)); })));
|
|
736
|
+
app.delete('/api/vendors/:id', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
|
737
|
+
try {
|
|
738
|
+
const result = yield dbManager.deleteVendor(req.params.id);
|
|
739
|
+
res.json(result);
|
|
740
|
+
}
|
|
741
|
+
catch (error) {
|
|
742
|
+
console.error('[删除供应商] 错误:', error);
|
|
743
|
+
res.setHeader('Content-Type', 'application/json');
|
|
744
|
+
res.status(500).json({ error: error instanceof Error ? error.message : '删除失败' });
|
|
745
|
+
}
|
|
746
|
+
}));
|
|
734
747
|
app.get('/api/services', (req, res) => {
|
|
735
748
|
const vendorId = typeof req.query.vendorId === 'string' ? req.query.vendorId : undefined;
|
|
736
749
|
res.json(dbManager.getAPIServices(vendorId));
|
|
737
750
|
});
|
|
738
|
-
app.post('/api/services', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
|
751
|
+
app.post('/api/services', asyncHandler((req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
|
739
752
|
console.log('[创建服务] 请求数据:', JSON.stringify(req.body, null, 2));
|
|
740
753
|
const result = yield dbManager.createAPIService(req.body);
|
|
741
754
|
console.log('[创建服务] 创建结果:', JSON.stringify(result, null, 2));
|
|
742
755
|
res.json(result);
|
|
756
|
+
})));
|
|
757
|
+
app.put('/api/services/:id', asyncHandler((req, res) => __awaiter(void 0, void 0, void 0, function* () { return res.json(yield dbManager.updateAPIService(req.params.id, req.body)); })));
|
|
758
|
+
app.delete('/api/services/:id', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
|
759
|
+
console.log('[删除服务] 请求 ID:', req.params.id);
|
|
760
|
+
try {
|
|
761
|
+
const result = yield dbManager.deleteAPIService(req.params.id);
|
|
762
|
+
console.log('[删除服务] 结果:', result);
|
|
763
|
+
res.json(result);
|
|
764
|
+
}
|
|
765
|
+
catch (error) {
|
|
766
|
+
console.error('[删除服务] 错误:', error);
|
|
767
|
+
// 显式设置 Content-Type 并返回 JSON 错误
|
|
768
|
+
res.setHeader('Content-Type', 'application/json');
|
|
769
|
+
res.status(500).json({ error: error instanceof Error ? error.message : '删除失败' });
|
|
770
|
+
}
|
|
743
771
|
}));
|
|
744
|
-
app.put('/api/services/:id', (req, res) => __awaiter(void 0, void 0, void 0, function* () { return res.json(yield dbManager.updateAPIService(req.params.id, req.body)); }));
|
|
745
|
-
app.delete('/api/services/:id', (req, res) => __awaiter(void 0, void 0, void 0, function* () { return res.json(yield dbManager.deleteAPIService(req.params.id)); }));
|
|
746
772
|
app.get('/api/routes', (_req, res) => res.json(dbManager.getRoutes()));
|
|
747
|
-
app.post('/api/routes', (req, res) => __awaiter(void 0, void 0, void 0, function* () { return res.json(yield dbManager.createRoute(req.body)); }));
|
|
748
|
-
app.put('/api/routes/:id', (req, res) => __awaiter(void 0, void 0, void 0, function* () { return res.json(yield dbManager.updateRoute(req.params.id, req.body)); }));
|
|
749
|
-
app.delete('/api/routes/:id', (req, res) => __awaiter(void 0, void 0, void 0, function* () { return res.json(yield dbManager.deleteRoute(req.params.id)); }));
|
|
773
|
+
app.post('/api/routes', asyncHandler((req, res) => __awaiter(void 0, void 0, void 0, function* () { return res.json(yield dbManager.createRoute(req.body)); })));
|
|
774
|
+
app.put('/api/routes/:id', asyncHandler((req, res) => __awaiter(void 0, void 0, void 0, function* () { return res.json(yield dbManager.updateRoute(req.params.id, req.body)); })));
|
|
775
|
+
app.delete('/api/routes/:id', asyncHandler((req, res) => __awaiter(void 0, void 0, void 0, function* () { return res.json(yield dbManager.deleteRoute(req.params.id)); })));
|
|
750
776
|
app.post('/api/routes/:id/activate', asyncHandler((req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
|
751
777
|
const result = yield dbManager.activateRoute(req.params.id);
|
|
752
778
|
if (result) {
|
|
@@ -803,12 +829,12 @@ const registerRoutes = (dbManager, proxyServer) => {
|
|
|
803
829
|
const routeId = typeof req.query.routeId === 'string' ? req.query.routeId : undefined;
|
|
804
830
|
res.json(dbManager.getRules(routeId));
|
|
805
831
|
});
|
|
806
|
-
app.post('/api/rules', (req, res) => __awaiter(void 0, void 0, void 0, function* () { return res.json(yield dbManager.createRule(req.body)); }));
|
|
807
|
-
app.put('/api/rules/:id', (req, res) => __awaiter(void 0, void 0, void 0, function* () { return res.json(yield dbManager.updateRule(req.params.id, req.body)); }));
|
|
808
|
-
app.delete('/api/rules/:id', (req, res) => __awaiter(void 0, void 0, void 0, function* () { return res.json(yield dbManager.deleteRule(req.params.id)); }));
|
|
809
|
-
app.put('/api/rules/:id/reset-tokens', (req, res) => __awaiter(void 0, void 0, void 0, function* () { return res.json(yield dbManager.resetRuleTokenUsage(req.params.id)); }));
|
|
810
|
-
app.put('/api/rules/:id/reset-requests', (req, res) => __awaiter(void 0, void 0, void 0, function* () { return res.json(yield dbManager.resetRuleRequestCount(req.params.id)); }));
|
|
811
|
-
app.put('/api/rules/:id/toggle-disable', (req, res) => __awaiter(void 0, void 0, void 0, function* () { return res.json(yield dbManager.toggleRuleDisabled(req.params.id)); }));
|
|
832
|
+
app.post('/api/rules', asyncHandler((req, res) => __awaiter(void 0, void 0, void 0, function* () { return res.json(yield dbManager.createRule(req.body)); })));
|
|
833
|
+
app.put('/api/rules/:id', asyncHandler((req, res) => __awaiter(void 0, void 0, void 0, function* () { return res.json(yield dbManager.updateRule(req.params.id, req.body)); })));
|
|
834
|
+
app.delete('/api/rules/:id', asyncHandler((req, res) => __awaiter(void 0, void 0, void 0, function* () { return res.json(yield dbManager.deleteRule(req.params.id)); })));
|
|
835
|
+
app.put('/api/rules/:id/reset-tokens', asyncHandler((req, res) => __awaiter(void 0, void 0, void 0, function* () { return res.json(yield dbManager.resetRuleTokenUsage(req.params.id)); })));
|
|
836
|
+
app.put('/api/rules/:id/reset-requests', asyncHandler((req, res) => __awaiter(void 0, void 0, void 0, function* () { return res.json(yield dbManager.resetRuleRequestCount(req.params.id)); })));
|
|
837
|
+
app.put('/api/rules/:id/toggle-disable', asyncHandler((req, res) => __awaiter(void 0, void 0, void 0, function* () { return res.json(yield dbManager.toggleRuleDisabled(req.params.id)); })));
|
|
812
838
|
// 解除规则的黑名单状态
|
|
813
839
|
app.put('/api/rules/:id/clear-blacklist', asyncHandler((req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
|
814
840
|
const { id } = req.params;
|
|
@@ -1274,10 +1300,16 @@ ${instruction}
|
|
|
1274
1300
|
const data = yield dbManager.exportData(password);
|
|
1275
1301
|
res.json({ data });
|
|
1276
1302
|
})));
|
|
1303
|
+
// 导入数据预览
|
|
1304
|
+
app.post('/api/import/preview', asyncHandler((req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1305
|
+
const { encryptedData, password } = req.body;
|
|
1306
|
+
const result = yield dbManager.previewImportData(encryptedData, password);
|
|
1307
|
+
res.json(result);
|
|
1308
|
+
})));
|
|
1277
1309
|
app.post('/api/import', asyncHandler((req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
|
1278
1310
|
const { encryptedData, password } = req.body;
|
|
1279
1311
|
const result = yield dbManager.importData(encryptedData, password);
|
|
1280
|
-
if (result) {
|
|
1312
|
+
if (result.success) {
|
|
1281
1313
|
yield proxyServer.reloadRoutes();
|
|
1282
1314
|
}
|
|
1283
1315
|
res.json(result);
|
|
@@ -1428,6 +1460,17 @@ const start = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
1428
1460
|
registerRoutes(dbManager, proxyServer);
|
|
1429
1461
|
yield proxyServer.registerProxyRoutes();
|
|
1430
1462
|
app.use(express_1.default.static(path_1.default.resolve(__dirname, '../ui')));
|
|
1463
|
+
// 404 处理程序 - 确保返回 JSON 而不是 HTML(放在所有路由和静态文件之后)
|
|
1464
|
+
app.use((_req, res) => {
|
|
1465
|
+
res.status(404).json({ error: 'Not found' });
|
|
1466
|
+
});
|
|
1467
|
+
// Error handling middleware - must be the last middleware
|
|
1468
|
+
app.use((err, _req, res, _next) => {
|
|
1469
|
+
console.error('[Error Handler]', err);
|
|
1470
|
+
// Ensure JSON response
|
|
1471
|
+
res.setHeader('Content-Type', 'application/json');
|
|
1472
|
+
res.status(500).json({ error: err.message || 'Internal server error' });
|
|
1473
|
+
});
|
|
1431
1474
|
const isPortUsable = yield (0, utils_1.checkPortUsable)(port);
|
|
1432
1475
|
if (!isPortUsable) {
|
|
1433
1476
|
console.error(`端口 ${port} 已被占用,无法启动服务。请执行 aicos stop 后重启。`);
|
|
@@ -1469,10 +1512,6 @@ const start = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
1469
1512
|
process.on('SIGINT', shutdown);
|
|
1470
1513
|
process.on('SIGTERM', shutdown);
|
|
1471
1514
|
});
|
|
1472
|
-
app.use((err, _req, res, _next) => {
|
|
1473
|
-
console.error(err);
|
|
1474
|
-
res.status(500).json({ error: err.message || 'Internal server error' });
|
|
1475
|
-
});
|
|
1476
1515
|
// 全局未捕获异常处理 - 防止服务崩溃
|
|
1477
1516
|
process.on('uncaughtException', (error) => {
|
|
1478
1517
|
console.error('[Uncaught Exception] 服务遇到未捕获的异常:', error);
|