@dbcube/core 5.2.3 → 5.2.4
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/bin.cjs +2 -3
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +2 -3
- package/dist/bin.js.map +1 -1
- package/dist/index.cjs +109 -387
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +10 -33
- package/dist/index.d.ts +10 -33
- package/dist/index.js +110 -387
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -146,15 +146,14 @@ var Downloader = class {
|
|
|
146
146
|
static currentSpinner = null;
|
|
147
147
|
static VERSION_URLS = {
|
|
148
148
|
query: "https://raw.githubusercontent.com/Dbcube/binaries/main/query-engines.json",
|
|
149
|
-
schema: "https://raw.githubusercontent.com/Dbcube/binaries/main/schema-engines.json"
|
|
150
|
-
sqlite: "https://raw.githubusercontent.com/Dbcube/binaries/main/sqlite-engines.json"
|
|
149
|
+
schema: "https://raw.githubusercontent.com/Dbcube/binaries/main/schema-engines.json"
|
|
151
150
|
};
|
|
152
151
|
/**
|
|
153
152
|
* Fetch latest version from GitHub
|
|
154
153
|
*/
|
|
155
154
|
static async fetchLatestVersion(prefix) {
|
|
156
155
|
const url = this.VERSION_URLS[prefix];
|
|
157
|
-
return new Promise((
|
|
156
|
+
return new Promise((resolve5, reject) => {
|
|
158
157
|
https.get(url, (response) => {
|
|
159
158
|
let data = "";
|
|
160
159
|
response.on("data", (chunk) => {
|
|
@@ -164,7 +163,7 @@ var Downloader = class {
|
|
|
164
163
|
try {
|
|
165
164
|
const versions = JSON.parse(data);
|
|
166
165
|
if (versions && versions.length > 0) {
|
|
167
|
-
|
|
166
|
+
resolve5(versions[0].version);
|
|
168
167
|
} else {
|
|
169
168
|
reject(new Error("No versions found"));
|
|
170
169
|
}
|
|
@@ -317,7 +316,7 @@ var Downloader = class {
|
|
|
317
316
|
spinner: "dots12"
|
|
318
317
|
}).start();
|
|
319
318
|
const binariesToProcess = [];
|
|
320
|
-
for (const prefix of ["query", "schema"
|
|
319
|
+
for (const prefix of ["query", "schema"]) {
|
|
321
320
|
try {
|
|
322
321
|
const localVersion = this.getLocalVersion(binDir, prefix);
|
|
323
322
|
const remoteVersion = await this.fetchLatestVersion(prefix);
|
|
@@ -373,7 +372,7 @@ var Downloader = class {
|
|
|
373
372
|
if (attempt < maxRetries && (errorMessage.includes("ECONNRESET") || errorMessage.includes("timeout") || errorMessage.includes("ETIMEDOUT") || errorMessage.includes("ENOTFOUND"))) {
|
|
374
373
|
attempt++;
|
|
375
374
|
console.log(`\u{1F504} Retrying ${binary.prefix}-engine (${attempt}/${maxRetries})...`);
|
|
376
|
-
await new Promise((
|
|
375
|
+
await new Promise((resolve5) => setTimeout(resolve5, 1e3 + Math.random() * 1e3));
|
|
377
376
|
} else {
|
|
378
377
|
throw new Error(`Error downloading ${binary.prefix}: ${errorMessage}`);
|
|
379
378
|
}
|
|
@@ -421,12 +420,12 @@ var Downloader = class {
|
|
|
421
420
|
return `[${filledBar}${emptyBar}] ${percentage}`;
|
|
422
421
|
}
|
|
423
422
|
static downloadFileWithProgress(url, outputPath, prefix) {
|
|
424
|
-
return new Promise((
|
|
423
|
+
return new Promise((resolve5, reject) => {
|
|
425
424
|
const request = https.get(url, { timeout: 0 }, (response) => {
|
|
426
425
|
if (response.statusCode === 302 || response.statusCode === 301) {
|
|
427
426
|
const redirectUrl = response.headers.location;
|
|
428
427
|
if (redirectUrl) {
|
|
429
|
-
return this.downloadFileWithProgress(redirectUrl, outputPath, prefix).then(
|
|
428
|
+
return this.downloadFileWithProgress(redirectUrl, outputPath, prefix).then(resolve5).catch(reject);
|
|
430
429
|
}
|
|
431
430
|
}
|
|
432
431
|
if (response.statusCode !== 200) {
|
|
@@ -449,7 +448,7 @@ var Downloader = class {
|
|
|
449
448
|
}
|
|
450
449
|
});
|
|
451
450
|
response.on("end", () => {
|
|
452
|
-
file.end(() =>
|
|
451
|
+
file.end(() => resolve5());
|
|
453
452
|
});
|
|
454
453
|
response.on("error", (err) => {
|
|
455
454
|
file.close();
|
|
@@ -481,7 +480,7 @@ var Downloader = class {
|
|
|
481
480
|
this.mainSpinner.text = `\u{1F4E5} ${chalk.bold(binary)} - ${progressText}`;
|
|
482
481
|
}
|
|
483
482
|
static extractBinary(zipPath, outputPath, prefix) {
|
|
484
|
-
return new Promise((
|
|
483
|
+
return new Promise((resolve5, reject) => {
|
|
485
484
|
const outDir = path.dirname(outputPath);
|
|
486
485
|
let extracted = 0;
|
|
487
486
|
const pending = [];
|
|
@@ -516,7 +515,7 @@ var Downloader = class {
|
|
|
516
515
|
if (extracted === 0) {
|
|
517
516
|
reject(new Error(`No se encontr\xF3 archivo v\xE1lido en el ZIP para ${prefix}`));
|
|
518
517
|
} else {
|
|
519
|
-
|
|
518
|
+
resolve5();
|
|
520
519
|
}
|
|
521
520
|
}).catch((err) => {
|
|
522
521
|
this.cleanupFile(zipPath);
|
|
@@ -835,22 +834,22 @@ var DaemonClient = class _DaemonClient {
|
|
|
835
834
|
child.unref();
|
|
836
835
|
}
|
|
837
836
|
tryConnect(port) {
|
|
838
|
-
return new Promise((
|
|
837
|
+
return new Promise((resolve5) => {
|
|
839
838
|
const socket = net.createConnection({ host: "127.0.0.1", port }, async () => {
|
|
840
839
|
socket.setNoDelay(true);
|
|
841
840
|
this.attach(socket);
|
|
842
841
|
try {
|
|
843
842
|
const pong = await this.send({ action: "ping" }, 2e3);
|
|
844
|
-
|
|
843
|
+
resolve5(pong.status === 200);
|
|
845
844
|
} catch {
|
|
846
845
|
this.detach();
|
|
847
|
-
|
|
846
|
+
resolve5(false);
|
|
848
847
|
}
|
|
849
848
|
});
|
|
850
|
-
socket.once("error", () =>
|
|
849
|
+
socket.once("error", () => resolve5(false));
|
|
851
850
|
socket.setTimeout(3e3, () => {
|
|
852
851
|
socket.destroy();
|
|
853
|
-
|
|
852
|
+
resolve5(false);
|
|
854
853
|
});
|
|
855
854
|
});
|
|
856
855
|
}
|
|
@@ -898,7 +897,7 @@ var DaemonClient = class _DaemonClient {
|
|
|
898
897
|
* single socket, so pending requests resolve in send order.
|
|
899
898
|
*/
|
|
900
899
|
send(payload, timeoutMs) {
|
|
901
|
-
return new Promise((
|
|
900
|
+
return new Promise((resolve5, reject) => {
|
|
902
901
|
if (!this.socket || this.socket.destroyed) {
|
|
903
902
|
reject(new Error("Daemon not connected"));
|
|
904
903
|
return;
|
|
@@ -909,7 +908,7 @@ var DaemonClient = class _DaemonClient {
|
|
|
909
908
|
reject(new Error("Daemon request timeout"));
|
|
910
909
|
this.detach();
|
|
911
910
|
}, timeoutMs ?? this.requestTimeout);
|
|
912
|
-
this.pending.push({ resolve:
|
|
911
|
+
this.pending.push({ resolve: resolve5, reject, timer });
|
|
913
912
|
this.socket.write(JSON.stringify(payload) + "\n");
|
|
914
913
|
});
|
|
915
914
|
}
|
|
@@ -1113,7 +1112,7 @@ var Engine = class {
|
|
|
1113
1112
|
if (!this.binary) {
|
|
1114
1113
|
throw new Error("Binary not initialized");
|
|
1115
1114
|
}
|
|
1116
|
-
return new Promise((
|
|
1115
|
+
return new Promise((resolve5, reject) => {
|
|
1117
1116
|
const child = spawn2(this.binary[binary], [...this.arguments, ...args]);
|
|
1118
1117
|
let stdoutBuffer = "";
|
|
1119
1118
|
let stderrBuffer = "";
|
|
@@ -1129,7 +1128,7 @@ var Engine = class {
|
|
|
1129
1128
|
if (!isResolved) {
|
|
1130
1129
|
isResolved = true;
|
|
1131
1130
|
clearTimeout(timeoutId);
|
|
1132
|
-
|
|
1131
|
+
resolve5(response);
|
|
1133
1132
|
}
|
|
1134
1133
|
};
|
|
1135
1134
|
const tryParseLines = (buffer) => {
|
|
@@ -1326,10 +1325,10 @@ function loadKoffiBackend() {
|
|
|
1326
1325
|
return { status: 500, message: `Invalid embedded response: ${e.message}`, data: null };
|
|
1327
1326
|
}
|
|
1328
1327
|
};
|
|
1329
|
-
const call = (fn, ...args) => new Promise((
|
|
1328
|
+
const call = (fn, ...args) => new Promise((resolve5, reject) => {
|
|
1330
1329
|
fn.async(...args, (err, ptr) => {
|
|
1331
1330
|
if (err) return reject(err);
|
|
1332
|
-
|
|
1331
|
+
resolve5(take(ptr));
|
|
1333
1332
|
});
|
|
1334
1333
|
});
|
|
1335
1334
|
return {
|
|
@@ -1463,9 +1462,9 @@ var QueryEngine = class {
|
|
|
1463
1462
|
timeout;
|
|
1464
1463
|
connectionId;
|
|
1465
1464
|
tcpPort;
|
|
1466
|
-
constructor(name, timeout = 3e4) {
|
|
1465
|
+
constructor(name, timeout = 3e4, explicitConfig) {
|
|
1467
1466
|
this.name = name;
|
|
1468
|
-
this.config = this.setConfig(name);
|
|
1467
|
+
this.config = explicitConfig ?? this.setConfig(name);
|
|
1469
1468
|
this.arguments = this.setArguments();
|
|
1470
1469
|
this.timeout = this.config?.daemon?.requestTimeoutMs ?? timeout;
|
|
1471
1470
|
this.connectionId = `${name}_query_engine_${this.config.type}_${this.config.config.DATABASE}_${this.config.config.HOST || "localhost"}`;
|
|
@@ -1483,12 +1482,12 @@ var QueryEngine = class {
|
|
|
1483
1482
|
throw new Error("No available ports found in range 9900-9944");
|
|
1484
1483
|
}
|
|
1485
1484
|
isPortAvailable(port) {
|
|
1486
|
-
return new Promise((
|
|
1485
|
+
return new Promise((resolve5) => {
|
|
1487
1486
|
const tester = net2.createServer();
|
|
1488
|
-
tester.once("error", () =>
|
|
1487
|
+
tester.once("error", () => resolve5(false));
|
|
1489
1488
|
tester.once("listening", () => {
|
|
1490
1489
|
tester.close();
|
|
1491
|
-
|
|
1490
|
+
resolve5(true);
|
|
1492
1491
|
});
|
|
1493
1492
|
tester.listen(port, "127.0.0.1");
|
|
1494
1493
|
});
|
|
@@ -1721,7 +1720,7 @@ var QueryEngine = class {
|
|
|
1721
1720
|
throw e;
|
|
1722
1721
|
}
|
|
1723
1722
|
}
|
|
1724
|
-
return new Promise((
|
|
1723
|
+
return new Promise((resolve5) => pool.waiters.push(resolve5));
|
|
1725
1724
|
}
|
|
1726
1725
|
releaseSocket(socket, broken) {
|
|
1727
1726
|
const pool = socketPools.get(this.connectionId);
|
|
@@ -1760,25 +1759,25 @@ var QueryEngine = class {
|
|
|
1760
1759
|
throw new Error("TCP server failed to become ready within timeout");
|
|
1761
1760
|
}
|
|
1762
1761
|
async isServerResponding(port) {
|
|
1763
|
-
return new Promise((
|
|
1762
|
+
return new Promise((resolve5) => {
|
|
1764
1763
|
const client = new net2.Socket();
|
|
1765
1764
|
const timeout = setTimeout(() => {
|
|
1766
1765
|
client.destroy();
|
|
1767
|
-
|
|
1766
|
+
resolve5(false);
|
|
1768
1767
|
}, 1e3);
|
|
1769
1768
|
client.connect(port, "127.0.0.1", () => {
|
|
1770
1769
|
clearTimeout(timeout);
|
|
1771
1770
|
client.destroy();
|
|
1772
|
-
|
|
1771
|
+
resolve5(true);
|
|
1773
1772
|
});
|
|
1774
1773
|
client.on("error", () => {
|
|
1775
1774
|
clearTimeout(timeout);
|
|
1776
|
-
|
|
1775
|
+
resolve5(false);
|
|
1777
1776
|
});
|
|
1778
1777
|
});
|
|
1779
1778
|
}
|
|
1780
1779
|
sleep(ms) {
|
|
1781
|
-
return new Promise((
|
|
1780
|
+
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
1782
1781
|
}
|
|
1783
1782
|
getCachedDML(dmlJson) {
|
|
1784
1783
|
if (queryCache.has(dmlJson)) {
|
|
@@ -1798,7 +1797,7 @@ var QueryEngine = class {
|
|
|
1798
1797
|
throw new Error("Binary not initialized");
|
|
1799
1798
|
}
|
|
1800
1799
|
this.tcpPort = await this.findAvailablePort(this.tcpPort);
|
|
1801
|
-
return new Promise((
|
|
1800
|
+
return new Promise((resolve5, reject) => {
|
|
1802
1801
|
const serverArgs = [...this.arguments, "--action", "server", "--tcp-port", this.tcpPort.toString()];
|
|
1803
1802
|
const serverProcess = spawn3(this.binary["query_engine"], serverArgs);
|
|
1804
1803
|
let started = false;
|
|
@@ -1818,7 +1817,7 @@ var QueryEngine = class {
|
|
|
1818
1817
|
port: this.tcpPort,
|
|
1819
1818
|
process: serverProcess
|
|
1820
1819
|
});
|
|
1821
|
-
|
|
1820
|
+
resolve5();
|
|
1822
1821
|
}
|
|
1823
1822
|
}
|
|
1824
1823
|
});
|
|
@@ -1837,7 +1836,7 @@ var QueryEngine = class {
|
|
|
1837
1836
|
});
|
|
1838
1837
|
}
|
|
1839
1838
|
async createNewConnection(port) {
|
|
1840
|
-
return new Promise((
|
|
1839
|
+
return new Promise((resolve5, reject) => {
|
|
1841
1840
|
const client = new net2.Socket();
|
|
1842
1841
|
client.setNoDelay(true);
|
|
1843
1842
|
client.setKeepAlive(true, 6e4);
|
|
@@ -1847,7 +1846,7 @@ var QueryEngine = class {
|
|
|
1847
1846
|
}, 5e3);
|
|
1848
1847
|
client.connect(port, "127.0.0.1", () => {
|
|
1849
1848
|
clearTimeout(timeout);
|
|
1850
|
-
|
|
1849
|
+
resolve5(client);
|
|
1851
1850
|
});
|
|
1852
1851
|
client.on("error", (error) => {
|
|
1853
1852
|
clearTimeout(timeout);
|
|
@@ -1856,7 +1855,7 @@ var QueryEngine = class {
|
|
|
1856
1855
|
});
|
|
1857
1856
|
}
|
|
1858
1857
|
async executeOnConnection(connection, command) {
|
|
1859
|
-
return new Promise((
|
|
1858
|
+
return new Promise((resolve5, reject) => {
|
|
1860
1859
|
let responseBuffer = "";
|
|
1861
1860
|
let isResolved = false;
|
|
1862
1861
|
const timeout = setTimeout(() => {
|
|
@@ -1881,7 +1880,7 @@ var QueryEngine = class {
|
|
|
1881
1880
|
connection.removeListener("error", onError);
|
|
1882
1881
|
try {
|
|
1883
1882
|
const response = JSON.parse(line.slice(marker + "PROCESS_RESPONSE:".length));
|
|
1884
|
-
|
|
1883
|
+
resolve5({
|
|
1885
1884
|
status: response.status,
|
|
1886
1885
|
message: response.message,
|
|
1887
1886
|
data: response.data
|
|
@@ -1910,7 +1909,7 @@ var QueryEngine = class {
|
|
|
1910
1909
|
if (!this.binary) {
|
|
1911
1910
|
throw new Error("Binary not initialized");
|
|
1912
1911
|
}
|
|
1913
|
-
return new Promise((
|
|
1912
|
+
return new Promise((resolve5, reject) => {
|
|
1914
1913
|
const child = spawn3(this.binary[binary], [...this.arguments, ...args]);
|
|
1915
1914
|
let stdoutBuffer = "";
|
|
1916
1915
|
let stderrBuffer = "";
|
|
@@ -1926,7 +1925,7 @@ var QueryEngine = class {
|
|
|
1926
1925
|
if (!isResolved) {
|
|
1927
1926
|
isResolved = true;
|
|
1928
1927
|
clearTimeout(timeoutId);
|
|
1929
|
-
|
|
1928
|
+
resolve5(response);
|
|
1930
1929
|
}
|
|
1931
1930
|
};
|
|
1932
1931
|
const tryParseLines = (buffer) => {
|
|
@@ -2012,346 +2011,70 @@ var QueryEngine = class {
|
|
|
2012
2011
|
}
|
|
2013
2012
|
};
|
|
2014
2013
|
|
|
2015
|
-
// src/lib/SqliteExecutor.ts
|
|
2016
|
-
import { exec } from "child_process";
|
|
2017
|
-
import * as path7 from "path";
|
|
2018
|
-
import * as fs5 from "fs";
|
|
2019
|
-
import { promisify } from "util";
|
|
2020
|
-
import { createRequire as createRequire3 } from "module";
|
|
2021
|
-
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
2022
|
-
import { dirname as dirname4 } from "path";
|
|
2023
|
-
var execAsync = promisify(exec);
|
|
2024
|
-
var SqliteExecutor = class {
|
|
2025
|
-
binaryPath;
|
|
2026
|
-
dbPath;
|
|
2027
|
-
constructor(dbPath) {
|
|
2028
|
-
this.dbPath = dbPath;
|
|
2029
|
-
this.binaryPath = this.getBinaryPath();
|
|
2030
|
-
}
|
|
2031
|
-
findVersionedBinary(binDir, platform2) {
|
|
2032
|
-
try {
|
|
2033
|
-
const files = fs5.readdirSync(binDir);
|
|
2034
|
-
const extension = platform2 === "win32" ? ".exe" : "";
|
|
2035
|
-
const platformName = platform2 === "win32" ? "windows" : platform2 === "darwin" ? "macos" : "linux";
|
|
2036
|
-
const pattern = new RegExp(`^sqlite-engine-v\\d+\\.\\d+\\.\\d+-${platformName}-x64${extension.replace(".", "\\.")}$`);
|
|
2037
|
-
const matchingFile = files.find((f) => pattern.test(f));
|
|
2038
|
-
if (matchingFile) {
|
|
2039
|
-
return path7.join(binDir, matchingFile);
|
|
2040
|
-
}
|
|
2041
|
-
} catch (error) {
|
|
2042
|
-
}
|
|
2043
|
-
return null;
|
|
2044
|
-
}
|
|
2045
|
-
getBinaryPath() {
|
|
2046
|
-
const __filename2 = typeof import.meta !== "undefined" && import.meta.url ? fileURLToPath3(import.meta.url) : "";
|
|
2047
|
-
const __dirname = __filename2 ? dirname4(__filename2) : process.cwd();
|
|
2048
|
-
const possibleDirs = [
|
|
2049
|
-
path7.resolve(process.cwd(), ".dbcube", "bin"),
|
|
2050
|
-
path7.resolve(process.cwd(), "node_modules", ".dbcube", "bin"),
|
|
2051
|
-
path7.resolve(__dirname, "..", "bin")
|
|
2052
|
-
];
|
|
2053
|
-
const platform2 = process.platform;
|
|
2054
|
-
const extension = platform2 === "win32" ? ".exe" : "";
|
|
2055
|
-
const platformName = platform2 === "win32" ? "windows" : platform2 === "darwin" ? "macos" : "linux";
|
|
2056
|
-
for (const dir of possibleDirs) {
|
|
2057
|
-
const versionedPath = this.findVersionedBinary(dir, platform2);
|
|
2058
|
-
if (versionedPath && fs5.existsSync(versionedPath)) {
|
|
2059
|
-
return versionedPath;
|
|
2060
|
-
}
|
|
2061
|
-
}
|
|
2062
|
-
const binaryName = `sqlite-engine-${platformName}-x64${extension}`;
|
|
2063
|
-
for (const dir of possibleDirs) {
|
|
2064
|
-
const fullPath = path7.join(dir, binaryName);
|
|
2065
|
-
if (fs5.existsSync(fullPath)) {
|
|
2066
|
-
return fullPath;
|
|
2067
|
-
}
|
|
2068
|
-
}
|
|
2069
|
-
const fallbackName = `sqlite-engine${extension}`;
|
|
2070
|
-
for (const dir of possibleDirs) {
|
|
2071
|
-
const fullPath = path7.join(dir, fallbackName);
|
|
2072
|
-
if (fs5.existsSync(fullPath)) {
|
|
2073
|
-
return fullPath;
|
|
2074
|
-
}
|
|
2075
|
-
}
|
|
2076
|
-
return path7.join(possibleDirs[0], binaryName);
|
|
2077
|
-
}
|
|
2078
|
-
async executeBinary(args) {
|
|
2079
|
-
const escapedArgs = args.map((arg) => {
|
|
2080
|
-
if (arg.includes(" ") || arg.includes('"') || arg.includes("(") || arg.includes(")")) {
|
|
2081
|
-
return `"${arg.replace(/"/g, '\\"')}"`;
|
|
2082
|
-
}
|
|
2083
|
-
return arg;
|
|
2084
|
-
});
|
|
2085
|
-
const command = `"${this.binaryPath}" ${escapedArgs.join(" ")}`;
|
|
2086
|
-
try {
|
|
2087
|
-
const { stdout, stderr } = await execAsync(command, {
|
|
2088
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
2089
|
-
// 10MB buffer
|
|
2090
|
-
timeout: 3e4
|
|
2091
|
-
// 30s timeout
|
|
2092
|
-
});
|
|
2093
|
-
if (stderr && stderr.trim()) {
|
|
2094
|
-
console.warn("SQLite Engine Warning:", stderr);
|
|
2095
|
-
}
|
|
2096
|
-
const result = JSON.parse(stdout.trim());
|
|
2097
|
-
return result;
|
|
2098
|
-
} catch (error) {
|
|
2099
|
-
if (error.stdout) {
|
|
2100
|
-
try {
|
|
2101
|
-
const result = JSON.parse(error.stdout.trim());
|
|
2102
|
-
return result;
|
|
2103
|
-
} catch (parseError) {
|
|
2104
|
-
}
|
|
2105
|
-
}
|
|
2106
|
-
throw new Error(`SQLite execution failed: ${error.message}`);
|
|
2107
|
-
}
|
|
2108
|
-
}
|
|
2109
|
-
async connect() {
|
|
2110
|
-
try {
|
|
2111
|
-
const result = await this.executeBinary([
|
|
2112
|
-
"--action",
|
|
2113
|
-
"connect",
|
|
2114
|
-
"--database",
|
|
2115
|
-
this.dbPath
|
|
2116
|
-
]);
|
|
2117
|
-
return result.status === "success";
|
|
2118
|
-
} catch (error) {
|
|
2119
|
-
return false;
|
|
2120
|
-
}
|
|
2121
|
-
}
|
|
2122
|
-
async exists() {
|
|
2123
|
-
try {
|
|
2124
|
-
const result = await this.executeBinary([
|
|
2125
|
-
"--action",
|
|
2126
|
-
"exists",
|
|
2127
|
-
"--database",
|
|
2128
|
-
this.dbPath
|
|
2129
|
-
]);
|
|
2130
|
-
return result.status === "success" && result.data === true;
|
|
2131
|
-
} catch (error) {
|
|
2132
|
-
return false;
|
|
2133
|
-
}
|
|
2134
|
-
}
|
|
2135
|
-
async query(sql, params) {
|
|
2136
|
-
const args = [
|
|
2137
|
-
"--action",
|
|
2138
|
-
"query",
|
|
2139
|
-
"--database",
|
|
2140
|
-
this.dbPath,
|
|
2141
|
-
"--query",
|
|
2142
|
-
sql
|
|
2143
|
-
];
|
|
2144
|
-
if (params && params.length > 0) {
|
|
2145
|
-
args.push("--params", JSON.stringify(params));
|
|
2146
|
-
}
|
|
2147
|
-
return this.executeBinary(args);
|
|
2148
|
-
}
|
|
2149
|
-
// Método para múltiples queries (como lo hace better-sqlite3)
|
|
2150
|
-
async queryMultiple(sql) {
|
|
2151
|
-
return this.query(sql);
|
|
2152
|
-
}
|
|
2153
|
-
// Método prepare que simula prepared statements
|
|
2154
|
-
prepare(sql) {
|
|
2155
|
-
return {
|
|
2156
|
-
all: async (...params) => {
|
|
2157
|
-
const result = await this.query(sql, params);
|
|
2158
|
-
if (result.status === "error") {
|
|
2159
|
-
throw new Error(result.message);
|
|
2160
|
-
}
|
|
2161
|
-
return Array.isArray(result.data) ? result.data : [];
|
|
2162
|
-
},
|
|
2163
|
-
run: async (...params) => {
|
|
2164
|
-
const result = await this.query(sql, params);
|
|
2165
|
-
if (result.status === "error") {
|
|
2166
|
-
throw new Error(result.message);
|
|
2167
|
-
}
|
|
2168
|
-
if (typeof result.data === "object" && result.data.hasOwnProperty("changes") && result.data.hasOwnProperty("lastID")) {
|
|
2169
|
-
return result.data;
|
|
2170
|
-
}
|
|
2171
|
-
return { changes: 0, lastID: 0 };
|
|
2172
|
-
}
|
|
2173
|
-
};
|
|
2174
|
-
}
|
|
2175
|
-
// Para compatibilidad con better-sqlite3 API sincrona usando deasync si es necesario
|
|
2176
|
-
prepareSync(sql) {
|
|
2177
|
-
const __filename2 = typeof import.meta !== "undefined" && import.meta.url ? fileURLToPath3(import.meta.url) : "";
|
|
2178
|
-
const requireUrl = __filename2 || import.meta.url;
|
|
2179
|
-
const require2 = createRequire3(requireUrl);
|
|
2180
|
-
const deasync = require2("deasync");
|
|
2181
|
-
return {
|
|
2182
|
-
all: (...params) => {
|
|
2183
|
-
let result;
|
|
2184
|
-
let done = false;
|
|
2185
|
-
let error;
|
|
2186
|
-
this.query(sql, params).then((res) => {
|
|
2187
|
-
if (res.status === "error") {
|
|
2188
|
-
error = new Error(res.message);
|
|
2189
|
-
} else {
|
|
2190
|
-
result = Array.isArray(res.data) ? res.data : [];
|
|
2191
|
-
}
|
|
2192
|
-
done = true;
|
|
2193
|
-
}).catch((err) => {
|
|
2194
|
-
error = err;
|
|
2195
|
-
done = true;
|
|
2196
|
-
});
|
|
2197
|
-
deasync.loopWhile(() => !done);
|
|
2198
|
-
if (error) throw error;
|
|
2199
|
-
return result;
|
|
2200
|
-
},
|
|
2201
|
-
run: (...params) => {
|
|
2202
|
-
let result;
|
|
2203
|
-
let done = false;
|
|
2204
|
-
let error;
|
|
2205
|
-
this.query(sql, params).then((res) => {
|
|
2206
|
-
if (res.status === "error") {
|
|
2207
|
-
error = new Error(res.message);
|
|
2208
|
-
} else if (typeof res.data === "object" && res.data.hasOwnProperty("changes") && res.data.hasOwnProperty("lastID")) {
|
|
2209
|
-
result = res.data;
|
|
2210
|
-
} else {
|
|
2211
|
-
result = { changes: 0, lastID: 0 };
|
|
2212
|
-
}
|
|
2213
|
-
done = true;
|
|
2214
|
-
}).catch((err) => {
|
|
2215
|
-
error = err;
|
|
2216
|
-
done = true;
|
|
2217
|
-
});
|
|
2218
|
-
deasync.loopWhile(() => !done);
|
|
2219
|
-
if (error) throw error;
|
|
2220
|
-
return result;
|
|
2221
|
-
}
|
|
2222
|
-
};
|
|
2223
|
-
}
|
|
2224
|
-
};
|
|
2225
|
-
|
|
2226
2014
|
// src/lib/DbConfig.ts
|
|
2227
|
-
import * as
|
|
2228
|
-
import
|
|
2229
|
-
var rootPath =
|
|
2015
|
+
import * as path7 from "path";
|
|
2016
|
+
import fs5 from "fs";
|
|
2017
|
+
var rootPath = path7.resolve(process.cwd(), ".dbcube");
|
|
2230
2018
|
var SQLite = class {
|
|
2231
|
-
executor = null;
|
|
2232
2019
|
database;
|
|
2020
|
+
engine = null;
|
|
2233
2021
|
constructor(config) {
|
|
2234
|
-
this.database = config.DATABASE;
|
|
2022
|
+
this.database = config.DATABASE || "config";
|
|
2023
|
+
}
|
|
2024
|
+
/** Ruta del archivo SQLite interno (.dbcube/<database>.db). */
|
|
2025
|
+
dbFilePath() {
|
|
2026
|
+
return path7.join(rootPath, this.database + ".db");
|
|
2027
|
+
}
|
|
2028
|
+
/** QueryEngine sqlite apuntando al archivo interno, con config explícito
|
|
2029
|
+
* (no vive en dbcube.config.js). La ruta relativa `.dbcube/<db>` deja que
|
|
2030
|
+
* QueryEngine le añada `.db` → `.dbcube/<db>.db`, relativo al CWD. */
|
|
2031
|
+
getEngine() {
|
|
2032
|
+
if (!this.engine) {
|
|
2033
|
+
const relativeDb = path7.join(".dbcube", this.database).replace(/\\/g, "/");
|
|
2034
|
+
this.engine = new QueryEngine(`dbcube-internal-${this.database}`, 3e4, {
|
|
2035
|
+
type: "sqlite",
|
|
2036
|
+
config: { DATABASE: relativeDb }
|
|
2037
|
+
});
|
|
2038
|
+
}
|
|
2039
|
+
return this.engine;
|
|
2235
2040
|
}
|
|
2236
2041
|
async ifExist() {
|
|
2237
|
-
if (
|
|
2238
|
-
|
|
2239
|
-
const configPath = path8.join(rootPath, dbPath + ".db");
|
|
2240
|
-
if (!fs6.existsSync(rootPath)) {
|
|
2241
|
-
fs6.mkdirSync(rootPath, { recursive: true });
|
|
2242
|
-
}
|
|
2243
|
-
if (fs6.existsSync(configPath)) {
|
|
2244
|
-
return true;
|
|
2245
|
-
}
|
|
2246
|
-
if (!this.executor) {
|
|
2247
|
-
this.executor = new SqliteExecutor(configPath);
|
|
2248
|
-
}
|
|
2249
|
-
return await this.executor.exists();
|
|
2042
|
+
if (!fs5.existsSync(rootPath)) {
|
|
2043
|
+
fs5.mkdirSync(rootPath, { recursive: true });
|
|
2250
2044
|
}
|
|
2251
|
-
return
|
|
2045
|
+
return fs5.existsSync(this.dbFilePath());
|
|
2252
2046
|
}
|
|
2253
2047
|
async connect() {
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
const configPath = path8.join(rootPath, dbPath + ".db");
|
|
2259
|
-
if (!fs6.existsSync(rootPath)) {
|
|
2260
|
-
fs6.mkdirSync(rootPath, { recursive: true });
|
|
2261
|
-
}
|
|
2262
|
-
this.executor = new SqliteExecutor(configPath);
|
|
2263
|
-
const connected = await this.executor.connect();
|
|
2264
|
-
if (!connected) {
|
|
2265
|
-
throw new Error("Failed to connect to SQLite database");
|
|
2266
|
-
}
|
|
2267
|
-
}
|
|
2268
|
-
resolve6(this.executor);
|
|
2269
|
-
} catch (error) {
|
|
2270
|
-
reject(error);
|
|
2271
|
-
}
|
|
2272
|
-
});
|
|
2048
|
+
if (!fs5.existsSync(rootPath)) {
|
|
2049
|
+
fs5.mkdirSync(rootPath, { recursive: true });
|
|
2050
|
+
}
|
|
2051
|
+
return this.getEngine();
|
|
2273
2052
|
}
|
|
2274
2053
|
async disconnect() {
|
|
2275
|
-
return new Promise((resolve6) => {
|
|
2276
|
-
if (this.executor) {
|
|
2277
|
-
this.executor = null;
|
|
2278
|
-
}
|
|
2279
|
-
resolve6();
|
|
2280
|
-
});
|
|
2281
2054
|
}
|
|
2282
2055
|
async query(sqlQuery) {
|
|
2283
|
-
return
|
|
2284
|
-
try {
|
|
2285
|
-
if (typeof sqlQuery !== "string") {
|
|
2286
|
-
throw new Error("The SQL query must be a string.");
|
|
2287
|
-
}
|
|
2288
|
-
if (!this.executor) {
|
|
2289
|
-
await this.connect();
|
|
2290
|
-
}
|
|
2291
|
-
if (!this.executor) {
|
|
2292
|
-
throw new Error("Database connection is not available.");
|
|
2293
|
-
}
|
|
2294
|
-
const result = await this.executor.queryMultiple(sqlQuery);
|
|
2295
|
-
if (result.status === "error") {
|
|
2296
|
-
resolve6({
|
|
2297
|
-
status: "error",
|
|
2298
|
-
message: result.message,
|
|
2299
|
-
data: null
|
|
2300
|
-
});
|
|
2301
|
-
} else {
|
|
2302
|
-
resolve6({
|
|
2303
|
-
status: "success",
|
|
2304
|
-
message: "Query executed successfully",
|
|
2305
|
-
data: result.data
|
|
2306
|
-
});
|
|
2307
|
-
}
|
|
2308
|
-
} catch (error) {
|
|
2309
|
-
resolve6({
|
|
2310
|
-
status: "error",
|
|
2311
|
-
message: error.message || "An error occurred while executing the query.",
|
|
2312
|
-
data: null
|
|
2313
|
-
});
|
|
2314
|
-
}
|
|
2315
|
-
});
|
|
2056
|
+
return this.queryWithParameters(sqlQuery, []);
|
|
2316
2057
|
}
|
|
2317
2058
|
async queryWithParameters(sqlQuery, params = []) {
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
throw new Error("The SQL query must be a string.");
|
|
2322
|
-
}
|
|
2323
|
-
if (!Array.isArray(params)) {
|
|
2324
|
-
throw new Error("Parameters must be an array.");
|
|
2325
|
-
}
|
|
2326
|
-
if (!this.executor) {
|
|
2327
|
-
await this.connect();
|
|
2328
|
-
}
|
|
2329
|
-
if (!this.executor) {
|
|
2330
|
-
throw new Error("Database connection is not available.");
|
|
2331
|
-
}
|
|
2332
|
-
const result = await this.executor.query(sqlQuery, params);
|
|
2333
|
-
if (result.status === "error") {
|
|
2334
|
-
resolve6({
|
|
2335
|
-
status: "error",
|
|
2336
|
-
message: result.message,
|
|
2337
|
-
data: null
|
|
2338
|
-
});
|
|
2339
|
-
} else {
|
|
2340
|
-
resolve6({
|
|
2341
|
-
status: "success",
|
|
2342
|
-
message: "Query executed successfully",
|
|
2343
|
-
data: result.data
|
|
2344
|
-
});
|
|
2345
|
-
}
|
|
2346
|
-
} catch (error) {
|
|
2347
|
-
console.log(error);
|
|
2348
|
-
resolve6({
|
|
2349
|
-
status: "error",
|
|
2350
|
-
message: error.message || "An error occurred while executing the query.",
|
|
2351
|
-
data: null
|
|
2352
|
-
});
|
|
2059
|
+
try {
|
|
2060
|
+
if (typeof sqlQuery !== "string") {
|
|
2061
|
+
throw new Error("The SQL query must be a string.");
|
|
2353
2062
|
}
|
|
2354
|
-
|
|
2063
|
+
if (!Array.isArray(params)) {
|
|
2064
|
+
throw new Error("Parameters must be an array.");
|
|
2065
|
+
}
|
|
2066
|
+
const response = await this.getEngine().rawQuery(sqlQuery, params);
|
|
2067
|
+
if (response.status !== 200) {
|
|
2068
|
+
return { status: "error", message: response.message || "Query failed", data: null };
|
|
2069
|
+
}
|
|
2070
|
+
return { status: "success", message: "Query executed successfully", data: response.data };
|
|
2071
|
+
} catch (error) {
|
|
2072
|
+
return {
|
|
2073
|
+
status: "error",
|
|
2074
|
+
message: error.message || "An error occurred while executing the query.",
|
|
2075
|
+
data: null
|
|
2076
|
+
};
|
|
2077
|
+
}
|
|
2355
2078
|
}
|
|
2356
2079
|
convertToParameterizedQuery(sql) {
|
|
2357
2080
|
const normalizedSql = sql.replace(/\s+/g, " ").trim();
|
|
@@ -2439,8 +2162,8 @@ var DbConfig = new SQLite({ DATABASE: "config" });
|
|
|
2439
2162
|
var DbConfig_default = DbConfig;
|
|
2440
2163
|
|
|
2441
2164
|
// src/lib/FileLogger.ts
|
|
2442
|
-
import * as
|
|
2443
|
-
import * as
|
|
2165
|
+
import * as fs6 from "fs";
|
|
2166
|
+
import * as path8 from "path";
|
|
2444
2167
|
import { EventEmitter } from "events";
|
|
2445
2168
|
var FileLogger = class _FileLogger extends EventEmitter {
|
|
2446
2169
|
static watchers = /* @__PURE__ */ new Map();
|
|
@@ -2455,9 +2178,9 @@ var FileLogger = class _FileLogger extends EventEmitter {
|
|
|
2455
2178
|
*/
|
|
2456
2179
|
static async write(filePath, message, level = "INFO", append = true) {
|
|
2457
2180
|
try {
|
|
2458
|
-
const dir =
|
|
2459
|
-
if (!
|
|
2460
|
-
|
|
2181
|
+
const dir = path8.dirname(filePath);
|
|
2182
|
+
if (!fs6.existsSync(dir)) {
|
|
2183
|
+
fs6.mkdirSync(dir, { recursive: true });
|
|
2461
2184
|
}
|
|
2462
2185
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
2463
2186
|
const formattedMessage = `[${timestamp}] [${level}] ${message}
|
|
@@ -2467,9 +2190,9 @@ var FileLogger = class _FileLogger extends EventEmitter {
|
|
|
2467
2190
|
return true;
|
|
2468
2191
|
}
|
|
2469
2192
|
if (append) {
|
|
2470
|
-
await
|
|
2193
|
+
await fs6.promises.appendFile(filePath, formattedMessage, "utf8");
|
|
2471
2194
|
} else {
|
|
2472
|
-
await
|
|
2195
|
+
await fs6.promises.writeFile(filePath, formattedMessage, "utf8");
|
|
2473
2196
|
}
|
|
2474
2197
|
return true;
|
|
2475
2198
|
} catch (error) {
|
|
@@ -2494,12 +2217,12 @@ var FileLogger = class _FileLogger extends EventEmitter {
|
|
|
2494
2217
|
const buffer = _FileLogger.buffers.get(filePath);
|
|
2495
2218
|
if (buffer && buffer.length > 0) {
|
|
2496
2219
|
try {
|
|
2497
|
-
const dir =
|
|
2498
|
-
if (!
|
|
2499
|
-
|
|
2220
|
+
const dir = path8.dirname(filePath);
|
|
2221
|
+
if (!fs6.existsSync(dir)) {
|
|
2222
|
+
fs6.mkdirSync(dir, { recursive: true });
|
|
2500
2223
|
}
|
|
2501
2224
|
const content = buffer.join("");
|
|
2502
|
-
await
|
|
2225
|
+
await fs6.promises.appendFile(filePath, content, "utf8");
|
|
2503
2226
|
_FileLogger.buffers.delete(filePath);
|
|
2504
2227
|
return true;
|
|
2505
2228
|
} catch (error) {
|
|
@@ -2635,10 +2358,10 @@ var FileLogger = class _FileLogger extends EventEmitter {
|
|
|
2635
2358
|
// Si debe retornar como array de líneas
|
|
2636
2359
|
} = options;
|
|
2637
2360
|
try {
|
|
2638
|
-
if (!
|
|
2361
|
+
if (!fs6.existsSync(filePath)) {
|
|
2639
2362
|
return asArray ? [] : "";
|
|
2640
2363
|
}
|
|
2641
|
-
let content = await
|
|
2364
|
+
let content = await fs6.promises.readFile(filePath, "utf8");
|
|
2642
2365
|
if (asArray) {
|
|
2643
2366
|
let linesArray = content.split("\n").filter((line) => line.trim() !== "");
|
|
2644
2367
|
if (lines !== null) {
|
|
@@ -2681,15 +2404,15 @@ var FileLogger = class _FileLogger extends EventEmitter {
|
|
|
2681
2404
|
} = options;
|
|
2682
2405
|
let lastSize = 0;
|
|
2683
2406
|
let lastPosition = 0;
|
|
2684
|
-
if (
|
|
2685
|
-
const stats =
|
|
2407
|
+
if (fs6.existsSync(filePath)) {
|
|
2408
|
+
const stats = fs6.statSync(filePath);
|
|
2686
2409
|
lastSize = stats.size;
|
|
2687
2410
|
lastPosition = fromEnd ? stats.size : 0;
|
|
2688
2411
|
}
|
|
2689
2412
|
const listener = async (curr, prev) => {
|
|
2690
2413
|
try {
|
|
2691
2414
|
if (curr.size > lastSize) {
|
|
2692
|
-
const stream =
|
|
2415
|
+
const stream = fs6.createReadStream(filePath, {
|
|
2693
2416
|
start: lastPosition,
|
|
2694
2417
|
end: curr.size - 1,
|
|
2695
2418
|
encoding: "utf8"
|
|
@@ -2717,7 +2440,7 @@ var FileLogger = class _FileLogger extends EventEmitter {
|
|
|
2717
2440
|
console.error("Error en watcher:", error);
|
|
2718
2441
|
}
|
|
2719
2442
|
};
|
|
2720
|
-
|
|
2443
|
+
fs6.watchFile(filePath, { persistent, interval }, listener);
|
|
2721
2444
|
const watcherId = `${filePath}_${Date.now()}`;
|
|
2722
2445
|
_FileLogger.watchers.set(watcherId, listener);
|
|
2723
2446
|
return {
|
|
@@ -2725,7 +2448,7 @@ var FileLogger = class _FileLogger extends EventEmitter {
|
|
|
2725
2448
|
stop: () => {
|
|
2726
2449
|
const storedListener = _FileLogger.watchers.get(watcherId);
|
|
2727
2450
|
if (storedListener) {
|
|
2728
|
-
|
|
2451
|
+
fs6.unwatchFile(filePath, storedListener);
|
|
2729
2452
|
_FileLogger.watchers.delete(watcherId);
|
|
2730
2453
|
}
|
|
2731
2454
|
},
|
|
@@ -2738,7 +2461,7 @@ var FileLogger = class _FileLogger extends EventEmitter {
|
|
|
2738
2461
|
static stopAllWatchers() {
|
|
2739
2462
|
for (const [watcherId] of _FileLogger.watchers) {
|
|
2740
2463
|
const filePath = watcherId.split("_")[0];
|
|
2741
|
-
|
|
2464
|
+
fs6.unwatchFile(filePath);
|
|
2742
2465
|
}
|
|
2743
2466
|
_FileLogger.watchers.clear();
|
|
2744
2467
|
}
|
|
@@ -2768,7 +2491,7 @@ var FileLogger = class _FileLogger extends EventEmitter {
|
|
|
2768
2491
|
if (lines.length > maxLines) {
|
|
2769
2492
|
const keepLines = lines.slice(-maxLines);
|
|
2770
2493
|
const content = keepLines.join("\n") + "\n";
|
|
2771
|
-
await
|
|
2494
|
+
await fs6.promises.writeFile(filePath, content, "utf8");
|
|
2772
2495
|
return lines.length - maxLines;
|
|
2773
2496
|
}
|
|
2774
2497
|
return 0;
|
|
@@ -2783,8 +2506,8 @@ var FileLogger = class _FileLogger extends EventEmitter {
|
|
|
2783
2506
|
*/
|
|
2784
2507
|
static async deleteLogFile(filePath) {
|
|
2785
2508
|
try {
|
|
2786
|
-
if (
|
|
2787
|
-
await
|
|
2509
|
+
if (fs6.existsSync(filePath)) {
|
|
2510
|
+
await fs6.promises.unlink(filePath);
|
|
2788
2511
|
return true;
|
|
2789
2512
|
}
|
|
2790
2513
|
return false;
|