@dbcube/core 5.2.1 → 5.2.3

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
@@ -194,7 +194,7 @@ var Downloader = class {
194
194
  */
195
195
  static async fetchLatestVersion(prefix) {
196
196
  const url = this.VERSION_URLS[prefix];
197
- return new Promise((resolve5, reject) => {
197
+ return new Promise((resolve6, reject) => {
198
198
  https.get(url, (response) => {
199
199
  let data = "";
200
200
  response.on("data", (chunk) => {
@@ -204,7 +204,7 @@ var Downloader = class {
204
204
  try {
205
205
  const versions = JSON.parse(data);
206
206
  if (versions && versions.length > 0) {
207
- resolve5(versions[0].version);
207
+ resolve6(versions[0].version);
208
208
  } else {
209
209
  reject(new Error("No versions found"));
210
210
  }
@@ -413,7 +413,7 @@ var Downloader = class {
413
413
  if (attempt < maxRetries && (errorMessage.includes("ECONNRESET") || errorMessage.includes("timeout") || errorMessage.includes("ETIMEDOUT") || errorMessage.includes("ENOTFOUND"))) {
414
414
  attempt++;
415
415
  console.log(`\u{1F504} Retrying ${binary.prefix}-engine (${attempt}/${maxRetries})...`);
416
- await new Promise((resolve5) => setTimeout(resolve5, 1e3 + Math.random() * 1e3));
416
+ await new Promise((resolve6) => setTimeout(resolve6, 1e3 + Math.random() * 1e3));
417
417
  } else {
418
418
  throw new Error(`Error downloading ${binary.prefix}: ${errorMessage}`);
419
419
  }
@@ -461,12 +461,12 @@ var Downloader = class {
461
461
  return `[${filledBar}${emptyBar}] ${percentage}`;
462
462
  }
463
463
  static downloadFileWithProgress(url, outputPath, prefix) {
464
- return new Promise((resolve5, reject) => {
464
+ return new Promise((resolve6, reject) => {
465
465
  const request = https.get(url, { timeout: 0 }, (response) => {
466
466
  if (response.statusCode === 302 || response.statusCode === 301) {
467
467
  const redirectUrl = response.headers.location;
468
468
  if (redirectUrl) {
469
- return this.downloadFileWithProgress(redirectUrl, outputPath, prefix).then(resolve5).catch(reject);
469
+ return this.downloadFileWithProgress(redirectUrl, outputPath, prefix).then(resolve6).catch(reject);
470
470
  }
471
471
  }
472
472
  if (response.statusCode !== 200) {
@@ -489,7 +489,7 @@ var Downloader = class {
489
489
  }
490
490
  });
491
491
  response.on("end", () => {
492
- file.end(() => resolve5());
492
+ file.end(() => resolve6());
493
493
  });
494
494
  response.on("error", (err) => {
495
495
  file.close();
@@ -521,35 +521,47 @@ var Downloader = class {
521
521
  this.mainSpinner.text = `\u{1F4E5} ${import_chalk.default.bold(binary)} - ${progressText}`;
522
522
  }
523
523
  static extractBinary(zipPath, outputPath, prefix) {
524
- return new Promise((resolve5, reject) => {
525
- let extracted = false;
524
+ return new Promise((resolve6, reject) => {
525
+ const outDir = path.dirname(outputPath);
526
+ let extracted = 0;
527
+ const pending = [];
526
528
  fs.createReadStream(zipPath).pipe(unzipper.Parse()).on("entry", (entry) => {
527
- if (entry.type === "File" && !extracted) {
528
- extracted = true;
529
- const writeStream = fs.createWriteStream(outputPath);
529
+ if (entry.type !== "File") {
530
+ entry.autodrain();
531
+ return;
532
+ }
533
+ const isMain = extracted === 0;
534
+ extracted++;
535
+ const target = isMain ? outputPath : path.join(outDir, path.basename(entry.path));
536
+ pending.push(new Promise((res, rej) => {
537
+ const writeStream = fs.createWriteStream(target);
530
538
  entry.pipe(writeStream);
531
539
  writeStream.on("finish", () => {
532
540
  if (process.platform !== "win32") {
533
- fs.chmodSync(outputPath, 493);
541
+ try {
542
+ fs.chmodSync(target, 493);
543
+ } catch {
544
+ }
534
545
  }
535
- this.cleanupFile(zipPath);
536
- resolve5();
546
+ res();
537
547
  });
538
- writeStream.on("error", (err) => {
539
- this.cleanupFile(zipPath);
540
- reject(err);
541
- });
542
- } else {
543
- entry.autodrain();
544
- }
548
+ writeStream.on("error", rej);
549
+ }));
545
550
  }).on("error", (err) => {
546
551
  this.cleanupFile(zipPath);
547
552
  reject(err);
548
553
  }).on("close", () => {
549
- if (!extracted) {
554
+ Promise.all(pending).then(() => {
550
555
  this.cleanupFile(zipPath);
551
- reject(new Error(`No se encontr\xF3 archivo v\xE1lido en el ZIP para ${prefix}`));
552
- }
556
+ if (extracted === 0) {
557
+ reject(new Error(`No se encontr\xF3 archivo v\xE1lido en el ZIP para ${prefix}`));
558
+ } else {
559
+ resolve6();
560
+ }
561
+ }).catch((err) => {
562
+ this.cleanupFile(zipPath);
563
+ reject(err);
564
+ });
553
565
  });
554
566
  });
555
567
  }
@@ -864,22 +876,22 @@ var DaemonClient = class _DaemonClient {
864
876
  child.unref();
865
877
  }
866
878
  tryConnect(port) {
867
- return new Promise((resolve5) => {
879
+ return new Promise((resolve6) => {
868
880
  const socket = import_net.default.createConnection({ host: "127.0.0.1", port }, async () => {
869
881
  socket.setNoDelay(true);
870
882
  this.attach(socket);
871
883
  try {
872
884
  const pong = await this.send({ action: "ping" }, 2e3);
873
- resolve5(pong.status === 200);
885
+ resolve6(pong.status === 200);
874
886
  } catch {
875
887
  this.detach();
876
- resolve5(false);
888
+ resolve6(false);
877
889
  }
878
890
  });
879
- socket.once("error", () => resolve5(false));
891
+ socket.once("error", () => resolve6(false));
880
892
  socket.setTimeout(3e3, () => {
881
893
  socket.destroy();
882
- resolve5(false);
894
+ resolve6(false);
883
895
  });
884
896
  });
885
897
  }
@@ -927,7 +939,7 @@ var DaemonClient = class _DaemonClient {
927
939
  * single socket, so pending requests resolve in send order.
928
940
  */
929
941
  send(payload, timeoutMs) {
930
- return new Promise((resolve5, reject) => {
942
+ return new Promise((resolve6, reject) => {
931
943
  if (!this.socket || this.socket.destroyed) {
932
944
  reject(new Error("Daemon not connected"));
933
945
  return;
@@ -938,12 +950,12 @@ var DaemonClient = class _DaemonClient {
938
950
  reject(new Error("Daemon request timeout"));
939
951
  this.detach();
940
952
  }, timeoutMs ?? this.requestTimeout);
941
- this.pending.push({ resolve: resolve5, reject, timer });
953
+ this.pending.push({ resolve: resolve6, reject, timer });
942
954
  this.socket.write(JSON.stringify(payload) + "\n");
943
955
  });
944
956
  }
945
957
  async execute(dml, txId) {
946
- const payload = { action: "execute", dml: JSON.stringify(dml) };
958
+ const payload = { action: "execute", dml };
947
959
  if (txId) payload.tx_id = txId;
948
960
  return this.send(payload);
949
961
  }
@@ -1010,8 +1022,8 @@ var Engine = class {
1010
1022
  const binaryPath = this.binary["query_engine"];
1011
1023
  if (!binaryPath) return null;
1012
1024
  const client = DaemonClient.get(this.name, binaryPath, this.arguments);
1013
- const ok = await client.ensure();
1014
- if (!ok) {
1025
+ const ok2 = await client.ensure();
1026
+ if (!ok2) {
1015
1027
  this.daemonFailed = true;
1016
1028
  return null;
1017
1029
  }
@@ -1142,7 +1154,7 @@ var Engine = class {
1142
1154
  if (!this.binary) {
1143
1155
  throw new Error("Binary not initialized");
1144
1156
  }
1145
- return new Promise((resolve5, reject) => {
1157
+ return new Promise((resolve6, reject) => {
1146
1158
  const child = (0, import_child_process2.spawn)(this.binary[binary], [...this.arguments, ...args]);
1147
1159
  let stdoutBuffer = "";
1148
1160
  let stderrBuffer = "";
@@ -1158,18 +1170,18 @@ var Engine = class {
1158
1170
  if (!isResolved) {
1159
1171
  isResolved = true;
1160
1172
  clearTimeout(timeoutId);
1161
- resolve5(response);
1173
+ resolve6(response);
1162
1174
  }
1163
1175
  };
1164
- child.stdout.on("data", (data) => {
1165
- const text = data.toString();
1166
- stdoutBuffer += text;
1167
- const visible = text.split("\n").filter((l) => l.trim() && !l.includes("PROCESS_RESPONSE:")).join("\n");
1168
- if (visible) console.log(visible);
1169
- const match = stdoutBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
1170
- if (match) {
1176
+ const tryParseLines = (buffer) => {
1177
+ let idx;
1178
+ while ((idx = buffer.indexOf("\n")) !== -1) {
1179
+ const line = buffer.slice(0, idx);
1180
+ buffer = buffer.slice(idx + 1);
1181
+ const marker = line.indexOf("PROCESS_RESPONSE:");
1182
+ if (marker === -1) continue;
1171
1183
  try {
1172
- const response = JSON.parse(match[1]);
1184
+ const response = JSON.parse(line.slice(marker + "PROCESS_RESPONSE:".length));
1173
1185
  resolveOnce({
1174
1186
  status: response.status,
1175
1187
  message: response.message,
@@ -1183,29 +1195,19 @@ var Engine = class {
1183
1195
  });
1184
1196
  }
1185
1197
  }
1198
+ return buffer;
1199
+ };
1200
+ child.stdout.on("data", (data) => {
1201
+ const text = data.toString();
1202
+ const visible = text.split("\n").filter((l) => l.trim() && !l.includes("PROCESS_RESPONSE:")).join("\n");
1203
+ if (visible) console.log(visible);
1204
+ stdoutBuffer = tryParseLines(stdoutBuffer + text);
1186
1205
  });
1187
1206
  child.stderr.on("data", (data) => {
1188
1207
  const text = data.toString();
1189
- stderrBuffer += text;
1190
1208
  const visible = text.split("\n").filter((l) => l.trim() && !l.includes("PROCESS_RESPONSE:")).join("\n");
1191
1209
  if (visible) console.log(visible);
1192
- const match = stderrBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
1193
- if (match) {
1194
- try {
1195
- const response = JSON.parse(match[1]);
1196
- resolveOnce({
1197
- status: response.status,
1198
- message: response.message,
1199
- data: response.data
1200
- });
1201
- } catch (error) {
1202
- resolveOnce({
1203
- status: 500,
1204
- message: "Failed to parse response JSON",
1205
- data: null
1206
- });
1207
- }
1208
- }
1210
+ stderrBuffer = tryParseLines(stderrBuffer + text);
1209
1211
  });
1210
1212
  child.on("close", (code) => {
1211
1213
  clearTimeout(timeoutId);
@@ -1234,13 +1236,264 @@ var Engine = class {
1234
1236
 
1235
1237
  // src/lib/QueryEngine.ts
1236
1238
  var import_path5 = __toESM(require("path"));
1239
+
1240
+ // src/lib/EmbeddedEngine.ts
1241
+ var fs4 = __toESM(require("fs"));
1242
+ var path5 = __toESM(require("path"));
1243
+ if (!process.env.UV_THREADPOOL_SIZE) {
1244
+ process.env.UV_THREADPOOL_SIZE = "16";
1245
+ }
1246
+ var backend = null;
1247
+ var loadFailed = false;
1248
+ var handles = /* @__PURE__ */ new Map();
1249
+ var connecting = /* @__PURE__ */ new Map();
1250
+ function platTag() {
1251
+ const arch2 = process.arch === "arm64" ? "arm64" : "x64";
1252
+ if (process.platform === "win32") return { plat: "windows", ext: "dll", arch: arch2 };
1253
+ if (process.platform === "darwin") return { plat: "macos", ext: "dylib", arch: arch2 };
1254
+ return { plat: "linux", ext: "so", arch: arch2 };
1255
+ }
1256
+ function findFile(name) {
1257
+ const candidates = [
1258
+ path5.resolve(process.cwd(), ".dbcube", "bin", name),
1259
+ path5.resolve(process.cwd(), "node_modules", ".dbcube", "bin", name)
1260
+ ];
1261
+ for (const c of candidates) {
1262
+ if (fs4.existsSync(c)) return c;
1263
+ }
1264
+ return null;
1265
+ }
1266
+ function ok(data) {
1267
+ return { status: 200, message: "OK", data };
1268
+ }
1269
+ function errResp(e) {
1270
+ const msg = e instanceof Error ? e.message : String(e);
1271
+ return { status: 500, message: msg, data: null };
1272
+ }
1273
+ function loadNapiBackend() {
1274
+ const { plat, arch: arch2 } = platTag();
1275
+ const addonPath = findFile(`query-engine-node-${plat}-${arch2}.node`);
1276
+ if (!addonPath) return null;
1277
+ try {
1278
+ const addon = require(addonPath);
1279
+ if (typeof addon.connect !== "function") return null;
1280
+ return {
1281
+ async connect(cfgJson) {
1282
+ return Number(await addon.connect(cfgJson));
1283
+ },
1284
+ async execute(handle, dml, txId) {
1285
+ try {
1286
+ const rows = await addon.execute(handle, dml, txId ?? void 0);
1287
+ return ok(rows);
1288
+ } catch (e) {
1289
+ return errResp(e);
1290
+ }
1291
+ },
1292
+ async executeBatch(handle, ops) {
1293
+ try {
1294
+ const results = await addon.executeBatch(handle, ops);
1295
+ return ok(results);
1296
+ } catch (e) {
1297
+ return errResp(e);
1298
+ }
1299
+ },
1300
+ async raw(handle, query, params, txId) {
1301
+ try {
1302
+ const rows = await addon.raw(handle, query, params, txId ?? void 0);
1303
+ return ok(rows);
1304
+ } catch (e) {
1305
+ return errResp(e);
1306
+ }
1307
+ },
1308
+ async begin(handle) {
1309
+ try {
1310
+ const txId = await addon.begin(handle);
1311
+ return ok({ tx_id: txId });
1312
+ } catch (e) {
1313
+ return errResp(e);
1314
+ }
1315
+ },
1316
+ async commit(_handle, txId) {
1317
+ try {
1318
+ await addon.commit(txId);
1319
+ return ok(null);
1320
+ } catch (e) {
1321
+ return errResp(e);
1322
+ }
1323
+ },
1324
+ async rollback(_handle, txId) {
1325
+ try {
1326
+ await addon.rollback(txId);
1327
+ return ok(null);
1328
+ } catch (e) {
1329
+ return errResp(e);
1330
+ }
1331
+ },
1332
+ async disconnect(handle) {
1333
+ try {
1334
+ addon.disconnect(handle);
1335
+ } catch {
1336
+ }
1337
+ }
1338
+ };
1339
+ } catch {
1340
+ return null;
1341
+ }
1342
+ }
1343
+ function loadKoffiBackend() {
1344
+ const { plat, ext, arch: arch2 } = platTag();
1345
+ const libPath = findFile(`query-engine-embedded-${plat}-${arch2}.${ext}`);
1346
+ if (!libPath) return null;
1347
+ try {
1348
+ const koffi = require("koffi");
1349
+ const lib = koffi.load(libPath);
1350
+ const cConnect = lib.func("dbc_connect", "void *", ["str"]);
1351
+ const cExecute = lib.func("dbc_execute", "void *", ["uint64", "str", "str"]);
1352
+ const cExecuteBatch = lib.func("dbc_execute_batch", "void *", ["uint64", "str"]);
1353
+ const cRaw = lib.func("dbc_raw", "void *", ["uint64", "str", "str", "str"]);
1354
+ const cBegin = lib.func("dbc_begin", "void *", ["uint64"]);
1355
+ const cCommit = lib.func("dbc_commit", "void *", ["uint64", "str"]);
1356
+ const cRollback = lib.func("dbc_rollback", "void *", ["uint64", "str"]);
1357
+ const cDisconnect = lib.func("dbc_disconnect", "void *", ["uint64"]);
1358
+ const cFree = lib.func("dbc_free", "void", ["void *"]);
1359
+ const take = (ptr) => {
1360
+ if (!ptr) return { status: 500, message: "embedded engine returned null", data: null };
1361
+ const s = koffi.decode(ptr, "char", -1);
1362
+ cFree(ptr);
1363
+ try {
1364
+ const r = JSON.parse(s);
1365
+ return { status: r.status ?? 500, message: r.message ?? "", data: r.data ?? null };
1366
+ } catch (e) {
1367
+ return { status: 500, message: `Invalid embedded response: ${e.message}`, data: null };
1368
+ }
1369
+ };
1370
+ const call = (fn, ...args) => new Promise((resolve6, reject) => {
1371
+ fn.async(...args, (err, ptr) => {
1372
+ if (err) return reject(err);
1373
+ resolve6(take(ptr));
1374
+ });
1375
+ });
1376
+ return {
1377
+ async connect(cfgJson) {
1378
+ const res = await call(cConnect, cfgJson);
1379
+ if (res.status !== 200 || !res.data?.handle) {
1380
+ throw new Error(String(res.message || "embedded connect failed"));
1381
+ }
1382
+ return Number(res.data.handle);
1383
+ },
1384
+ execute: (handle, dml, txId) => call(cExecute, handle, JSON.stringify(dml), txId),
1385
+ executeBatch: (handle, ops) => call(cExecuteBatch, handle, JSON.stringify(ops)),
1386
+ raw: (handle, query, params, txId) => call(cRaw, handle, query, JSON.stringify(params ?? []), txId),
1387
+ begin: (handle) => call(cBegin, handle),
1388
+ commit: (handle, txId) => call(cCommit, handle, txId),
1389
+ rollback: (handle, txId) => call(cRollback, handle, txId),
1390
+ async disconnect(handle) {
1391
+ try {
1392
+ await call(cDisconnect, handle);
1393
+ } catch {
1394
+ }
1395
+ }
1396
+ };
1397
+ } catch {
1398
+ return null;
1399
+ }
1400
+ }
1401
+ function loadBackend() {
1402
+ if (backend) return backend;
1403
+ if (loadFailed) return null;
1404
+ if (process.env.DBCUBE_EMBEDDED === "0" || process.env.DBCUBE_EMBEDDED === "false") {
1405
+ loadFailed = true;
1406
+ return null;
1407
+ }
1408
+ backend = loadNapiBackend() ?? loadKoffiBackend();
1409
+ if (!backend) loadFailed = true;
1410
+ return backend;
1411
+ }
1412
+ var EmbeddedEngine = class {
1413
+ /** true si algún backend nativo está disponible en esta instalación. */
1414
+ static available() {
1415
+ return loadBackend() !== null;
1416
+ }
1417
+ static async handleFor(connectionId, config) {
1418
+ const existing = handles.get(connectionId);
1419
+ if (existing) return existing;
1420
+ const inFlight = connecting.get(connectionId);
1421
+ if (inFlight) return inFlight;
1422
+ const promise = (async () => {
1423
+ const be = loadBackend();
1424
+ if (!be) throw new Error("embedded engine not available");
1425
+ const motor = config.type === "postgres" ? "postgresql" : config.type;
1426
+ const cfg = {
1427
+ databaseRef: connectionId,
1428
+ motor,
1429
+ database: config.type === "sqlite" ? `${config.config.DATABASE}.db` : config.config.DATABASE,
1430
+ host: config.config.HOST,
1431
+ port: config.config.PORT != null ? Number(config.config.PORT) : void 0,
1432
+ user: config.config.USER,
1433
+ password: config.config.PASSWORD,
1434
+ maxConnections: config.pool?.maxConnections,
1435
+ minConnections: config.pool?.minConnections,
1436
+ acquireTimeoutMs: config.pool?.acquireTimeoutMs,
1437
+ idleTimeoutMs: config.pool?.idleTimeoutMs
1438
+ };
1439
+ const handle = await be.connect(JSON.stringify(cfg));
1440
+ handles.set(connectionId, handle);
1441
+ return handle;
1442
+ })();
1443
+ connecting.set(connectionId, promise);
1444
+ try {
1445
+ return await promise;
1446
+ } finally {
1447
+ connecting.delete(connectionId);
1448
+ }
1449
+ }
1450
+ static async executeDml(connectionId, config, dml, txId) {
1451
+ const be = loadBackend();
1452
+ const handle = await this.handleFor(connectionId, config);
1453
+ return be.execute(handle, dml, txId ?? null);
1454
+ }
1455
+ static async executeBatch(connectionId, config, ops) {
1456
+ const be = loadBackend();
1457
+ const handle = await this.handleFor(connectionId, config);
1458
+ return be.executeBatch(handle, ops);
1459
+ }
1460
+ static async rawQuery(connectionId, config, query, params, txId) {
1461
+ const be = loadBackend();
1462
+ const handle = await this.handleFor(connectionId, config);
1463
+ return be.raw(handle, query, params ?? [], txId ?? null);
1464
+ }
1465
+ static async begin(connectionId, config) {
1466
+ const be = loadBackend();
1467
+ const handle = await this.handleFor(connectionId, config);
1468
+ return be.begin(handle);
1469
+ }
1470
+ static async commit(connectionId, config, txId) {
1471
+ const be = loadBackend();
1472
+ const handle = await this.handleFor(connectionId, config);
1473
+ return be.commit(handle, txId);
1474
+ }
1475
+ static async rollback(connectionId, config, txId) {
1476
+ const be = loadBackend();
1477
+ const handle = await this.handleFor(connectionId, config);
1478
+ return be.rollback(handle, txId);
1479
+ }
1480
+ static async disconnect(connectionId) {
1481
+ const be = loadBackend();
1482
+ const handle = handles.get(connectionId);
1483
+ if (be && handle) {
1484
+ handles.delete(connectionId);
1485
+ await be.disconnect(handle);
1486
+ }
1487
+ }
1488
+ };
1489
+
1490
+ // src/lib/QueryEngine.ts
1237
1491
  var import_module2 = require("module");
1238
1492
  var net2 = __toESM(require("net"));
1239
1493
  var import_child_process3 = require("child_process");
1240
1494
  var globalTcpServers = /* @__PURE__ */ new Map();
1241
- var globalTcpConnections = /* @__PURE__ */ new Map();
1242
- var connectionQueues = /* @__PURE__ */ new Map();
1243
- var connectionProcessing = /* @__PURE__ */ new Map();
1495
+ var socketPools = /* @__PURE__ */ new Map();
1496
+ var CLIENT_POOL_SIZE = 10;
1244
1497
  var queryCache = /* @__PURE__ */ new Map();
1245
1498
  var MAX_CACHE_SIZE = 500;
1246
1499
  var QueryEngine = class {
@@ -1271,12 +1524,12 @@ var QueryEngine = class {
1271
1524
  throw new Error("No available ports found in range 9900-9944");
1272
1525
  }
1273
1526
  isPortAvailable(port) {
1274
- return new Promise((resolve5) => {
1527
+ return new Promise((resolve6) => {
1275
1528
  const tester = net2.createServer();
1276
- tester.once("error", () => resolve5(false));
1529
+ tester.once("error", () => resolve6(false));
1277
1530
  tester.once("listening", () => {
1278
1531
  tester.close();
1279
- resolve5(true);
1532
+ resolve6(true);
1280
1533
  });
1281
1534
  tester.listen(port, "127.0.0.1");
1282
1535
  });
@@ -1383,38 +1636,79 @@ var QueryEngine = class {
1383
1636
  }
1384
1637
  return command;
1385
1638
  }
1639
+ /** El motor embebido (FFI) es el camino por defecto cuando la librería
1640
+ * nativa está disponible; el daemon TCP queda como fallback y como modo
1641
+ * multi-proceso explícito. */
1642
+ useEmbedded() {
1643
+ return EmbeddedEngine.available();
1644
+ }
1386
1645
  /**
1387
- * Executes a DML plan over the persistent TCP server.
1646
+ * Executes a DML plan. Embedded engine when available (in-process FFI,
1647
+ * no network hop); persistent TCP daemon otherwise.
1388
1648
  * Pass txId to run it inside an active transaction.
1389
1649
  */
1390
1650
  async executeDml(dml, txId) {
1391
- const command = { action: "execute", dml: JSON.stringify(dml) };
1651
+ if (this.useEmbedded()) {
1652
+ return EmbeddedEngine.executeDml(this.connectionId, this.config, dml, txId);
1653
+ }
1654
+ const command = { action: "execute", dml };
1392
1655
  if (txId) command.tx_id = txId;
1393
1656
  return this.executeWithTcpServer(command);
1394
1657
  }
1395
1658
  /**
1396
- * Executes raw SQL (or a MongoDB command document) with bound parameters
1397
- * over the persistent TCP server.
1659
+ * Atomic batch: N write plans inside one transaction with a single
1660
+ * engine round-trip. Falls back to begin/ops/commit over the daemon
1661
+ * when the embedded engine is not available.
1662
+ */
1663
+ async executeBatch(ops) {
1664
+ if (this.useEmbedded()) {
1665
+ return EmbeddedEngine.executeBatch(this.connectionId, this.config, ops);
1666
+ }
1667
+ const txId = await this.beginTransaction();
1668
+ try {
1669
+ const results = [];
1670
+ for (const op of ops) {
1671
+ const res = await this.executeDml(op, txId);
1672
+ if (res.status !== 200) {
1673
+ throw new Error(String(res.message));
1674
+ }
1675
+ results.push(res.data);
1676
+ }
1677
+ await this.commitTransaction(txId);
1678
+ return { status: 200, message: "Batch committed", data: results };
1679
+ } catch (error) {
1680
+ try {
1681
+ await this.rollbackTransaction(txId);
1682
+ } catch {
1683
+ }
1684
+ return { status: 500, message: error?.message ?? String(error), data: null };
1685
+ }
1686
+ }
1687
+ /**
1688
+ * Executes raw SQL (or a MongoDB command document) with bound parameters.
1398
1689
  */
1399
1690
  async rawQuery(query, params = [], txId) {
1691
+ if (this.useEmbedded()) {
1692
+ return EmbeddedEngine.rawQuery(this.connectionId, this.config, query, params, txId);
1693
+ }
1400
1694
  const command = { action: "raw", query, params };
1401
1695
  if (txId) command.tx_id = txId;
1402
1696
  return this.executeWithTcpServer(command);
1403
1697
  }
1404
- /** Starts a server-side transaction and returns its id. */
1698
+ /** Starts a transaction and returns its id. */
1405
1699
  async beginTransaction() {
1406
- const res = await this.executeWithTcpServer({ action: "begin" });
1700
+ const res = this.useEmbedded() ? await EmbeddedEngine.begin(this.connectionId, this.config) : await this.executeWithTcpServer({ action: "begin" });
1407
1701
  if (res.status !== 200 || !res.data?.tx_id) {
1408
1702
  throw new Error(String(res.message || "Failed to begin transaction (update the query-engine binary: npx dbcube update)"));
1409
1703
  }
1410
1704
  return res.data.tx_id;
1411
1705
  }
1412
1706
  async commitTransaction(txId) {
1413
- const res = await this.executeWithTcpServer({ action: "commit", tx_id: txId });
1707
+ const res = this.useEmbedded() ? await EmbeddedEngine.commit(this.connectionId, this.config, txId) : await this.executeWithTcpServer({ action: "commit", tx_id: txId });
1414
1708
  if (res.status !== 200) throw new Error(String(res.message || "Failed to commit transaction"));
1415
1709
  }
1416
1710
  async rollbackTransaction(txId) {
1417
- const res = await this.executeWithTcpServer({ action: "rollback", tx_id: txId });
1711
+ const res = this.useEmbedded() ? await EmbeddedEngine.rollback(this.connectionId, this.config, txId) : await this.executeWithTcpServer({ action: "rollback", tx_id: txId });
1418
1712
  if (res.status !== 200) throw new Error(String(res.message || "Failed to rollback transaction"));
1419
1713
  }
1420
1714
  async executeWithTcpServer(command) {
@@ -1433,7 +1727,63 @@ var QueryEngine = class {
1433
1727
  await this.startTcpServer();
1434
1728
  await this.waitForServerReady();
1435
1729
  }
1436
- return this.sendTcpRequestFast(command);
1730
+ const port = globalTcpServers.get(this.connectionId).port;
1731
+ const socket = await this.acquireSocket(port);
1732
+ try {
1733
+ const result = await this.executeOnConnection(socket, command);
1734
+ this.releaseSocket(socket, false);
1735
+ return result;
1736
+ } catch (error) {
1737
+ this.releaseSocket(socket, true);
1738
+ throw error;
1739
+ }
1740
+ }
1741
+ poolFor() {
1742
+ let pool = socketPools.get(this.connectionId);
1743
+ if (!pool) {
1744
+ pool = { free: [], total: 0, waiters: [] };
1745
+ socketPools.set(this.connectionId, pool);
1746
+ }
1747
+ return pool;
1748
+ }
1749
+ async acquireSocket(port) {
1750
+ const pool = this.poolFor();
1751
+ while (pool.free.length > 0) {
1752
+ const s = pool.free.pop();
1753
+ if (!s.destroyed) return s;
1754
+ pool.total--;
1755
+ }
1756
+ if (pool.total < CLIENT_POOL_SIZE) {
1757
+ pool.total++;
1758
+ try {
1759
+ return await this.createNewConnection(port);
1760
+ } catch (e) {
1761
+ pool.total--;
1762
+ throw e;
1763
+ }
1764
+ }
1765
+ return new Promise((resolve6) => pool.waiters.push(resolve6));
1766
+ }
1767
+ releaseSocket(socket, broken) {
1768
+ const pool = socketPools.get(this.connectionId);
1769
+ if (!pool) {
1770
+ socket.destroy();
1771
+ return;
1772
+ }
1773
+ if (broken || socket.destroyed) {
1774
+ pool.total--;
1775
+ try {
1776
+ socket.destroy();
1777
+ } catch {
1778
+ }
1779
+ return;
1780
+ }
1781
+ const waiter = pool.waiters.shift();
1782
+ if (waiter) {
1783
+ waiter(socket);
1784
+ } else {
1785
+ pool.free.push(socket);
1786
+ }
1437
1787
  }
1438
1788
  async waitForServerReady() {
1439
1789
  const maxRetries = 10;
@@ -1451,25 +1801,25 @@ var QueryEngine = class {
1451
1801
  throw new Error("TCP server failed to become ready within timeout");
1452
1802
  }
1453
1803
  async isServerResponding(port) {
1454
- return new Promise((resolve5) => {
1804
+ return new Promise((resolve6) => {
1455
1805
  const client = new net2.Socket();
1456
1806
  const timeout = setTimeout(() => {
1457
1807
  client.destroy();
1458
- resolve5(false);
1808
+ resolve6(false);
1459
1809
  }, 1e3);
1460
1810
  client.connect(port, "127.0.0.1", () => {
1461
1811
  clearTimeout(timeout);
1462
1812
  client.destroy();
1463
- resolve5(true);
1813
+ resolve6(true);
1464
1814
  });
1465
1815
  client.on("error", () => {
1466
1816
  clearTimeout(timeout);
1467
- resolve5(false);
1817
+ resolve6(false);
1468
1818
  });
1469
1819
  });
1470
1820
  }
1471
1821
  sleep(ms) {
1472
- return new Promise((resolve5) => setTimeout(resolve5, ms));
1822
+ return new Promise((resolve6) => setTimeout(resolve6, ms));
1473
1823
  }
1474
1824
  getCachedDML(dmlJson) {
1475
1825
  if (queryCache.has(dmlJson)) {
@@ -1489,7 +1839,7 @@ var QueryEngine = class {
1489
1839
  throw new Error("Binary not initialized");
1490
1840
  }
1491
1841
  this.tcpPort = await this.findAvailablePort(this.tcpPort);
1492
- return new Promise((resolve5, reject) => {
1842
+ return new Promise((resolve6, reject) => {
1493
1843
  const serverArgs = [...this.arguments, "--action", "server", "--tcp-port", this.tcpPort.toString()];
1494
1844
  const serverProcess = (0, import_child_process3.spawn)(this.binary["query_engine"], serverArgs);
1495
1845
  let started = false;
@@ -1509,7 +1859,7 @@ var QueryEngine = class {
1509
1859
  port: this.tcpPort,
1510
1860
  process: serverProcess
1511
1861
  });
1512
- resolve5();
1862
+ resolve6();
1513
1863
  }
1514
1864
  }
1515
1865
  });
@@ -1527,60 +1877,8 @@ var QueryEngine = class {
1527
1877
  });
1528
1878
  });
1529
1879
  }
1530
- async sendTcpRequestFast(command) {
1531
- return new Promise((resolve5, reject) => {
1532
- let queue = connectionQueues.get(this.connectionId);
1533
- if (!queue) {
1534
- queue = [];
1535
- connectionQueues.set(this.connectionId, queue);
1536
- }
1537
- queue.push({ command, resolve: resolve5, reject });
1538
- this.processQueue();
1539
- });
1540
- }
1541
- async processQueue() {
1542
- if (connectionProcessing.get(this.connectionId)) {
1543
- return;
1544
- }
1545
- const queue = connectionQueues.get(this.connectionId);
1546
- if (!queue || queue.length === 0) {
1547
- return;
1548
- }
1549
- connectionProcessing.set(this.connectionId, true);
1550
- try {
1551
- const serverInfo = globalTcpServers.get(this.connectionId);
1552
- if (!serverInfo) {
1553
- throw new Error("Server not initialized");
1554
- }
1555
- while (queue.length > 0) {
1556
- const request = queue.shift();
1557
- if (!request) break;
1558
- try {
1559
- let connection = globalTcpConnections.get(this.connectionId);
1560
- if (!connection || connection.destroyed || connection.readyState !== "open") {
1561
- connection = await this.createNewConnection(serverInfo.port);
1562
- globalTcpConnections.set(this.connectionId, connection);
1563
- }
1564
- const result = await this.executeOnConnection(connection, request.command);
1565
- request.resolve(result);
1566
- } catch (error) {
1567
- const staleConnection = globalTcpConnections.get(this.connectionId);
1568
- if (staleConnection) {
1569
- try {
1570
- staleConnection.destroy();
1571
- } catch {
1572
- }
1573
- }
1574
- globalTcpConnections.delete(this.connectionId);
1575
- request.reject(error);
1576
- }
1577
- }
1578
- } finally {
1579
- connectionProcessing.set(this.connectionId, false);
1580
- }
1581
- }
1582
1880
  async createNewConnection(port) {
1583
- return new Promise((resolve5, reject) => {
1881
+ return new Promise((resolve6, reject) => {
1584
1882
  const client = new net2.Socket();
1585
1883
  client.setNoDelay(true);
1586
1884
  client.setKeepAlive(true, 6e4);
@@ -1590,7 +1888,7 @@ var QueryEngine = class {
1590
1888
  }, 5e3);
1591
1889
  client.connect(port, "127.0.0.1", () => {
1592
1890
  clearTimeout(timeout);
1593
- resolve5(client);
1891
+ resolve6(client);
1594
1892
  });
1595
1893
  client.on("error", (error) => {
1596
1894
  clearTimeout(timeout);
@@ -1599,7 +1897,7 @@ var QueryEngine = class {
1599
1897
  });
1600
1898
  }
1601
1899
  async executeOnConnection(connection, command) {
1602
- return new Promise((resolve5, reject) => {
1900
+ return new Promise((resolve6, reject) => {
1603
1901
  let responseBuffer = "";
1604
1902
  let isResolved = false;
1605
1903
  const timeout = setTimeout(() => {
@@ -1612,15 +1910,19 @@ var QueryEngine = class {
1612
1910
  }, this.timeout);
1613
1911
  const onData = (data) => {
1614
1912
  responseBuffer += data.toString();
1615
- const match = responseBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
1616
- if (match && !isResolved) {
1913
+ let idx;
1914
+ while ((idx = responseBuffer.indexOf("\n")) !== -1 && !isResolved) {
1915
+ const line = responseBuffer.slice(0, idx);
1916
+ responseBuffer = responseBuffer.slice(idx + 1);
1917
+ const marker = line.indexOf("PROCESS_RESPONSE:");
1918
+ if (marker === -1) continue;
1617
1919
  isResolved = true;
1618
1920
  clearTimeout(timeout);
1619
1921
  connection.removeListener("data", onData);
1620
1922
  connection.removeListener("error", onError);
1621
1923
  try {
1622
- const response = JSON.parse(match[1]);
1623
- resolve5({
1924
+ const response = JSON.parse(line.slice(marker + "PROCESS_RESPONSE:".length));
1925
+ resolve6({
1624
1926
  status: response.status,
1625
1927
  message: response.message,
1626
1928
  data: response.data
@@ -1649,7 +1951,7 @@ var QueryEngine = class {
1649
1951
  if (!this.binary) {
1650
1952
  throw new Error("Binary not initialized");
1651
1953
  }
1652
- return new Promise((resolve5, reject) => {
1954
+ return new Promise((resolve6, reject) => {
1653
1955
  const child = (0, import_child_process3.spawn)(this.binary[binary], [...this.arguments, ...args]);
1654
1956
  let stdoutBuffer = "";
1655
1957
  let stderrBuffer = "";
@@ -1665,15 +1967,18 @@ var QueryEngine = class {
1665
1967
  if (!isResolved) {
1666
1968
  isResolved = true;
1667
1969
  clearTimeout(timeoutId);
1668
- resolve5(response);
1970
+ resolve6(response);
1669
1971
  }
1670
1972
  };
1671
- child.stdout.on("data", (data) => {
1672
- stdoutBuffer += data.toString();
1673
- const match = stdoutBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
1674
- if (match) {
1973
+ const tryParseLines = (buffer) => {
1974
+ let idx;
1975
+ while ((idx = buffer.indexOf("\n")) !== -1) {
1976
+ const line = buffer.slice(0, idx);
1977
+ buffer = buffer.slice(idx + 1);
1978
+ const marker = line.indexOf("PROCESS_RESPONSE:");
1979
+ if (marker === -1) continue;
1675
1980
  try {
1676
- const response = JSON.parse(match[1]);
1981
+ const response = JSON.parse(line.slice(marker + "PROCESS_RESPONSE:".length));
1677
1982
  resolveOnce({
1678
1983
  status: response.status,
1679
1984
  message: response.message,
@@ -1687,26 +1992,13 @@ var QueryEngine = class {
1687
1992
  });
1688
1993
  }
1689
1994
  }
1995
+ return buffer;
1996
+ };
1997
+ child.stdout.on("data", (data) => {
1998
+ stdoutBuffer = tryParseLines(stdoutBuffer + data.toString());
1690
1999
  });
1691
2000
  child.stderr.on("data", (data) => {
1692
- stderrBuffer += data.toString();
1693
- const match = stderrBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
1694
- if (match) {
1695
- try {
1696
- const response = JSON.parse(match[1]);
1697
- resolveOnce({
1698
- status: response.status,
1699
- message: response.message,
1700
- data: response.data
1701
- });
1702
- } catch (error) {
1703
- resolveOnce({
1704
- status: 500,
1705
- message: "Failed to parse response JSON",
1706
- data: null
1707
- });
1708
- }
1709
- }
2001
+ stderrBuffer = tryParseLines(stderrBuffer + data.toString());
1710
2002
  });
1711
2003
  child.on("close", (code) => {
1712
2004
  clearTimeout(timeoutId);
@@ -1732,11 +2024,16 @@ var QueryEngine = class {
1732
2024
  });
1733
2025
  }
1734
2026
  async disconnect() {
1735
- const connection = globalTcpConnections.get(this.connectionId);
1736
- if (connection && connection.readyState === "open") {
1737
- connection.write(JSON.stringify({ action: "disconnect" }));
1738
- connection.destroy();
1739
- globalTcpConnections.delete(this.connectionId);
2027
+ await EmbeddedEngine.disconnect(this.connectionId);
2028
+ const pool = socketPools.get(this.connectionId);
2029
+ if (pool) {
2030
+ for (const s of pool.free) {
2031
+ try {
2032
+ s.destroy();
2033
+ } catch {
2034
+ }
2035
+ }
2036
+ socketPools.delete(this.connectionId);
1740
2037
  }
1741
2038
  const serverInfo = globalTcpServers.get(this.connectionId);
1742
2039
  if (serverInfo && serverInfo.process && !serverInfo.process.killed) {
@@ -1758,8 +2055,8 @@ var QueryEngine = class {
1758
2055
 
1759
2056
  // src/lib/SqliteExecutor.ts
1760
2057
  var import_child_process4 = require("child_process");
1761
- var path6 = __toESM(require("path"));
1762
- var fs4 = __toESM(require("fs"));
2058
+ var path7 = __toESM(require("path"));
2059
+ var fs5 = __toESM(require("fs"));
1763
2060
  var import_util = require("util");
1764
2061
  var import_module3 = require("module");
1765
2062
  var import_url3 = require("url");
@@ -1775,13 +2072,13 @@ var SqliteExecutor = class {
1775
2072
  }
1776
2073
  findVersionedBinary(binDir, platform2) {
1777
2074
  try {
1778
- const files = fs4.readdirSync(binDir);
2075
+ const files = fs5.readdirSync(binDir);
1779
2076
  const extension = platform2 === "win32" ? ".exe" : "";
1780
2077
  const platformName = platform2 === "win32" ? "windows" : platform2 === "darwin" ? "macos" : "linux";
1781
2078
  const pattern = new RegExp(`^sqlite-engine-v\\d+\\.\\d+\\.\\d+-${platformName}-x64${extension.replace(".", "\\.")}$`);
1782
2079
  const matchingFile = files.find((f) => pattern.test(f));
1783
2080
  if (matchingFile) {
1784
- return path6.join(binDir, matchingFile);
2081
+ return path7.join(binDir, matchingFile);
1785
2082
  }
1786
2083
  } catch (error) {
1787
2084
  }
@@ -1791,34 +2088,34 @@ var SqliteExecutor = class {
1791
2088
  const __filename2 = typeof import_meta3 !== "undefined" && import_meta3.url ? (0, import_url3.fileURLToPath)(import_meta3.url) : "";
1792
2089
  const __dirname = __filename2 ? (0, import_path6.dirname)(__filename2) : process.cwd();
1793
2090
  const possibleDirs = [
1794
- path6.resolve(process.cwd(), ".dbcube", "bin"),
1795
- path6.resolve(process.cwd(), "node_modules", ".dbcube", "bin"),
1796
- path6.resolve(__dirname, "..", "bin")
2091
+ path7.resolve(process.cwd(), ".dbcube", "bin"),
2092
+ path7.resolve(process.cwd(), "node_modules", ".dbcube", "bin"),
2093
+ path7.resolve(__dirname, "..", "bin")
1797
2094
  ];
1798
2095
  const platform2 = process.platform;
1799
2096
  const extension = platform2 === "win32" ? ".exe" : "";
1800
2097
  const platformName = platform2 === "win32" ? "windows" : platform2 === "darwin" ? "macos" : "linux";
1801
2098
  for (const dir of possibleDirs) {
1802
2099
  const versionedPath = this.findVersionedBinary(dir, platform2);
1803
- if (versionedPath && fs4.existsSync(versionedPath)) {
2100
+ if (versionedPath && fs5.existsSync(versionedPath)) {
1804
2101
  return versionedPath;
1805
2102
  }
1806
2103
  }
1807
2104
  const binaryName = `sqlite-engine-${platformName}-x64${extension}`;
1808
2105
  for (const dir of possibleDirs) {
1809
- const fullPath = path6.join(dir, binaryName);
1810
- if (fs4.existsSync(fullPath)) {
2106
+ const fullPath = path7.join(dir, binaryName);
2107
+ if (fs5.existsSync(fullPath)) {
1811
2108
  return fullPath;
1812
2109
  }
1813
2110
  }
1814
2111
  const fallbackName = `sqlite-engine${extension}`;
1815
2112
  for (const dir of possibleDirs) {
1816
- const fullPath = path6.join(dir, fallbackName);
1817
- if (fs4.existsSync(fullPath)) {
2113
+ const fullPath = path7.join(dir, fallbackName);
2114
+ if (fs5.existsSync(fullPath)) {
1818
2115
  return fullPath;
1819
2116
  }
1820
2117
  }
1821
- return path6.join(possibleDirs[0], binaryName);
2118
+ return path7.join(possibleDirs[0], binaryName);
1822
2119
  }
1823
2120
  async executeBinary(args) {
1824
2121
  const escapedArgs = args.map((arg) => {
@@ -1969,9 +2266,9 @@ var SqliteExecutor = class {
1969
2266
  };
1970
2267
 
1971
2268
  // src/lib/DbConfig.ts
1972
- var path7 = __toESM(require("path"));
2269
+ var path8 = __toESM(require("path"));
1973
2270
  var import_fs2 = __toESM(require("fs"));
1974
- var rootPath = path7.resolve(process.cwd(), ".dbcube");
2271
+ var rootPath = path8.resolve(process.cwd(), ".dbcube");
1975
2272
  var SQLite = class {
1976
2273
  executor = null;
1977
2274
  database;
@@ -1981,7 +2278,7 @@ var SQLite = class {
1981
2278
  async ifExist() {
1982
2279
  if (this.database) {
1983
2280
  const dbPath = this.database || ":memory:";
1984
- const configPath = path7.join(rootPath, dbPath + ".db");
2281
+ const configPath = path8.join(rootPath, dbPath + ".db");
1985
2282
  if (!import_fs2.default.existsSync(rootPath)) {
1986
2283
  import_fs2.default.mkdirSync(rootPath, { recursive: true });
1987
2284
  }
@@ -1996,11 +2293,11 @@ var SQLite = class {
1996
2293
  return false;
1997
2294
  }
1998
2295
  async connect() {
1999
- return new Promise(async (resolve5, reject) => {
2296
+ return new Promise(async (resolve6, reject) => {
2000
2297
  try {
2001
2298
  if (!this.executor) {
2002
2299
  const dbPath = this.database || ":memory:";
2003
- const configPath = path7.join(rootPath, dbPath + ".db");
2300
+ const configPath = path8.join(rootPath, dbPath + ".db");
2004
2301
  if (!import_fs2.default.existsSync(rootPath)) {
2005
2302
  import_fs2.default.mkdirSync(rootPath, { recursive: true });
2006
2303
  }
@@ -2010,22 +2307,22 @@ var SQLite = class {
2010
2307
  throw new Error("Failed to connect to SQLite database");
2011
2308
  }
2012
2309
  }
2013
- resolve5(this.executor);
2310
+ resolve6(this.executor);
2014
2311
  } catch (error) {
2015
2312
  reject(error);
2016
2313
  }
2017
2314
  });
2018
2315
  }
2019
2316
  async disconnect() {
2020
- return new Promise((resolve5) => {
2317
+ return new Promise((resolve6) => {
2021
2318
  if (this.executor) {
2022
2319
  this.executor = null;
2023
2320
  }
2024
- resolve5();
2321
+ resolve6();
2025
2322
  });
2026
2323
  }
2027
2324
  async query(sqlQuery) {
2028
- return new Promise(async (resolve5) => {
2325
+ return new Promise(async (resolve6) => {
2029
2326
  try {
2030
2327
  if (typeof sqlQuery !== "string") {
2031
2328
  throw new Error("The SQL query must be a string.");
@@ -2038,20 +2335,20 @@ var SQLite = class {
2038
2335
  }
2039
2336
  const result = await this.executor.queryMultiple(sqlQuery);
2040
2337
  if (result.status === "error") {
2041
- resolve5({
2338
+ resolve6({
2042
2339
  status: "error",
2043
2340
  message: result.message,
2044
2341
  data: null
2045
2342
  });
2046
2343
  } else {
2047
- resolve5({
2344
+ resolve6({
2048
2345
  status: "success",
2049
2346
  message: "Query executed successfully",
2050
2347
  data: result.data
2051
2348
  });
2052
2349
  }
2053
2350
  } catch (error) {
2054
- resolve5({
2351
+ resolve6({
2055
2352
  status: "error",
2056
2353
  message: error.message || "An error occurred while executing the query.",
2057
2354
  data: null
@@ -2060,7 +2357,7 @@ var SQLite = class {
2060
2357
  });
2061
2358
  }
2062
2359
  async queryWithParameters(sqlQuery, params = []) {
2063
- return new Promise(async (resolve5) => {
2360
+ return new Promise(async (resolve6) => {
2064
2361
  try {
2065
2362
  if (typeof sqlQuery !== "string") {
2066
2363
  throw new Error("The SQL query must be a string.");
@@ -2076,13 +2373,13 @@ var SQLite = class {
2076
2373
  }
2077
2374
  const result = await this.executor.query(sqlQuery, params);
2078
2375
  if (result.status === "error") {
2079
- resolve5({
2376
+ resolve6({
2080
2377
  status: "error",
2081
2378
  message: result.message,
2082
2379
  data: null
2083
2380
  });
2084
2381
  } else {
2085
- resolve5({
2382
+ resolve6({
2086
2383
  status: "success",
2087
2384
  message: "Query executed successfully",
2088
2385
  data: result.data
@@ -2090,7 +2387,7 @@ var SQLite = class {
2090
2387
  }
2091
2388
  } catch (error) {
2092
2389
  console.log(error);
2093
- resolve5({
2390
+ resolve6({
2094
2391
  status: "error",
2095
2392
  message: error.message || "An error occurred while executing the query.",
2096
2393
  data: null
@@ -2184,8 +2481,8 @@ var DbConfig = new SQLite({ DATABASE: "config" });
2184
2481
  var DbConfig_default = DbConfig;
2185
2482
 
2186
2483
  // src/lib/FileLogger.ts
2187
- var fs6 = __toESM(require("fs"));
2188
- var path8 = __toESM(require("path"));
2484
+ var fs7 = __toESM(require("fs"));
2485
+ var path9 = __toESM(require("path"));
2189
2486
  var import_events = require("events");
2190
2487
  var FileLogger = class _FileLogger extends import_events.EventEmitter {
2191
2488
  static watchers = /* @__PURE__ */ new Map();
@@ -2200,9 +2497,9 @@ var FileLogger = class _FileLogger extends import_events.EventEmitter {
2200
2497
  */
2201
2498
  static async write(filePath, message, level = "INFO", append = true) {
2202
2499
  try {
2203
- const dir = path8.dirname(filePath);
2204
- if (!fs6.existsSync(dir)) {
2205
- fs6.mkdirSync(dir, { recursive: true });
2500
+ const dir = path9.dirname(filePath);
2501
+ if (!fs7.existsSync(dir)) {
2502
+ fs7.mkdirSync(dir, { recursive: true });
2206
2503
  }
2207
2504
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
2208
2505
  const formattedMessage = `[${timestamp}] [${level}] ${message}
@@ -2212,9 +2509,9 @@ var FileLogger = class _FileLogger extends import_events.EventEmitter {
2212
2509
  return true;
2213
2510
  }
2214
2511
  if (append) {
2215
- await fs6.promises.appendFile(filePath, formattedMessage, "utf8");
2512
+ await fs7.promises.appendFile(filePath, formattedMessage, "utf8");
2216
2513
  } else {
2217
- await fs6.promises.writeFile(filePath, formattedMessage, "utf8");
2514
+ await fs7.promises.writeFile(filePath, formattedMessage, "utf8");
2218
2515
  }
2219
2516
  return true;
2220
2517
  } catch (error) {
@@ -2239,12 +2536,12 @@ var FileLogger = class _FileLogger extends import_events.EventEmitter {
2239
2536
  const buffer = _FileLogger.buffers.get(filePath);
2240
2537
  if (buffer && buffer.length > 0) {
2241
2538
  try {
2242
- const dir = path8.dirname(filePath);
2243
- if (!fs6.existsSync(dir)) {
2244
- fs6.mkdirSync(dir, { recursive: true });
2539
+ const dir = path9.dirname(filePath);
2540
+ if (!fs7.existsSync(dir)) {
2541
+ fs7.mkdirSync(dir, { recursive: true });
2245
2542
  }
2246
2543
  const content = buffer.join("");
2247
- await fs6.promises.appendFile(filePath, content, "utf8");
2544
+ await fs7.promises.appendFile(filePath, content, "utf8");
2248
2545
  _FileLogger.buffers.delete(filePath);
2249
2546
  return true;
2250
2547
  } catch (error) {
@@ -2380,10 +2677,10 @@ var FileLogger = class _FileLogger extends import_events.EventEmitter {
2380
2677
  // Si debe retornar como array de líneas
2381
2678
  } = options;
2382
2679
  try {
2383
- if (!fs6.existsSync(filePath)) {
2680
+ if (!fs7.existsSync(filePath)) {
2384
2681
  return asArray ? [] : "";
2385
2682
  }
2386
- let content = await fs6.promises.readFile(filePath, "utf8");
2683
+ let content = await fs7.promises.readFile(filePath, "utf8");
2387
2684
  if (asArray) {
2388
2685
  let linesArray = content.split("\n").filter((line) => line.trim() !== "");
2389
2686
  if (lines !== null) {
@@ -2426,15 +2723,15 @@ var FileLogger = class _FileLogger extends import_events.EventEmitter {
2426
2723
  } = options;
2427
2724
  let lastSize = 0;
2428
2725
  let lastPosition = 0;
2429
- if (fs6.existsSync(filePath)) {
2430
- const stats = fs6.statSync(filePath);
2726
+ if (fs7.existsSync(filePath)) {
2727
+ const stats = fs7.statSync(filePath);
2431
2728
  lastSize = stats.size;
2432
2729
  lastPosition = fromEnd ? stats.size : 0;
2433
2730
  }
2434
2731
  const listener = async (curr, prev) => {
2435
2732
  try {
2436
2733
  if (curr.size > lastSize) {
2437
- const stream = fs6.createReadStream(filePath, {
2734
+ const stream = fs7.createReadStream(filePath, {
2438
2735
  start: lastPosition,
2439
2736
  end: curr.size - 1,
2440
2737
  encoding: "utf8"
@@ -2462,7 +2759,7 @@ var FileLogger = class _FileLogger extends import_events.EventEmitter {
2462
2759
  console.error("Error en watcher:", error);
2463
2760
  }
2464
2761
  };
2465
- fs6.watchFile(filePath, { persistent, interval }, listener);
2762
+ fs7.watchFile(filePath, { persistent, interval }, listener);
2466
2763
  const watcherId = `${filePath}_${Date.now()}`;
2467
2764
  _FileLogger.watchers.set(watcherId, listener);
2468
2765
  return {
@@ -2470,7 +2767,7 @@ var FileLogger = class _FileLogger extends import_events.EventEmitter {
2470
2767
  stop: () => {
2471
2768
  const storedListener = _FileLogger.watchers.get(watcherId);
2472
2769
  if (storedListener) {
2473
- fs6.unwatchFile(filePath, storedListener);
2770
+ fs7.unwatchFile(filePath, storedListener);
2474
2771
  _FileLogger.watchers.delete(watcherId);
2475
2772
  }
2476
2773
  },
@@ -2483,7 +2780,7 @@ var FileLogger = class _FileLogger extends import_events.EventEmitter {
2483
2780
  static stopAllWatchers() {
2484
2781
  for (const [watcherId] of _FileLogger.watchers) {
2485
2782
  const filePath = watcherId.split("_")[0];
2486
- fs6.unwatchFile(filePath);
2783
+ fs7.unwatchFile(filePath);
2487
2784
  }
2488
2785
  _FileLogger.watchers.clear();
2489
2786
  }
@@ -2513,7 +2810,7 @@ var FileLogger = class _FileLogger extends import_events.EventEmitter {
2513
2810
  if (lines.length > maxLines) {
2514
2811
  const keepLines = lines.slice(-maxLines);
2515
2812
  const content = keepLines.join("\n") + "\n";
2516
- await fs6.promises.writeFile(filePath, content, "utf8");
2813
+ await fs7.promises.writeFile(filePath, content, "utf8");
2517
2814
  return lines.length - maxLines;
2518
2815
  }
2519
2816
  return 0;
@@ -2528,8 +2825,8 @@ var FileLogger = class _FileLogger extends import_events.EventEmitter {
2528
2825
  */
2529
2826
  static async deleteLogFile(filePath) {
2530
2827
  try {
2531
- if (fs6.existsSync(filePath)) {
2532
- await fs6.promises.unlink(filePath);
2828
+ if (fs7.existsSync(filePath)) {
2829
+ await fs7.promises.unlink(filePath);
2533
2830
  return true;
2534
2831
  }
2535
2832
  return false;