@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.js CHANGED
@@ -1,3 +1,10 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
1
8
  // src/lib/Engine.ts
2
9
  import path4 from "path";
3
10
 
@@ -132,7 +139,7 @@ import * as unzipper from "unzipper";
132
139
  import ora from "ora";
133
140
  import chalk from "chalk";
134
141
  import { fileURLToPath } from "url";
135
- import { dirname } from "path";
142
+ import { dirname as dirname2 } from "path";
136
143
  var { https } = followRedirects;
137
144
  var Downloader = class {
138
145
  static mainSpinner = null;
@@ -147,7 +154,7 @@ var Downloader = class {
147
154
  */
148
155
  static async fetchLatestVersion(prefix) {
149
156
  const url = this.VERSION_URLS[prefix];
150
- return new Promise((resolve5, reject) => {
157
+ return new Promise((resolve6, reject) => {
151
158
  https.get(url, (response) => {
152
159
  let data = "";
153
160
  response.on("data", (chunk) => {
@@ -157,7 +164,7 @@ var Downloader = class {
157
164
  try {
158
165
  const versions = JSON.parse(data);
159
166
  if (versions && versions.length > 0) {
160
- resolve5(versions[0].version);
167
+ resolve6(versions[0].version);
161
168
  } else {
162
169
  reject(new Error("No versions found"));
163
170
  }
@@ -366,7 +373,7 @@ var Downloader = class {
366
373
  if (attempt < maxRetries && (errorMessage.includes("ECONNRESET") || errorMessage.includes("timeout") || errorMessage.includes("ETIMEDOUT") || errorMessage.includes("ENOTFOUND"))) {
367
374
  attempt++;
368
375
  console.log(`\u{1F504} Retrying ${binary.prefix}-engine (${attempt}/${maxRetries})...`);
369
- await new Promise((resolve5) => setTimeout(resolve5, 1e3 + Math.random() * 1e3));
376
+ await new Promise((resolve6) => setTimeout(resolve6, 1e3 + Math.random() * 1e3));
370
377
  } else {
371
378
  throw new Error(`Error downloading ${binary.prefix}: ${errorMessage}`);
372
379
  }
@@ -414,12 +421,12 @@ var Downloader = class {
414
421
  return `[${filledBar}${emptyBar}] ${percentage}`;
415
422
  }
416
423
  static downloadFileWithProgress(url, outputPath, prefix) {
417
- return new Promise((resolve5, reject) => {
424
+ return new Promise((resolve6, reject) => {
418
425
  const request = https.get(url, { timeout: 0 }, (response) => {
419
426
  if (response.statusCode === 302 || response.statusCode === 301) {
420
427
  const redirectUrl = response.headers.location;
421
428
  if (redirectUrl) {
422
- return this.downloadFileWithProgress(redirectUrl, outputPath, prefix).then(resolve5).catch(reject);
429
+ return this.downloadFileWithProgress(redirectUrl, outputPath, prefix).then(resolve6).catch(reject);
423
430
  }
424
431
  }
425
432
  if (response.statusCode !== 200) {
@@ -442,7 +449,7 @@ var Downloader = class {
442
449
  }
443
450
  });
444
451
  response.on("end", () => {
445
- file.end(() => resolve5());
452
+ file.end(() => resolve6());
446
453
  });
447
454
  response.on("error", (err) => {
448
455
  file.close();
@@ -474,35 +481,47 @@ var Downloader = class {
474
481
  this.mainSpinner.text = `\u{1F4E5} ${chalk.bold(binary)} - ${progressText}`;
475
482
  }
476
483
  static extractBinary(zipPath, outputPath, prefix) {
477
- return new Promise((resolve5, reject) => {
478
- let extracted = false;
484
+ return new Promise((resolve6, reject) => {
485
+ const outDir = path.dirname(outputPath);
486
+ let extracted = 0;
487
+ const pending = [];
479
488
  fs.createReadStream(zipPath).pipe(unzipper.Parse()).on("entry", (entry) => {
480
- if (entry.type === "File" && !extracted) {
481
- extracted = true;
482
- const writeStream = fs.createWriteStream(outputPath);
489
+ if (entry.type !== "File") {
490
+ entry.autodrain();
491
+ return;
492
+ }
493
+ const isMain = extracted === 0;
494
+ extracted++;
495
+ const target = isMain ? outputPath : path.join(outDir, path.basename(entry.path));
496
+ pending.push(new Promise((res, rej) => {
497
+ const writeStream = fs.createWriteStream(target);
483
498
  entry.pipe(writeStream);
484
499
  writeStream.on("finish", () => {
485
500
  if (process.platform !== "win32") {
486
- fs.chmodSync(outputPath, 493);
501
+ try {
502
+ fs.chmodSync(target, 493);
503
+ } catch {
504
+ }
487
505
  }
488
- this.cleanupFile(zipPath);
489
- resolve5();
490
- });
491
- writeStream.on("error", (err) => {
492
- this.cleanupFile(zipPath);
493
- reject(err);
506
+ res();
494
507
  });
495
- } else {
496
- entry.autodrain();
497
- }
508
+ writeStream.on("error", rej);
509
+ }));
498
510
  }).on("error", (err) => {
499
511
  this.cleanupFile(zipPath);
500
512
  reject(err);
501
513
  }).on("close", () => {
502
- if (!extracted) {
514
+ Promise.all(pending).then(() => {
503
515
  this.cleanupFile(zipPath);
504
- reject(new Error(`No se encontr\xF3 archivo v\xE1lido en el ZIP para ${prefix}`));
505
- }
516
+ if (extracted === 0) {
517
+ reject(new Error(`No se encontr\xF3 archivo v\xE1lido en el ZIP para ${prefix}`));
518
+ } else {
519
+ resolve6();
520
+ }
521
+ }).catch((err) => {
522
+ this.cleanupFile(zipPath);
523
+ reject(err);
524
+ });
506
525
  });
507
526
  });
508
527
  }
@@ -516,7 +535,7 @@ var Downloader = class {
516
535
  }
517
536
  static getDefaultBinDir() {
518
537
  const __filename2 = typeof import.meta !== "undefined" && import.meta.url ? fileURLToPath(import.meta.url) : "";
519
- const __dirname = __filename2 ? dirname(__filename2) : process.cwd();
538
+ const __dirname = __filename2 ? dirname2(__filename2) : process.cwd();
520
539
  const possibleDirs = [
521
540
  path.resolve(process.cwd(), ".dbcube", "bin"),
522
541
  path.resolve(process.cwd(), "node_modules", ".dbcube", "bin"),
@@ -546,7 +565,7 @@ import * as fs2 from "fs";
546
565
  import * as path2 from "path";
547
566
  import * as os3 from "os";
548
567
  import { fileURLToPath as fileURLToPath2 } from "url";
549
- import { dirname as dirname2 } from "path";
568
+ import { dirname as dirname3 } from "path";
550
569
  var Binary = class {
551
570
  static isDownloading = false;
552
571
  static downloadPromise = null;
@@ -579,7 +598,7 @@ var Binary = class {
579
598
  }
580
599
  static getBinDir() {
581
600
  const __filename2 = typeof import.meta !== "undefined" && import.meta.url ? fileURLToPath2(import.meta.url) : "";
582
- const __dirname = __filename2 ? dirname2(__filename2) : process.cwd();
601
+ const __dirname = __filename2 ? dirname3(__filename2) : process.cwd();
583
602
  const possibleDirs = [
584
603
  path2.resolve(process.cwd(), ".dbcube", "bin"),
585
604
  path2.resolve(process.cwd(), "node_modules", ".dbcube", "bin"),
@@ -816,22 +835,22 @@ var DaemonClient = class _DaemonClient {
816
835
  child.unref();
817
836
  }
818
837
  tryConnect(port) {
819
- return new Promise((resolve5) => {
838
+ return new Promise((resolve6) => {
820
839
  const socket = net.createConnection({ host: "127.0.0.1", port }, async () => {
821
840
  socket.setNoDelay(true);
822
841
  this.attach(socket);
823
842
  try {
824
843
  const pong = await this.send({ action: "ping" }, 2e3);
825
- resolve5(pong.status === 200);
844
+ resolve6(pong.status === 200);
826
845
  } catch {
827
846
  this.detach();
828
- resolve5(false);
847
+ resolve6(false);
829
848
  }
830
849
  });
831
- socket.once("error", () => resolve5(false));
850
+ socket.once("error", () => resolve6(false));
832
851
  socket.setTimeout(3e3, () => {
833
852
  socket.destroy();
834
- resolve5(false);
853
+ resolve6(false);
835
854
  });
836
855
  });
837
856
  }
@@ -879,7 +898,7 @@ var DaemonClient = class _DaemonClient {
879
898
  * single socket, so pending requests resolve in send order.
880
899
  */
881
900
  send(payload, timeoutMs) {
882
- return new Promise((resolve5, reject) => {
901
+ return new Promise((resolve6, reject) => {
883
902
  if (!this.socket || this.socket.destroyed) {
884
903
  reject(new Error("Daemon not connected"));
885
904
  return;
@@ -890,12 +909,12 @@ var DaemonClient = class _DaemonClient {
890
909
  reject(new Error("Daemon request timeout"));
891
910
  this.detach();
892
911
  }, timeoutMs ?? this.requestTimeout);
893
- this.pending.push({ resolve: resolve5, reject, timer });
912
+ this.pending.push({ resolve: resolve6, reject, timer });
894
913
  this.socket.write(JSON.stringify(payload) + "\n");
895
914
  });
896
915
  }
897
916
  async execute(dml, txId) {
898
- const payload = { action: "execute", dml: JSON.stringify(dml) };
917
+ const payload = { action: "execute", dml };
899
918
  if (txId) payload.tx_id = txId;
900
919
  return this.send(payload);
901
920
  }
@@ -962,8 +981,8 @@ var Engine = class {
962
981
  const binaryPath = this.binary["query_engine"];
963
982
  if (!binaryPath) return null;
964
983
  const client = DaemonClient.get(this.name, binaryPath, this.arguments);
965
- const ok = await client.ensure();
966
- if (!ok) {
984
+ const ok2 = await client.ensure();
985
+ if (!ok2) {
967
986
  this.daemonFailed = true;
968
987
  return null;
969
988
  }
@@ -1094,7 +1113,7 @@ var Engine = class {
1094
1113
  if (!this.binary) {
1095
1114
  throw new Error("Binary not initialized");
1096
1115
  }
1097
- return new Promise((resolve5, reject) => {
1116
+ return new Promise((resolve6, reject) => {
1098
1117
  const child = spawn2(this.binary[binary], [...this.arguments, ...args]);
1099
1118
  let stdoutBuffer = "";
1100
1119
  let stderrBuffer = "";
@@ -1110,18 +1129,18 @@ var Engine = class {
1110
1129
  if (!isResolved) {
1111
1130
  isResolved = true;
1112
1131
  clearTimeout(timeoutId);
1113
- resolve5(response);
1132
+ resolve6(response);
1114
1133
  }
1115
1134
  };
1116
- child.stdout.on("data", (data) => {
1117
- const text = data.toString();
1118
- stdoutBuffer += text;
1119
- const visible = text.split("\n").filter((l) => l.trim() && !l.includes("PROCESS_RESPONSE:")).join("\n");
1120
- if (visible) console.log(visible);
1121
- const match = stdoutBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
1122
- if (match) {
1135
+ const tryParseLines = (buffer) => {
1136
+ let idx;
1137
+ while ((idx = buffer.indexOf("\n")) !== -1) {
1138
+ const line = buffer.slice(0, idx);
1139
+ buffer = buffer.slice(idx + 1);
1140
+ const marker = line.indexOf("PROCESS_RESPONSE:");
1141
+ if (marker === -1) continue;
1123
1142
  try {
1124
- const response = JSON.parse(match[1]);
1143
+ const response = JSON.parse(line.slice(marker + "PROCESS_RESPONSE:".length));
1125
1144
  resolveOnce({
1126
1145
  status: response.status,
1127
1146
  message: response.message,
@@ -1135,29 +1154,19 @@ var Engine = class {
1135
1154
  });
1136
1155
  }
1137
1156
  }
1157
+ return buffer;
1158
+ };
1159
+ child.stdout.on("data", (data) => {
1160
+ const text = data.toString();
1161
+ const visible = text.split("\n").filter((l) => l.trim() && !l.includes("PROCESS_RESPONSE:")).join("\n");
1162
+ if (visible) console.log(visible);
1163
+ stdoutBuffer = tryParseLines(stdoutBuffer + text);
1138
1164
  });
1139
1165
  child.stderr.on("data", (data) => {
1140
1166
  const text = data.toString();
1141
- stderrBuffer += text;
1142
1167
  const visible = text.split("\n").filter((l) => l.trim() && !l.includes("PROCESS_RESPONSE:")).join("\n");
1143
1168
  if (visible) console.log(visible);
1144
- const match = stderrBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
1145
- if (match) {
1146
- try {
1147
- const response = JSON.parse(match[1]);
1148
- resolveOnce({
1149
- status: response.status,
1150
- message: response.message,
1151
- data: response.data
1152
- });
1153
- } catch (error) {
1154
- resolveOnce({
1155
- status: 500,
1156
- message: "Failed to parse response JSON",
1157
- data: null
1158
- });
1159
- }
1160
- }
1169
+ stderrBuffer = tryParseLines(stderrBuffer + text);
1161
1170
  });
1162
1171
  child.on("close", (code) => {
1163
1172
  clearTimeout(timeoutId);
@@ -1185,14 +1194,265 @@ var Engine = class {
1185
1194
  };
1186
1195
 
1187
1196
  // src/lib/QueryEngine.ts
1188
- import path5 from "path";
1197
+ import path6 from "path";
1198
+
1199
+ // src/lib/EmbeddedEngine.ts
1200
+ import * as fs4 from "fs";
1201
+ import * as path5 from "path";
1202
+ if (!process.env.UV_THREADPOOL_SIZE) {
1203
+ process.env.UV_THREADPOOL_SIZE = "16";
1204
+ }
1205
+ var backend = null;
1206
+ var loadFailed = false;
1207
+ var handles = /* @__PURE__ */ new Map();
1208
+ var connecting = /* @__PURE__ */ new Map();
1209
+ function platTag() {
1210
+ const arch2 = process.arch === "arm64" ? "arm64" : "x64";
1211
+ if (process.platform === "win32") return { plat: "windows", ext: "dll", arch: arch2 };
1212
+ if (process.platform === "darwin") return { plat: "macos", ext: "dylib", arch: arch2 };
1213
+ return { plat: "linux", ext: "so", arch: arch2 };
1214
+ }
1215
+ function findFile(name) {
1216
+ const candidates = [
1217
+ path5.resolve(process.cwd(), ".dbcube", "bin", name),
1218
+ path5.resolve(process.cwd(), "node_modules", ".dbcube", "bin", name)
1219
+ ];
1220
+ for (const c of candidates) {
1221
+ if (fs4.existsSync(c)) return c;
1222
+ }
1223
+ return null;
1224
+ }
1225
+ function ok(data) {
1226
+ return { status: 200, message: "OK", data };
1227
+ }
1228
+ function errResp(e) {
1229
+ const msg = e instanceof Error ? e.message : String(e);
1230
+ return { status: 500, message: msg, data: null };
1231
+ }
1232
+ function loadNapiBackend() {
1233
+ const { plat, arch: arch2 } = platTag();
1234
+ const addonPath = findFile(`query-engine-node-${plat}-${arch2}.node`);
1235
+ if (!addonPath) return null;
1236
+ try {
1237
+ const addon = __require(addonPath);
1238
+ if (typeof addon.connect !== "function") return null;
1239
+ return {
1240
+ async connect(cfgJson) {
1241
+ return Number(await addon.connect(cfgJson));
1242
+ },
1243
+ async execute(handle, dml, txId) {
1244
+ try {
1245
+ const rows = await addon.execute(handle, dml, txId ?? void 0);
1246
+ return ok(rows);
1247
+ } catch (e) {
1248
+ return errResp(e);
1249
+ }
1250
+ },
1251
+ async executeBatch(handle, ops) {
1252
+ try {
1253
+ const results = await addon.executeBatch(handle, ops);
1254
+ return ok(results);
1255
+ } catch (e) {
1256
+ return errResp(e);
1257
+ }
1258
+ },
1259
+ async raw(handle, query, params, txId) {
1260
+ try {
1261
+ const rows = await addon.raw(handle, query, params, txId ?? void 0);
1262
+ return ok(rows);
1263
+ } catch (e) {
1264
+ return errResp(e);
1265
+ }
1266
+ },
1267
+ async begin(handle) {
1268
+ try {
1269
+ const txId = await addon.begin(handle);
1270
+ return ok({ tx_id: txId });
1271
+ } catch (e) {
1272
+ return errResp(e);
1273
+ }
1274
+ },
1275
+ async commit(_handle, txId) {
1276
+ try {
1277
+ await addon.commit(txId);
1278
+ return ok(null);
1279
+ } catch (e) {
1280
+ return errResp(e);
1281
+ }
1282
+ },
1283
+ async rollback(_handle, txId) {
1284
+ try {
1285
+ await addon.rollback(txId);
1286
+ return ok(null);
1287
+ } catch (e) {
1288
+ return errResp(e);
1289
+ }
1290
+ },
1291
+ async disconnect(handle) {
1292
+ try {
1293
+ addon.disconnect(handle);
1294
+ } catch {
1295
+ }
1296
+ }
1297
+ };
1298
+ } catch {
1299
+ return null;
1300
+ }
1301
+ }
1302
+ function loadKoffiBackend() {
1303
+ const { plat, ext, arch: arch2 } = platTag();
1304
+ const libPath = findFile(`query-engine-embedded-${plat}-${arch2}.${ext}`);
1305
+ if (!libPath) return null;
1306
+ try {
1307
+ const koffi = __require("koffi");
1308
+ const lib = koffi.load(libPath);
1309
+ const cConnect = lib.func("dbc_connect", "void *", ["str"]);
1310
+ const cExecute = lib.func("dbc_execute", "void *", ["uint64", "str", "str"]);
1311
+ const cExecuteBatch = lib.func("dbc_execute_batch", "void *", ["uint64", "str"]);
1312
+ const cRaw = lib.func("dbc_raw", "void *", ["uint64", "str", "str", "str"]);
1313
+ const cBegin = lib.func("dbc_begin", "void *", ["uint64"]);
1314
+ const cCommit = lib.func("dbc_commit", "void *", ["uint64", "str"]);
1315
+ const cRollback = lib.func("dbc_rollback", "void *", ["uint64", "str"]);
1316
+ const cDisconnect = lib.func("dbc_disconnect", "void *", ["uint64"]);
1317
+ const cFree = lib.func("dbc_free", "void", ["void *"]);
1318
+ const take = (ptr) => {
1319
+ if (!ptr) return { status: 500, message: "embedded engine returned null", data: null };
1320
+ const s = koffi.decode(ptr, "char", -1);
1321
+ cFree(ptr);
1322
+ try {
1323
+ const r = JSON.parse(s);
1324
+ return { status: r.status ?? 500, message: r.message ?? "", data: r.data ?? null };
1325
+ } catch (e) {
1326
+ return { status: 500, message: `Invalid embedded response: ${e.message}`, data: null };
1327
+ }
1328
+ };
1329
+ const call = (fn, ...args) => new Promise((resolve6, reject) => {
1330
+ fn.async(...args, (err, ptr) => {
1331
+ if (err) return reject(err);
1332
+ resolve6(take(ptr));
1333
+ });
1334
+ });
1335
+ return {
1336
+ async connect(cfgJson) {
1337
+ const res = await call(cConnect, cfgJson);
1338
+ if (res.status !== 200 || !res.data?.handle) {
1339
+ throw new Error(String(res.message || "embedded connect failed"));
1340
+ }
1341
+ return Number(res.data.handle);
1342
+ },
1343
+ execute: (handle, dml, txId) => call(cExecute, handle, JSON.stringify(dml), txId),
1344
+ executeBatch: (handle, ops) => call(cExecuteBatch, handle, JSON.stringify(ops)),
1345
+ raw: (handle, query, params, txId) => call(cRaw, handle, query, JSON.stringify(params ?? []), txId),
1346
+ begin: (handle) => call(cBegin, handle),
1347
+ commit: (handle, txId) => call(cCommit, handle, txId),
1348
+ rollback: (handle, txId) => call(cRollback, handle, txId),
1349
+ async disconnect(handle) {
1350
+ try {
1351
+ await call(cDisconnect, handle);
1352
+ } catch {
1353
+ }
1354
+ }
1355
+ };
1356
+ } catch {
1357
+ return null;
1358
+ }
1359
+ }
1360
+ function loadBackend() {
1361
+ if (backend) return backend;
1362
+ if (loadFailed) return null;
1363
+ if (process.env.DBCUBE_EMBEDDED === "0" || process.env.DBCUBE_EMBEDDED === "false") {
1364
+ loadFailed = true;
1365
+ return null;
1366
+ }
1367
+ backend = loadNapiBackend() ?? loadKoffiBackend();
1368
+ if (!backend) loadFailed = true;
1369
+ return backend;
1370
+ }
1371
+ var EmbeddedEngine = class {
1372
+ /** true si algún backend nativo está disponible en esta instalación. */
1373
+ static available() {
1374
+ return loadBackend() !== null;
1375
+ }
1376
+ static async handleFor(connectionId, config) {
1377
+ const existing = handles.get(connectionId);
1378
+ if (existing) return existing;
1379
+ const inFlight = connecting.get(connectionId);
1380
+ if (inFlight) return inFlight;
1381
+ const promise = (async () => {
1382
+ const be = loadBackend();
1383
+ if (!be) throw new Error("embedded engine not available");
1384
+ const motor = config.type === "postgres" ? "postgresql" : config.type;
1385
+ const cfg = {
1386
+ databaseRef: connectionId,
1387
+ motor,
1388
+ database: config.type === "sqlite" ? `${config.config.DATABASE}.db` : config.config.DATABASE,
1389
+ host: config.config.HOST,
1390
+ port: config.config.PORT != null ? Number(config.config.PORT) : void 0,
1391
+ user: config.config.USER,
1392
+ password: config.config.PASSWORD,
1393
+ maxConnections: config.pool?.maxConnections,
1394
+ minConnections: config.pool?.minConnections,
1395
+ acquireTimeoutMs: config.pool?.acquireTimeoutMs,
1396
+ idleTimeoutMs: config.pool?.idleTimeoutMs
1397
+ };
1398
+ const handle = await be.connect(JSON.stringify(cfg));
1399
+ handles.set(connectionId, handle);
1400
+ return handle;
1401
+ })();
1402
+ connecting.set(connectionId, promise);
1403
+ try {
1404
+ return await promise;
1405
+ } finally {
1406
+ connecting.delete(connectionId);
1407
+ }
1408
+ }
1409
+ static async executeDml(connectionId, config, dml, txId) {
1410
+ const be = loadBackend();
1411
+ const handle = await this.handleFor(connectionId, config);
1412
+ return be.execute(handle, dml, txId ?? null);
1413
+ }
1414
+ static async executeBatch(connectionId, config, ops) {
1415
+ const be = loadBackend();
1416
+ const handle = await this.handleFor(connectionId, config);
1417
+ return be.executeBatch(handle, ops);
1418
+ }
1419
+ static async rawQuery(connectionId, config, query, params, txId) {
1420
+ const be = loadBackend();
1421
+ const handle = await this.handleFor(connectionId, config);
1422
+ return be.raw(handle, query, params ?? [], txId ?? null);
1423
+ }
1424
+ static async begin(connectionId, config) {
1425
+ const be = loadBackend();
1426
+ const handle = await this.handleFor(connectionId, config);
1427
+ return be.begin(handle);
1428
+ }
1429
+ static async commit(connectionId, config, txId) {
1430
+ const be = loadBackend();
1431
+ const handle = await this.handleFor(connectionId, config);
1432
+ return be.commit(handle, txId);
1433
+ }
1434
+ static async rollback(connectionId, config, txId) {
1435
+ const be = loadBackend();
1436
+ const handle = await this.handleFor(connectionId, config);
1437
+ return be.rollback(handle, txId);
1438
+ }
1439
+ static async disconnect(connectionId) {
1440
+ const be = loadBackend();
1441
+ const handle = handles.get(connectionId);
1442
+ if (be && handle) {
1443
+ handles.delete(connectionId);
1444
+ await be.disconnect(handle);
1445
+ }
1446
+ }
1447
+ };
1448
+
1449
+ // src/lib/QueryEngine.ts
1189
1450
  import { createRequire as createRequire2 } from "module";
1190
1451
  import * as net2 from "net";
1191
1452
  import { spawn as spawn3 } from "child_process";
1192
1453
  var globalTcpServers = /* @__PURE__ */ new Map();
1193
- var globalTcpConnections = /* @__PURE__ */ new Map();
1194
- var connectionQueues = /* @__PURE__ */ new Map();
1195
- var connectionProcessing = /* @__PURE__ */ new Map();
1454
+ var socketPools = /* @__PURE__ */ new Map();
1455
+ var CLIENT_POOL_SIZE = 10;
1196
1456
  var queryCache = /* @__PURE__ */ new Map();
1197
1457
  var MAX_CACHE_SIZE = 500;
1198
1458
  var QueryEngine = class {
@@ -1223,12 +1483,12 @@ var QueryEngine = class {
1223
1483
  throw new Error("No available ports found in range 9900-9944");
1224
1484
  }
1225
1485
  isPortAvailable(port) {
1226
- return new Promise((resolve5) => {
1486
+ return new Promise((resolve6) => {
1227
1487
  const tester = net2.createServer();
1228
- tester.once("error", () => resolve5(false));
1488
+ tester.once("error", () => resolve6(false));
1229
1489
  tester.once("listening", () => {
1230
1490
  tester.close();
1231
- resolve5(true);
1491
+ resolve6(true);
1232
1492
  });
1233
1493
  tester.listen(port, "127.0.0.1");
1234
1494
  });
@@ -1289,7 +1549,7 @@ var QueryEngine = class {
1289
1549
  setConfig(name) {
1290
1550
  const configInstance = new Config();
1291
1551
  try {
1292
- const configFilePath = path5.resolve(process.cwd(), "dbcube.config.js");
1552
+ const configFilePath = path6.resolve(process.cwd(), "dbcube.config.js");
1293
1553
  const requireUrl = typeof __filename !== "undefined" ? __filename : process.cwd();
1294
1554
  const require2 = createRequire2(requireUrl);
1295
1555
  if (require2.cache && require2.resolve) {
@@ -1335,38 +1595,79 @@ var QueryEngine = class {
1335
1595
  }
1336
1596
  return command;
1337
1597
  }
1598
+ /** El motor embebido (FFI) es el camino por defecto cuando la librería
1599
+ * nativa está disponible; el daemon TCP queda como fallback y como modo
1600
+ * multi-proceso explícito. */
1601
+ useEmbedded() {
1602
+ return EmbeddedEngine.available();
1603
+ }
1338
1604
  /**
1339
- * Executes a DML plan over the persistent TCP server.
1605
+ * Executes a DML plan. Embedded engine when available (in-process FFI,
1606
+ * no network hop); persistent TCP daemon otherwise.
1340
1607
  * Pass txId to run it inside an active transaction.
1341
1608
  */
1342
1609
  async executeDml(dml, txId) {
1343
- const command = { action: "execute", dml: JSON.stringify(dml) };
1610
+ if (this.useEmbedded()) {
1611
+ return EmbeddedEngine.executeDml(this.connectionId, this.config, dml, txId);
1612
+ }
1613
+ const command = { action: "execute", dml };
1344
1614
  if (txId) command.tx_id = txId;
1345
1615
  return this.executeWithTcpServer(command);
1346
1616
  }
1347
1617
  /**
1348
- * Executes raw SQL (or a MongoDB command document) with bound parameters
1349
- * over the persistent TCP server.
1618
+ * Atomic batch: N write plans inside one transaction with a single
1619
+ * engine round-trip. Falls back to begin/ops/commit over the daemon
1620
+ * when the embedded engine is not available.
1621
+ */
1622
+ async executeBatch(ops) {
1623
+ if (this.useEmbedded()) {
1624
+ return EmbeddedEngine.executeBatch(this.connectionId, this.config, ops);
1625
+ }
1626
+ const txId = await this.beginTransaction();
1627
+ try {
1628
+ const results = [];
1629
+ for (const op of ops) {
1630
+ const res = await this.executeDml(op, txId);
1631
+ if (res.status !== 200) {
1632
+ throw new Error(String(res.message));
1633
+ }
1634
+ results.push(res.data);
1635
+ }
1636
+ await this.commitTransaction(txId);
1637
+ return { status: 200, message: "Batch committed", data: results };
1638
+ } catch (error) {
1639
+ try {
1640
+ await this.rollbackTransaction(txId);
1641
+ } catch {
1642
+ }
1643
+ return { status: 500, message: error?.message ?? String(error), data: null };
1644
+ }
1645
+ }
1646
+ /**
1647
+ * Executes raw SQL (or a MongoDB command document) with bound parameters.
1350
1648
  */
1351
1649
  async rawQuery(query, params = [], txId) {
1650
+ if (this.useEmbedded()) {
1651
+ return EmbeddedEngine.rawQuery(this.connectionId, this.config, query, params, txId);
1652
+ }
1352
1653
  const command = { action: "raw", query, params };
1353
1654
  if (txId) command.tx_id = txId;
1354
1655
  return this.executeWithTcpServer(command);
1355
1656
  }
1356
- /** Starts a server-side transaction and returns its id. */
1657
+ /** Starts a transaction and returns its id. */
1357
1658
  async beginTransaction() {
1358
- const res = await this.executeWithTcpServer({ action: "begin" });
1659
+ const res = this.useEmbedded() ? await EmbeddedEngine.begin(this.connectionId, this.config) : await this.executeWithTcpServer({ action: "begin" });
1359
1660
  if (res.status !== 200 || !res.data?.tx_id) {
1360
1661
  throw new Error(String(res.message || "Failed to begin transaction (update the query-engine binary: npx dbcube update)"));
1361
1662
  }
1362
1663
  return res.data.tx_id;
1363
1664
  }
1364
1665
  async commitTransaction(txId) {
1365
- const res = await this.executeWithTcpServer({ action: "commit", tx_id: txId });
1666
+ const res = this.useEmbedded() ? await EmbeddedEngine.commit(this.connectionId, this.config, txId) : await this.executeWithTcpServer({ action: "commit", tx_id: txId });
1366
1667
  if (res.status !== 200) throw new Error(String(res.message || "Failed to commit transaction"));
1367
1668
  }
1368
1669
  async rollbackTransaction(txId) {
1369
- const res = await this.executeWithTcpServer({ action: "rollback", tx_id: txId });
1670
+ const res = this.useEmbedded() ? await EmbeddedEngine.rollback(this.connectionId, this.config, txId) : await this.executeWithTcpServer({ action: "rollback", tx_id: txId });
1370
1671
  if (res.status !== 200) throw new Error(String(res.message || "Failed to rollback transaction"));
1371
1672
  }
1372
1673
  async executeWithTcpServer(command) {
@@ -1385,7 +1686,63 @@ var QueryEngine = class {
1385
1686
  await this.startTcpServer();
1386
1687
  await this.waitForServerReady();
1387
1688
  }
1388
- return this.sendTcpRequestFast(command);
1689
+ const port = globalTcpServers.get(this.connectionId).port;
1690
+ const socket = await this.acquireSocket(port);
1691
+ try {
1692
+ const result = await this.executeOnConnection(socket, command);
1693
+ this.releaseSocket(socket, false);
1694
+ return result;
1695
+ } catch (error) {
1696
+ this.releaseSocket(socket, true);
1697
+ throw error;
1698
+ }
1699
+ }
1700
+ poolFor() {
1701
+ let pool = socketPools.get(this.connectionId);
1702
+ if (!pool) {
1703
+ pool = { free: [], total: 0, waiters: [] };
1704
+ socketPools.set(this.connectionId, pool);
1705
+ }
1706
+ return pool;
1707
+ }
1708
+ async acquireSocket(port) {
1709
+ const pool = this.poolFor();
1710
+ while (pool.free.length > 0) {
1711
+ const s = pool.free.pop();
1712
+ if (!s.destroyed) return s;
1713
+ pool.total--;
1714
+ }
1715
+ if (pool.total < CLIENT_POOL_SIZE) {
1716
+ pool.total++;
1717
+ try {
1718
+ return await this.createNewConnection(port);
1719
+ } catch (e) {
1720
+ pool.total--;
1721
+ throw e;
1722
+ }
1723
+ }
1724
+ return new Promise((resolve6) => pool.waiters.push(resolve6));
1725
+ }
1726
+ releaseSocket(socket, broken) {
1727
+ const pool = socketPools.get(this.connectionId);
1728
+ if (!pool) {
1729
+ socket.destroy();
1730
+ return;
1731
+ }
1732
+ if (broken || socket.destroyed) {
1733
+ pool.total--;
1734
+ try {
1735
+ socket.destroy();
1736
+ } catch {
1737
+ }
1738
+ return;
1739
+ }
1740
+ const waiter = pool.waiters.shift();
1741
+ if (waiter) {
1742
+ waiter(socket);
1743
+ } else {
1744
+ pool.free.push(socket);
1745
+ }
1389
1746
  }
1390
1747
  async waitForServerReady() {
1391
1748
  const maxRetries = 10;
@@ -1403,25 +1760,25 @@ var QueryEngine = class {
1403
1760
  throw new Error("TCP server failed to become ready within timeout");
1404
1761
  }
1405
1762
  async isServerResponding(port) {
1406
- return new Promise((resolve5) => {
1763
+ return new Promise((resolve6) => {
1407
1764
  const client = new net2.Socket();
1408
1765
  const timeout = setTimeout(() => {
1409
1766
  client.destroy();
1410
- resolve5(false);
1767
+ resolve6(false);
1411
1768
  }, 1e3);
1412
1769
  client.connect(port, "127.0.0.1", () => {
1413
1770
  clearTimeout(timeout);
1414
1771
  client.destroy();
1415
- resolve5(true);
1772
+ resolve6(true);
1416
1773
  });
1417
1774
  client.on("error", () => {
1418
1775
  clearTimeout(timeout);
1419
- resolve5(false);
1776
+ resolve6(false);
1420
1777
  });
1421
1778
  });
1422
1779
  }
1423
1780
  sleep(ms) {
1424
- return new Promise((resolve5) => setTimeout(resolve5, ms));
1781
+ return new Promise((resolve6) => setTimeout(resolve6, ms));
1425
1782
  }
1426
1783
  getCachedDML(dmlJson) {
1427
1784
  if (queryCache.has(dmlJson)) {
@@ -1441,7 +1798,7 @@ var QueryEngine = class {
1441
1798
  throw new Error("Binary not initialized");
1442
1799
  }
1443
1800
  this.tcpPort = await this.findAvailablePort(this.tcpPort);
1444
- return new Promise((resolve5, reject) => {
1801
+ return new Promise((resolve6, reject) => {
1445
1802
  const serverArgs = [...this.arguments, "--action", "server", "--tcp-port", this.tcpPort.toString()];
1446
1803
  const serverProcess = spawn3(this.binary["query_engine"], serverArgs);
1447
1804
  let started = false;
@@ -1461,7 +1818,7 @@ var QueryEngine = class {
1461
1818
  port: this.tcpPort,
1462
1819
  process: serverProcess
1463
1820
  });
1464
- resolve5();
1821
+ resolve6();
1465
1822
  }
1466
1823
  }
1467
1824
  });
@@ -1479,60 +1836,8 @@ var QueryEngine = class {
1479
1836
  });
1480
1837
  });
1481
1838
  }
1482
- async sendTcpRequestFast(command) {
1483
- return new Promise((resolve5, reject) => {
1484
- let queue = connectionQueues.get(this.connectionId);
1485
- if (!queue) {
1486
- queue = [];
1487
- connectionQueues.set(this.connectionId, queue);
1488
- }
1489
- queue.push({ command, resolve: resolve5, reject });
1490
- this.processQueue();
1491
- });
1492
- }
1493
- async processQueue() {
1494
- if (connectionProcessing.get(this.connectionId)) {
1495
- return;
1496
- }
1497
- const queue = connectionQueues.get(this.connectionId);
1498
- if (!queue || queue.length === 0) {
1499
- return;
1500
- }
1501
- connectionProcessing.set(this.connectionId, true);
1502
- try {
1503
- const serverInfo = globalTcpServers.get(this.connectionId);
1504
- if (!serverInfo) {
1505
- throw new Error("Server not initialized");
1506
- }
1507
- while (queue.length > 0) {
1508
- const request = queue.shift();
1509
- if (!request) break;
1510
- try {
1511
- let connection = globalTcpConnections.get(this.connectionId);
1512
- if (!connection || connection.destroyed || connection.readyState !== "open") {
1513
- connection = await this.createNewConnection(serverInfo.port);
1514
- globalTcpConnections.set(this.connectionId, connection);
1515
- }
1516
- const result = await this.executeOnConnection(connection, request.command);
1517
- request.resolve(result);
1518
- } catch (error) {
1519
- const staleConnection = globalTcpConnections.get(this.connectionId);
1520
- if (staleConnection) {
1521
- try {
1522
- staleConnection.destroy();
1523
- } catch {
1524
- }
1525
- }
1526
- globalTcpConnections.delete(this.connectionId);
1527
- request.reject(error);
1528
- }
1529
- }
1530
- } finally {
1531
- connectionProcessing.set(this.connectionId, false);
1532
- }
1533
- }
1534
1839
  async createNewConnection(port) {
1535
- return new Promise((resolve5, reject) => {
1840
+ return new Promise((resolve6, reject) => {
1536
1841
  const client = new net2.Socket();
1537
1842
  client.setNoDelay(true);
1538
1843
  client.setKeepAlive(true, 6e4);
@@ -1542,7 +1847,7 @@ var QueryEngine = class {
1542
1847
  }, 5e3);
1543
1848
  client.connect(port, "127.0.0.1", () => {
1544
1849
  clearTimeout(timeout);
1545
- resolve5(client);
1850
+ resolve6(client);
1546
1851
  });
1547
1852
  client.on("error", (error) => {
1548
1853
  clearTimeout(timeout);
@@ -1551,7 +1856,7 @@ var QueryEngine = class {
1551
1856
  });
1552
1857
  }
1553
1858
  async executeOnConnection(connection, command) {
1554
- return new Promise((resolve5, reject) => {
1859
+ return new Promise((resolve6, reject) => {
1555
1860
  let responseBuffer = "";
1556
1861
  let isResolved = false;
1557
1862
  const timeout = setTimeout(() => {
@@ -1564,15 +1869,19 @@ var QueryEngine = class {
1564
1869
  }, this.timeout);
1565
1870
  const onData = (data) => {
1566
1871
  responseBuffer += data.toString();
1567
- const match = responseBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
1568
- if (match && !isResolved) {
1872
+ let idx;
1873
+ while ((idx = responseBuffer.indexOf("\n")) !== -1 && !isResolved) {
1874
+ const line = responseBuffer.slice(0, idx);
1875
+ responseBuffer = responseBuffer.slice(idx + 1);
1876
+ const marker = line.indexOf("PROCESS_RESPONSE:");
1877
+ if (marker === -1) continue;
1569
1878
  isResolved = true;
1570
1879
  clearTimeout(timeout);
1571
1880
  connection.removeListener("data", onData);
1572
1881
  connection.removeListener("error", onError);
1573
1882
  try {
1574
- const response = JSON.parse(match[1]);
1575
- resolve5({
1883
+ const response = JSON.parse(line.slice(marker + "PROCESS_RESPONSE:".length));
1884
+ resolve6({
1576
1885
  status: response.status,
1577
1886
  message: response.message,
1578
1887
  data: response.data
@@ -1601,7 +1910,7 @@ var QueryEngine = class {
1601
1910
  if (!this.binary) {
1602
1911
  throw new Error("Binary not initialized");
1603
1912
  }
1604
- return new Promise((resolve5, reject) => {
1913
+ return new Promise((resolve6, reject) => {
1605
1914
  const child = spawn3(this.binary[binary], [...this.arguments, ...args]);
1606
1915
  let stdoutBuffer = "";
1607
1916
  let stderrBuffer = "";
@@ -1617,15 +1926,18 @@ var QueryEngine = class {
1617
1926
  if (!isResolved) {
1618
1927
  isResolved = true;
1619
1928
  clearTimeout(timeoutId);
1620
- resolve5(response);
1929
+ resolve6(response);
1621
1930
  }
1622
1931
  };
1623
- child.stdout.on("data", (data) => {
1624
- stdoutBuffer += data.toString();
1625
- const match = stdoutBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
1626
- if (match) {
1932
+ const tryParseLines = (buffer) => {
1933
+ let idx;
1934
+ while ((idx = buffer.indexOf("\n")) !== -1) {
1935
+ const line = buffer.slice(0, idx);
1936
+ buffer = buffer.slice(idx + 1);
1937
+ const marker = line.indexOf("PROCESS_RESPONSE:");
1938
+ if (marker === -1) continue;
1627
1939
  try {
1628
- const response = JSON.parse(match[1]);
1940
+ const response = JSON.parse(line.slice(marker + "PROCESS_RESPONSE:".length));
1629
1941
  resolveOnce({
1630
1942
  status: response.status,
1631
1943
  message: response.message,
@@ -1639,26 +1951,13 @@ var QueryEngine = class {
1639
1951
  });
1640
1952
  }
1641
1953
  }
1954
+ return buffer;
1955
+ };
1956
+ child.stdout.on("data", (data) => {
1957
+ stdoutBuffer = tryParseLines(stdoutBuffer + data.toString());
1642
1958
  });
1643
1959
  child.stderr.on("data", (data) => {
1644
- stderrBuffer += data.toString();
1645
- const match = stderrBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
1646
- if (match) {
1647
- try {
1648
- const response = JSON.parse(match[1]);
1649
- resolveOnce({
1650
- status: response.status,
1651
- message: response.message,
1652
- data: response.data
1653
- });
1654
- } catch (error) {
1655
- resolveOnce({
1656
- status: 500,
1657
- message: "Failed to parse response JSON",
1658
- data: null
1659
- });
1660
- }
1661
- }
1960
+ stderrBuffer = tryParseLines(stderrBuffer + data.toString());
1662
1961
  });
1663
1962
  child.on("close", (code) => {
1664
1963
  clearTimeout(timeoutId);
@@ -1684,11 +1983,16 @@ var QueryEngine = class {
1684
1983
  });
1685
1984
  }
1686
1985
  async disconnect() {
1687
- const connection = globalTcpConnections.get(this.connectionId);
1688
- if (connection && connection.readyState === "open") {
1689
- connection.write(JSON.stringify({ action: "disconnect" }));
1690
- connection.destroy();
1691
- globalTcpConnections.delete(this.connectionId);
1986
+ await EmbeddedEngine.disconnect(this.connectionId);
1987
+ const pool = socketPools.get(this.connectionId);
1988
+ if (pool) {
1989
+ for (const s of pool.free) {
1990
+ try {
1991
+ s.destroy();
1992
+ } catch {
1993
+ }
1994
+ }
1995
+ socketPools.delete(this.connectionId);
1692
1996
  }
1693
1997
  const serverInfo = globalTcpServers.get(this.connectionId);
1694
1998
  if (serverInfo && serverInfo.process && !serverInfo.process.killed) {
@@ -1710,12 +2014,12 @@ var QueryEngine = class {
1710
2014
 
1711
2015
  // src/lib/SqliteExecutor.ts
1712
2016
  import { exec } from "child_process";
1713
- import * as path6 from "path";
1714
- import * as fs4 from "fs";
2017
+ import * as path7 from "path";
2018
+ import * as fs5 from "fs";
1715
2019
  import { promisify } from "util";
1716
2020
  import { createRequire as createRequire3 } from "module";
1717
2021
  import { fileURLToPath as fileURLToPath3 } from "url";
1718
- import { dirname as dirname3 } from "path";
2022
+ import { dirname as dirname4 } from "path";
1719
2023
  var execAsync = promisify(exec);
1720
2024
  var SqliteExecutor = class {
1721
2025
  binaryPath;
@@ -1726,13 +2030,13 @@ var SqliteExecutor = class {
1726
2030
  }
1727
2031
  findVersionedBinary(binDir, platform2) {
1728
2032
  try {
1729
- const files = fs4.readdirSync(binDir);
2033
+ const files = fs5.readdirSync(binDir);
1730
2034
  const extension = platform2 === "win32" ? ".exe" : "";
1731
2035
  const platformName = platform2 === "win32" ? "windows" : platform2 === "darwin" ? "macos" : "linux";
1732
2036
  const pattern = new RegExp(`^sqlite-engine-v\\d+\\.\\d+\\.\\d+-${platformName}-x64${extension.replace(".", "\\.")}$`);
1733
2037
  const matchingFile = files.find((f) => pattern.test(f));
1734
2038
  if (matchingFile) {
1735
- return path6.join(binDir, matchingFile);
2039
+ return path7.join(binDir, matchingFile);
1736
2040
  }
1737
2041
  } catch (error) {
1738
2042
  }
@@ -1740,36 +2044,36 @@ var SqliteExecutor = class {
1740
2044
  }
1741
2045
  getBinaryPath() {
1742
2046
  const __filename2 = typeof import.meta !== "undefined" && import.meta.url ? fileURLToPath3(import.meta.url) : "";
1743
- const __dirname = __filename2 ? dirname3(__filename2) : process.cwd();
2047
+ const __dirname = __filename2 ? dirname4(__filename2) : process.cwd();
1744
2048
  const possibleDirs = [
1745
- path6.resolve(process.cwd(), ".dbcube", "bin"),
1746
- path6.resolve(process.cwd(), "node_modules", ".dbcube", "bin"),
1747
- path6.resolve(__dirname, "..", "bin")
2049
+ path7.resolve(process.cwd(), ".dbcube", "bin"),
2050
+ path7.resolve(process.cwd(), "node_modules", ".dbcube", "bin"),
2051
+ path7.resolve(__dirname, "..", "bin")
1748
2052
  ];
1749
2053
  const platform2 = process.platform;
1750
2054
  const extension = platform2 === "win32" ? ".exe" : "";
1751
2055
  const platformName = platform2 === "win32" ? "windows" : platform2 === "darwin" ? "macos" : "linux";
1752
2056
  for (const dir of possibleDirs) {
1753
2057
  const versionedPath = this.findVersionedBinary(dir, platform2);
1754
- if (versionedPath && fs4.existsSync(versionedPath)) {
2058
+ if (versionedPath && fs5.existsSync(versionedPath)) {
1755
2059
  return versionedPath;
1756
2060
  }
1757
2061
  }
1758
2062
  const binaryName = `sqlite-engine-${platformName}-x64${extension}`;
1759
2063
  for (const dir of possibleDirs) {
1760
- const fullPath = path6.join(dir, binaryName);
1761
- if (fs4.existsSync(fullPath)) {
2064
+ const fullPath = path7.join(dir, binaryName);
2065
+ if (fs5.existsSync(fullPath)) {
1762
2066
  return fullPath;
1763
2067
  }
1764
2068
  }
1765
2069
  const fallbackName = `sqlite-engine${extension}`;
1766
2070
  for (const dir of possibleDirs) {
1767
- const fullPath = path6.join(dir, fallbackName);
1768
- if (fs4.existsSync(fullPath)) {
2071
+ const fullPath = path7.join(dir, fallbackName);
2072
+ if (fs5.existsSync(fullPath)) {
1769
2073
  return fullPath;
1770
2074
  }
1771
2075
  }
1772
- return path6.join(possibleDirs[0], binaryName);
2076
+ return path7.join(possibleDirs[0], binaryName);
1773
2077
  }
1774
2078
  async executeBinary(args) {
1775
2079
  const escapedArgs = args.map((arg) => {
@@ -1920,9 +2224,9 @@ var SqliteExecutor = class {
1920
2224
  };
1921
2225
 
1922
2226
  // src/lib/DbConfig.ts
1923
- import * as path7 from "path";
1924
- import fs5 from "fs";
1925
- var rootPath = path7.resolve(process.cwd(), ".dbcube");
2227
+ import * as path8 from "path";
2228
+ import fs6 from "fs";
2229
+ var rootPath = path8.resolve(process.cwd(), ".dbcube");
1926
2230
  var SQLite = class {
1927
2231
  executor = null;
1928
2232
  database;
@@ -1932,11 +2236,11 @@ var SQLite = class {
1932
2236
  async ifExist() {
1933
2237
  if (this.database) {
1934
2238
  const dbPath = this.database || ":memory:";
1935
- const configPath = path7.join(rootPath, dbPath + ".db");
1936
- if (!fs5.existsSync(rootPath)) {
1937
- fs5.mkdirSync(rootPath, { recursive: true });
2239
+ const configPath = path8.join(rootPath, dbPath + ".db");
2240
+ if (!fs6.existsSync(rootPath)) {
2241
+ fs6.mkdirSync(rootPath, { recursive: true });
1938
2242
  }
1939
- if (fs5.existsSync(configPath)) {
2243
+ if (fs6.existsSync(configPath)) {
1940
2244
  return true;
1941
2245
  }
1942
2246
  if (!this.executor) {
@@ -1947,13 +2251,13 @@ var SQLite = class {
1947
2251
  return false;
1948
2252
  }
1949
2253
  async connect() {
1950
- return new Promise(async (resolve5, reject) => {
2254
+ return new Promise(async (resolve6, reject) => {
1951
2255
  try {
1952
2256
  if (!this.executor) {
1953
2257
  const dbPath = this.database || ":memory:";
1954
- const configPath = path7.join(rootPath, dbPath + ".db");
1955
- if (!fs5.existsSync(rootPath)) {
1956
- fs5.mkdirSync(rootPath, { recursive: true });
2258
+ const configPath = path8.join(rootPath, dbPath + ".db");
2259
+ if (!fs6.existsSync(rootPath)) {
2260
+ fs6.mkdirSync(rootPath, { recursive: true });
1957
2261
  }
1958
2262
  this.executor = new SqliteExecutor(configPath);
1959
2263
  const connected = await this.executor.connect();
@@ -1961,22 +2265,22 @@ var SQLite = class {
1961
2265
  throw new Error("Failed to connect to SQLite database");
1962
2266
  }
1963
2267
  }
1964
- resolve5(this.executor);
2268
+ resolve6(this.executor);
1965
2269
  } catch (error) {
1966
2270
  reject(error);
1967
2271
  }
1968
2272
  });
1969
2273
  }
1970
2274
  async disconnect() {
1971
- return new Promise((resolve5) => {
2275
+ return new Promise((resolve6) => {
1972
2276
  if (this.executor) {
1973
2277
  this.executor = null;
1974
2278
  }
1975
- resolve5();
2279
+ resolve6();
1976
2280
  });
1977
2281
  }
1978
2282
  async query(sqlQuery) {
1979
- return new Promise(async (resolve5) => {
2283
+ return new Promise(async (resolve6) => {
1980
2284
  try {
1981
2285
  if (typeof sqlQuery !== "string") {
1982
2286
  throw new Error("The SQL query must be a string.");
@@ -1989,20 +2293,20 @@ var SQLite = class {
1989
2293
  }
1990
2294
  const result = await this.executor.queryMultiple(sqlQuery);
1991
2295
  if (result.status === "error") {
1992
- resolve5({
2296
+ resolve6({
1993
2297
  status: "error",
1994
2298
  message: result.message,
1995
2299
  data: null
1996
2300
  });
1997
2301
  } else {
1998
- resolve5({
2302
+ resolve6({
1999
2303
  status: "success",
2000
2304
  message: "Query executed successfully",
2001
2305
  data: result.data
2002
2306
  });
2003
2307
  }
2004
2308
  } catch (error) {
2005
- resolve5({
2309
+ resolve6({
2006
2310
  status: "error",
2007
2311
  message: error.message || "An error occurred while executing the query.",
2008
2312
  data: null
@@ -2011,7 +2315,7 @@ var SQLite = class {
2011
2315
  });
2012
2316
  }
2013
2317
  async queryWithParameters(sqlQuery, params = []) {
2014
- return new Promise(async (resolve5) => {
2318
+ return new Promise(async (resolve6) => {
2015
2319
  try {
2016
2320
  if (typeof sqlQuery !== "string") {
2017
2321
  throw new Error("The SQL query must be a string.");
@@ -2027,13 +2331,13 @@ var SQLite = class {
2027
2331
  }
2028
2332
  const result = await this.executor.query(sqlQuery, params);
2029
2333
  if (result.status === "error") {
2030
- resolve5({
2334
+ resolve6({
2031
2335
  status: "error",
2032
2336
  message: result.message,
2033
2337
  data: null
2034
2338
  });
2035
2339
  } else {
2036
- resolve5({
2340
+ resolve6({
2037
2341
  status: "success",
2038
2342
  message: "Query executed successfully",
2039
2343
  data: result.data
@@ -2041,7 +2345,7 @@ var SQLite = class {
2041
2345
  }
2042
2346
  } catch (error) {
2043
2347
  console.log(error);
2044
- resolve5({
2348
+ resolve6({
2045
2349
  status: "error",
2046
2350
  message: error.message || "An error occurred while executing the query.",
2047
2351
  data: null
@@ -2135,8 +2439,8 @@ var DbConfig = new SQLite({ DATABASE: "config" });
2135
2439
  var DbConfig_default = DbConfig;
2136
2440
 
2137
2441
  // src/lib/FileLogger.ts
2138
- import * as fs6 from "fs";
2139
- import * as path8 from "path";
2442
+ import * as fs7 from "fs";
2443
+ import * as path9 from "path";
2140
2444
  import { EventEmitter } from "events";
2141
2445
  var FileLogger = class _FileLogger extends EventEmitter {
2142
2446
  static watchers = /* @__PURE__ */ new Map();
@@ -2151,9 +2455,9 @@ var FileLogger = class _FileLogger extends EventEmitter {
2151
2455
  */
2152
2456
  static async write(filePath, message, level = "INFO", append = true) {
2153
2457
  try {
2154
- const dir = path8.dirname(filePath);
2155
- if (!fs6.existsSync(dir)) {
2156
- fs6.mkdirSync(dir, { recursive: true });
2458
+ const dir = path9.dirname(filePath);
2459
+ if (!fs7.existsSync(dir)) {
2460
+ fs7.mkdirSync(dir, { recursive: true });
2157
2461
  }
2158
2462
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
2159
2463
  const formattedMessage = `[${timestamp}] [${level}] ${message}
@@ -2163,9 +2467,9 @@ var FileLogger = class _FileLogger extends EventEmitter {
2163
2467
  return true;
2164
2468
  }
2165
2469
  if (append) {
2166
- await fs6.promises.appendFile(filePath, formattedMessage, "utf8");
2470
+ await fs7.promises.appendFile(filePath, formattedMessage, "utf8");
2167
2471
  } else {
2168
- await fs6.promises.writeFile(filePath, formattedMessage, "utf8");
2472
+ await fs7.promises.writeFile(filePath, formattedMessage, "utf8");
2169
2473
  }
2170
2474
  return true;
2171
2475
  } catch (error) {
@@ -2190,12 +2494,12 @@ var FileLogger = class _FileLogger extends EventEmitter {
2190
2494
  const buffer = _FileLogger.buffers.get(filePath);
2191
2495
  if (buffer && buffer.length > 0) {
2192
2496
  try {
2193
- const dir = path8.dirname(filePath);
2194
- if (!fs6.existsSync(dir)) {
2195
- fs6.mkdirSync(dir, { recursive: true });
2497
+ const dir = path9.dirname(filePath);
2498
+ if (!fs7.existsSync(dir)) {
2499
+ fs7.mkdirSync(dir, { recursive: true });
2196
2500
  }
2197
2501
  const content = buffer.join("");
2198
- await fs6.promises.appendFile(filePath, content, "utf8");
2502
+ await fs7.promises.appendFile(filePath, content, "utf8");
2199
2503
  _FileLogger.buffers.delete(filePath);
2200
2504
  return true;
2201
2505
  } catch (error) {
@@ -2331,10 +2635,10 @@ var FileLogger = class _FileLogger extends EventEmitter {
2331
2635
  // Si debe retornar como array de líneas
2332
2636
  } = options;
2333
2637
  try {
2334
- if (!fs6.existsSync(filePath)) {
2638
+ if (!fs7.existsSync(filePath)) {
2335
2639
  return asArray ? [] : "";
2336
2640
  }
2337
- let content = await fs6.promises.readFile(filePath, "utf8");
2641
+ let content = await fs7.promises.readFile(filePath, "utf8");
2338
2642
  if (asArray) {
2339
2643
  let linesArray = content.split("\n").filter((line) => line.trim() !== "");
2340
2644
  if (lines !== null) {
@@ -2377,15 +2681,15 @@ var FileLogger = class _FileLogger extends EventEmitter {
2377
2681
  } = options;
2378
2682
  let lastSize = 0;
2379
2683
  let lastPosition = 0;
2380
- if (fs6.existsSync(filePath)) {
2381
- const stats = fs6.statSync(filePath);
2684
+ if (fs7.existsSync(filePath)) {
2685
+ const stats = fs7.statSync(filePath);
2382
2686
  lastSize = stats.size;
2383
2687
  lastPosition = fromEnd ? stats.size : 0;
2384
2688
  }
2385
2689
  const listener = async (curr, prev) => {
2386
2690
  try {
2387
2691
  if (curr.size > lastSize) {
2388
- const stream = fs6.createReadStream(filePath, {
2692
+ const stream = fs7.createReadStream(filePath, {
2389
2693
  start: lastPosition,
2390
2694
  end: curr.size - 1,
2391
2695
  encoding: "utf8"
@@ -2413,7 +2717,7 @@ var FileLogger = class _FileLogger extends EventEmitter {
2413
2717
  console.error("Error en watcher:", error);
2414
2718
  }
2415
2719
  };
2416
- fs6.watchFile(filePath, { persistent, interval }, listener);
2720
+ fs7.watchFile(filePath, { persistent, interval }, listener);
2417
2721
  const watcherId = `${filePath}_${Date.now()}`;
2418
2722
  _FileLogger.watchers.set(watcherId, listener);
2419
2723
  return {
@@ -2421,7 +2725,7 @@ var FileLogger = class _FileLogger extends EventEmitter {
2421
2725
  stop: () => {
2422
2726
  const storedListener = _FileLogger.watchers.get(watcherId);
2423
2727
  if (storedListener) {
2424
- fs6.unwatchFile(filePath, storedListener);
2728
+ fs7.unwatchFile(filePath, storedListener);
2425
2729
  _FileLogger.watchers.delete(watcherId);
2426
2730
  }
2427
2731
  },
@@ -2434,7 +2738,7 @@ var FileLogger = class _FileLogger extends EventEmitter {
2434
2738
  static stopAllWatchers() {
2435
2739
  for (const [watcherId] of _FileLogger.watchers) {
2436
2740
  const filePath = watcherId.split("_")[0];
2437
- fs6.unwatchFile(filePath);
2741
+ fs7.unwatchFile(filePath);
2438
2742
  }
2439
2743
  _FileLogger.watchers.clear();
2440
2744
  }
@@ -2464,7 +2768,7 @@ var FileLogger = class _FileLogger extends EventEmitter {
2464
2768
  if (lines.length > maxLines) {
2465
2769
  const keepLines = lines.slice(-maxLines);
2466
2770
  const content = keepLines.join("\n") + "\n";
2467
- await fs6.promises.writeFile(filePath, content, "utf8");
2771
+ await fs7.promises.writeFile(filePath, content, "utf8");
2468
2772
  return lines.length - maxLines;
2469
2773
  }
2470
2774
  return 0;
@@ -2479,8 +2783,8 @@ var FileLogger = class _FileLogger extends EventEmitter {
2479
2783
  */
2480
2784
  static async deleteLogFile(filePath) {
2481
2785
  try {
2482
- if (fs6.existsSync(filePath)) {
2483
- await fs6.promises.unlink(filePath);
2786
+ if (fs7.existsSync(filePath)) {
2787
+ await fs7.promises.unlink(filePath);
2484
2788
  return true;
2485
2789
  }
2486
2790
  return false;