@dbcube/core 3.0.22 → 3.0.23

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/dist/index.cjs CHANGED
@@ -1293,13 +1293,20 @@ var path5 = __toESM(require("path"));
1293
1293
  var fs3 = __toESM(require("fs"));
1294
1294
  var import_util = require("util");
1295
1295
  var import_module3 = require("module");
1296
+ var net2 = __toESM(require("net"));
1296
1297
  var execAsync = (0, import_util.promisify)(import_child_process3.exec);
1298
+ var globalSqliteServers = /* @__PURE__ */ new Map();
1299
+ var globalSqliteConnections = /* @__PURE__ */ new Map();
1297
1300
  var SqliteExecutor = class {
1298
1301
  binaryPath;
1299
1302
  dbPath;
1303
+ connectionId;
1304
+ tcpPort = 9944;
1305
+ useTcp = true;
1300
1306
  constructor(dbPath) {
1301
1307
  this.dbPath = dbPath;
1302
1308
  this.binaryPath = this.getBinaryPath();
1309
+ this.connectionId = `sqlite_${dbPath.replace(/[^a-zA-Z0-9]/g, "_")}`;
1303
1310
  }
1304
1311
  getBinaryPath() {
1305
1312
  const possibleDirs = [
@@ -1382,7 +1389,173 @@ var SqliteExecutor = class {
1382
1389
  return false;
1383
1390
  }
1384
1391
  }
1392
+ async findAvailablePort(startPort) {
1393
+ for (let port = startPort; port >= 9900; port--) {
1394
+ if (await this.isPortAvailable(port)) {
1395
+ return port;
1396
+ }
1397
+ }
1398
+ throw new Error("No available ports found in range 9900-9944");
1399
+ }
1400
+ isPortAvailable(port) {
1401
+ return new Promise((resolve5) => {
1402
+ const tester = net2.createServer();
1403
+ tester.once("error", () => resolve5(false));
1404
+ tester.once("listening", () => {
1405
+ tester.close();
1406
+ resolve5(true);
1407
+ });
1408
+ tester.listen(port, "127.0.0.1");
1409
+ });
1410
+ }
1411
+ async startTcpServer() {
1412
+ this.tcpPort = await this.findAvailablePort(this.tcpPort);
1413
+ return new Promise((resolve5, reject) => {
1414
+ const serverArgs = [
1415
+ "--action",
1416
+ "serve",
1417
+ "--id",
1418
+ this.connectionId,
1419
+ "--database-ref",
1420
+ "config",
1421
+ "--database",
1422
+ this.dbPath
1423
+ ];
1424
+ const serverProcess = (0, import_child_process3.spawn)(this.binaryPath, serverArgs);
1425
+ let started = false;
1426
+ const timeout = setTimeout(() => {
1427
+ if (!started) {
1428
+ serverProcess.kill();
1429
+ reject(new Error("SQLite TCP server startup timeout"));
1430
+ }
1431
+ }, 1e4);
1432
+ serverProcess.stdout.on("data", (data) => {
1433
+ const output = data.toString();
1434
+ if (output.includes("SQLite TCP Server started") || output.includes("PROCESS_RESPONSE:")) {
1435
+ if (!started) {
1436
+ started = true;
1437
+ clearTimeout(timeout);
1438
+ const match = output.match(/PROCESS_RESPONSE:(\{.*\})/);
1439
+ if (match) {
1440
+ try {
1441
+ const response = JSON.parse(match[1]);
1442
+ if (response.data && response.data.port) {
1443
+ this.tcpPort = response.data.port;
1444
+ }
1445
+ } catch (e) {
1446
+ }
1447
+ }
1448
+ globalSqliteServers.set(this.connectionId, {
1449
+ port: this.tcpPort,
1450
+ process: serverProcess
1451
+ });
1452
+ resolve5();
1453
+ }
1454
+ }
1455
+ });
1456
+ serverProcess.stderr.on("data", (data) => {
1457
+ console.error(`[SQLite Server Error] ${data.toString().trim()}`);
1458
+ });
1459
+ serverProcess.on("close", () => {
1460
+ globalSqliteServers.delete(this.connectionId);
1461
+ globalSqliteConnections.delete(this.connectionId);
1462
+ });
1463
+ serverProcess.on("error", (error) => {
1464
+ if (!started) {
1465
+ clearTimeout(timeout);
1466
+ reject(error);
1467
+ }
1468
+ });
1469
+ });
1470
+ }
1471
+ async sendTcpQuery(sql, params) {
1472
+ const serverInfo = globalSqliteServers.get(this.connectionId);
1473
+ if (!serverInfo || !serverInfo.process || serverInfo.process.killed) {
1474
+ await this.startTcpServer();
1475
+ await this.sleep(500);
1476
+ }
1477
+ return new Promise((resolve5, reject) => {
1478
+ const client = new net2.Socket();
1479
+ let responseBuffer = "";
1480
+ let isResolved = false;
1481
+ const timeout = setTimeout(() => {
1482
+ if (!isResolved) {
1483
+ isResolved = true;
1484
+ client.destroy();
1485
+ reject(new Error("TCP query timeout"));
1486
+ }
1487
+ }, 1e4);
1488
+ client.connect(this.tcpPort, "127.0.0.1", () => {
1489
+ const command = {
1490
+ action: "query",
1491
+ query: sql,
1492
+ params: params || []
1493
+ };
1494
+ client.write(JSON.stringify(command) + "\n");
1495
+ });
1496
+ client.on("data", (data) => {
1497
+ responseBuffer += data.toString();
1498
+ const match = responseBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
1499
+ if (match && !isResolved) {
1500
+ isResolved = true;
1501
+ clearTimeout(timeout);
1502
+ client.destroy();
1503
+ try {
1504
+ const response = JSON.parse(match[1]);
1505
+ if (response.code === 200) {
1506
+ resolve5({
1507
+ status: "success",
1508
+ message: response.message,
1509
+ data: response.data
1510
+ });
1511
+ } else {
1512
+ resolve5({
1513
+ status: "error",
1514
+ message: response.message,
1515
+ data: null
1516
+ });
1517
+ }
1518
+ } catch (error) {
1519
+ reject(new Error("Failed to parse TCP response"));
1520
+ }
1521
+ }
1522
+ });
1523
+ client.on("error", (error) => {
1524
+ if (!isResolved) {
1525
+ isResolved = true;
1526
+ clearTimeout(timeout);
1527
+ this.useTcp = false;
1528
+ this.executeBinary([
1529
+ "--action",
1530
+ "query",
1531
+ "--database",
1532
+ this.dbPath,
1533
+ "--query",
1534
+ sql,
1535
+ ...params && params.length > 0 ? ["--params", JSON.stringify(params)] : []
1536
+ ]).then(resolve5).catch(reject);
1537
+ }
1538
+ });
1539
+ client.on("close", () => {
1540
+ if (!isResolved) {
1541
+ clearTimeout(timeout);
1542
+ reject(new Error("Connection closed without valid response"));
1543
+ }
1544
+ });
1545
+ });
1546
+ }
1547
+ sleep(ms) {
1548
+ return new Promise((resolve5) => setTimeout(resolve5, ms));
1549
+ }
1385
1550
  async query(sql, params) {
1551
+ if (this.useTcp) {
1552
+ try {
1553
+ return await this.sendTcpQuery(sql, params);
1554
+ } catch (error) {
1555
+ console.warn("TCP query failed, falling back to direct execution");
1556
+ this.useTcp = false;
1557
+ }
1558
+ }
1386
1559
  const args = [
1387
1560
  "--action",
1388
1561
  "query",