@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 +173 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +174 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -122,11 +122,19 @@ interface RunResult {
|
|
|
122
122
|
declare class SqliteExecutor {
|
|
123
123
|
private binaryPath;
|
|
124
124
|
private dbPath;
|
|
125
|
+
private connectionId;
|
|
126
|
+
private tcpPort;
|
|
127
|
+
private useTcp;
|
|
125
128
|
constructor(dbPath: string);
|
|
126
129
|
private getBinaryPath;
|
|
127
130
|
private executeBinary;
|
|
128
131
|
connect(): Promise<boolean>;
|
|
129
132
|
exists(): Promise<boolean>;
|
|
133
|
+
private findAvailablePort;
|
|
134
|
+
private isPortAvailable;
|
|
135
|
+
private startTcpServer;
|
|
136
|
+
private sendTcpQuery;
|
|
137
|
+
private sleep;
|
|
130
138
|
query(sql: string, params?: any[]): Promise<SqliteResult>;
|
|
131
139
|
queryMultiple(sql: string): Promise<SqliteResult>;
|
|
132
140
|
prepare(sql: string): {
|
package/dist/index.d.ts
CHANGED
|
@@ -122,11 +122,19 @@ interface RunResult {
|
|
|
122
122
|
declare class SqliteExecutor {
|
|
123
123
|
private binaryPath;
|
|
124
124
|
private dbPath;
|
|
125
|
+
private connectionId;
|
|
126
|
+
private tcpPort;
|
|
127
|
+
private useTcp;
|
|
125
128
|
constructor(dbPath: string);
|
|
126
129
|
private getBinaryPath;
|
|
127
130
|
private executeBinary;
|
|
128
131
|
connect(): Promise<boolean>;
|
|
129
132
|
exists(): Promise<boolean>;
|
|
133
|
+
private findAvailablePort;
|
|
134
|
+
private isPortAvailable;
|
|
135
|
+
private startTcpServer;
|
|
136
|
+
private sendTcpQuery;
|
|
137
|
+
private sleep;
|
|
130
138
|
query(sql: string, params?: any[]): Promise<SqliteResult>;
|
|
131
139
|
queryMultiple(sql: string): Promise<SqliteResult>;
|
|
132
140
|
prepare(sql: string): {
|
package/dist/index.js
CHANGED
|
@@ -1243,18 +1243,25 @@ var QueryEngine = class {
|
|
|
1243
1243
|
};
|
|
1244
1244
|
|
|
1245
1245
|
// src/lib/SqliteExecutor.ts
|
|
1246
|
-
import { exec } from "child_process";
|
|
1246
|
+
import { exec, spawn as spawn3 } from "child_process";
|
|
1247
1247
|
import * as path5 from "path";
|
|
1248
1248
|
import * as fs3 from "fs";
|
|
1249
1249
|
import { promisify } from "util";
|
|
1250
1250
|
import { createRequire as createRequire3 } from "module";
|
|
1251
|
+
import * as net2 from "net";
|
|
1251
1252
|
var execAsync = promisify(exec);
|
|
1253
|
+
var globalSqliteServers = /* @__PURE__ */ new Map();
|
|
1254
|
+
var globalSqliteConnections = /* @__PURE__ */ new Map();
|
|
1252
1255
|
var SqliteExecutor = class {
|
|
1253
1256
|
binaryPath;
|
|
1254
1257
|
dbPath;
|
|
1258
|
+
connectionId;
|
|
1259
|
+
tcpPort = 9944;
|
|
1260
|
+
useTcp = true;
|
|
1255
1261
|
constructor(dbPath) {
|
|
1256
1262
|
this.dbPath = dbPath;
|
|
1257
1263
|
this.binaryPath = this.getBinaryPath();
|
|
1264
|
+
this.connectionId = `sqlite_${dbPath.replace(/[^a-zA-Z0-9]/g, "_")}`;
|
|
1258
1265
|
}
|
|
1259
1266
|
getBinaryPath() {
|
|
1260
1267
|
const possibleDirs = [
|
|
@@ -1337,7 +1344,173 @@ var SqliteExecutor = class {
|
|
|
1337
1344
|
return false;
|
|
1338
1345
|
}
|
|
1339
1346
|
}
|
|
1347
|
+
async findAvailablePort(startPort) {
|
|
1348
|
+
for (let port = startPort; port >= 9900; port--) {
|
|
1349
|
+
if (await this.isPortAvailable(port)) {
|
|
1350
|
+
return port;
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
throw new Error("No available ports found in range 9900-9944");
|
|
1354
|
+
}
|
|
1355
|
+
isPortAvailable(port) {
|
|
1356
|
+
return new Promise((resolve5) => {
|
|
1357
|
+
const tester = net2.createServer();
|
|
1358
|
+
tester.once("error", () => resolve5(false));
|
|
1359
|
+
tester.once("listening", () => {
|
|
1360
|
+
tester.close();
|
|
1361
|
+
resolve5(true);
|
|
1362
|
+
});
|
|
1363
|
+
tester.listen(port, "127.0.0.1");
|
|
1364
|
+
});
|
|
1365
|
+
}
|
|
1366
|
+
async startTcpServer() {
|
|
1367
|
+
this.tcpPort = await this.findAvailablePort(this.tcpPort);
|
|
1368
|
+
return new Promise((resolve5, reject) => {
|
|
1369
|
+
const serverArgs = [
|
|
1370
|
+
"--action",
|
|
1371
|
+
"serve",
|
|
1372
|
+
"--id",
|
|
1373
|
+
this.connectionId,
|
|
1374
|
+
"--database-ref",
|
|
1375
|
+
"config",
|
|
1376
|
+
"--database",
|
|
1377
|
+
this.dbPath
|
|
1378
|
+
];
|
|
1379
|
+
const serverProcess = spawn3(this.binaryPath, serverArgs);
|
|
1380
|
+
let started = false;
|
|
1381
|
+
const timeout = setTimeout(() => {
|
|
1382
|
+
if (!started) {
|
|
1383
|
+
serverProcess.kill();
|
|
1384
|
+
reject(new Error("SQLite TCP server startup timeout"));
|
|
1385
|
+
}
|
|
1386
|
+
}, 1e4);
|
|
1387
|
+
serverProcess.stdout.on("data", (data) => {
|
|
1388
|
+
const output = data.toString();
|
|
1389
|
+
if (output.includes("SQLite TCP Server started") || output.includes("PROCESS_RESPONSE:")) {
|
|
1390
|
+
if (!started) {
|
|
1391
|
+
started = true;
|
|
1392
|
+
clearTimeout(timeout);
|
|
1393
|
+
const match = output.match(/PROCESS_RESPONSE:(\{.*\})/);
|
|
1394
|
+
if (match) {
|
|
1395
|
+
try {
|
|
1396
|
+
const response = JSON.parse(match[1]);
|
|
1397
|
+
if (response.data && response.data.port) {
|
|
1398
|
+
this.tcpPort = response.data.port;
|
|
1399
|
+
}
|
|
1400
|
+
} catch (e) {
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
globalSqliteServers.set(this.connectionId, {
|
|
1404
|
+
port: this.tcpPort,
|
|
1405
|
+
process: serverProcess
|
|
1406
|
+
});
|
|
1407
|
+
resolve5();
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
});
|
|
1411
|
+
serverProcess.stderr.on("data", (data) => {
|
|
1412
|
+
console.error(`[SQLite Server Error] ${data.toString().trim()}`);
|
|
1413
|
+
});
|
|
1414
|
+
serverProcess.on("close", () => {
|
|
1415
|
+
globalSqliteServers.delete(this.connectionId);
|
|
1416
|
+
globalSqliteConnections.delete(this.connectionId);
|
|
1417
|
+
});
|
|
1418
|
+
serverProcess.on("error", (error) => {
|
|
1419
|
+
if (!started) {
|
|
1420
|
+
clearTimeout(timeout);
|
|
1421
|
+
reject(error);
|
|
1422
|
+
}
|
|
1423
|
+
});
|
|
1424
|
+
});
|
|
1425
|
+
}
|
|
1426
|
+
async sendTcpQuery(sql, params) {
|
|
1427
|
+
const serverInfo = globalSqliteServers.get(this.connectionId);
|
|
1428
|
+
if (!serverInfo || !serverInfo.process || serverInfo.process.killed) {
|
|
1429
|
+
await this.startTcpServer();
|
|
1430
|
+
await this.sleep(500);
|
|
1431
|
+
}
|
|
1432
|
+
return new Promise((resolve5, reject) => {
|
|
1433
|
+
const client = new net2.Socket();
|
|
1434
|
+
let responseBuffer = "";
|
|
1435
|
+
let isResolved = false;
|
|
1436
|
+
const timeout = setTimeout(() => {
|
|
1437
|
+
if (!isResolved) {
|
|
1438
|
+
isResolved = true;
|
|
1439
|
+
client.destroy();
|
|
1440
|
+
reject(new Error("TCP query timeout"));
|
|
1441
|
+
}
|
|
1442
|
+
}, 1e4);
|
|
1443
|
+
client.connect(this.tcpPort, "127.0.0.1", () => {
|
|
1444
|
+
const command = {
|
|
1445
|
+
action: "query",
|
|
1446
|
+
query: sql,
|
|
1447
|
+
params: params || []
|
|
1448
|
+
};
|
|
1449
|
+
client.write(JSON.stringify(command) + "\n");
|
|
1450
|
+
});
|
|
1451
|
+
client.on("data", (data) => {
|
|
1452
|
+
responseBuffer += data.toString();
|
|
1453
|
+
const match = responseBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
|
|
1454
|
+
if (match && !isResolved) {
|
|
1455
|
+
isResolved = true;
|
|
1456
|
+
clearTimeout(timeout);
|
|
1457
|
+
client.destroy();
|
|
1458
|
+
try {
|
|
1459
|
+
const response = JSON.parse(match[1]);
|
|
1460
|
+
if (response.code === 200) {
|
|
1461
|
+
resolve5({
|
|
1462
|
+
status: "success",
|
|
1463
|
+
message: response.message,
|
|
1464
|
+
data: response.data
|
|
1465
|
+
});
|
|
1466
|
+
} else {
|
|
1467
|
+
resolve5({
|
|
1468
|
+
status: "error",
|
|
1469
|
+
message: response.message,
|
|
1470
|
+
data: null
|
|
1471
|
+
});
|
|
1472
|
+
}
|
|
1473
|
+
} catch (error) {
|
|
1474
|
+
reject(new Error("Failed to parse TCP response"));
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
});
|
|
1478
|
+
client.on("error", (error) => {
|
|
1479
|
+
if (!isResolved) {
|
|
1480
|
+
isResolved = true;
|
|
1481
|
+
clearTimeout(timeout);
|
|
1482
|
+
this.useTcp = false;
|
|
1483
|
+
this.executeBinary([
|
|
1484
|
+
"--action",
|
|
1485
|
+
"query",
|
|
1486
|
+
"--database",
|
|
1487
|
+
this.dbPath,
|
|
1488
|
+
"--query",
|
|
1489
|
+
sql,
|
|
1490
|
+
...params && params.length > 0 ? ["--params", JSON.stringify(params)] : []
|
|
1491
|
+
]).then(resolve5).catch(reject);
|
|
1492
|
+
}
|
|
1493
|
+
});
|
|
1494
|
+
client.on("close", () => {
|
|
1495
|
+
if (!isResolved) {
|
|
1496
|
+
clearTimeout(timeout);
|
|
1497
|
+
reject(new Error("Connection closed without valid response"));
|
|
1498
|
+
}
|
|
1499
|
+
});
|
|
1500
|
+
});
|
|
1501
|
+
}
|
|
1502
|
+
sleep(ms) {
|
|
1503
|
+
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
1504
|
+
}
|
|
1340
1505
|
async query(sql, params) {
|
|
1506
|
+
if (this.useTcp) {
|
|
1507
|
+
try {
|
|
1508
|
+
return await this.sendTcpQuery(sql, params);
|
|
1509
|
+
} catch (error) {
|
|
1510
|
+
console.warn("TCP query failed, falling back to direct execution");
|
|
1511
|
+
this.useTcp = false;
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1341
1514
|
const args = [
|
|
1342
1515
|
"--action",
|
|
1343
1516
|
"query",
|