@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.cjs
CHANGED
|
@@ -186,15 +186,14 @@ var Downloader = class {
|
|
|
186
186
|
static currentSpinner = null;
|
|
187
187
|
static VERSION_URLS = {
|
|
188
188
|
query: "https://raw.githubusercontent.com/Dbcube/binaries/main/query-engines.json",
|
|
189
|
-
schema: "https://raw.githubusercontent.com/Dbcube/binaries/main/schema-engines.json"
|
|
190
|
-
sqlite: "https://raw.githubusercontent.com/Dbcube/binaries/main/sqlite-engines.json"
|
|
189
|
+
schema: "https://raw.githubusercontent.com/Dbcube/binaries/main/schema-engines.json"
|
|
191
190
|
};
|
|
192
191
|
/**
|
|
193
192
|
* Fetch latest version from GitHub
|
|
194
193
|
*/
|
|
195
194
|
static async fetchLatestVersion(prefix) {
|
|
196
195
|
const url = this.VERSION_URLS[prefix];
|
|
197
|
-
return new Promise((
|
|
196
|
+
return new Promise((resolve5, reject) => {
|
|
198
197
|
https.get(url, (response) => {
|
|
199
198
|
let data = "";
|
|
200
199
|
response.on("data", (chunk) => {
|
|
@@ -204,7 +203,7 @@ var Downloader = class {
|
|
|
204
203
|
try {
|
|
205
204
|
const versions = JSON.parse(data);
|
|
206
205
|
if (versions && versions.length > 0) {
|
|
207
|
-
|
|
206
|
+
resolve5(versions[0].version);
|
|
208
207
|
} else {
|
|
209
208
|
reject(new Error("No versions found"));
|
|
210
209
|
}
|
|
@@ -357,7 +356,7 @@ var Downloader = class {
|
|
|
357
356
|
spinner: "dots12"
|
|
358
357
|
}).start();
|
|
359
358
|
const binariesToProcess = [];
|
|
360
|
-
for (const prefix of ["query", "schema"
|
|
359
|
+
for (const prefix of ["query", "schema"]) {
|
|
361
360
|
try {
|
|
362
361
|
const localVersion = this.getLocalVersion(binDir, prefix);
|
|
363
362
|
const remoteVersion = await this.fetchLatestVersion(prefix);
|
|
@@ -413,7 +412,7 @@ var Downloader = class {
|
|
|
413
412
|
if (attempt < maxRetries && (errorMessage.includes("ECONNRESET") || errorMessage.includes("timeout") || errorMessage.includes("ETIMEDOUT") || errorMessage.includes("ENOTFOUND"))) {
|
|
414
413
|
attempt++;
|
|
415
414
|
console.log(`\u{1F504} Retrying ${binary.prefix}-engine (${attempt}/${maxRetries})...`);
|
|
416
|
-
await new Promise((
|
|
415
|
+
await new Promise((resolve5) => setTimeout(resolve5, 1e3 + Math.random() * 1e3));
|
|
417
416
|
} else {
|
|
418
417
|
throw new Error(`Error downloading ${binary.prefix}: ${errorMessage}`);
|
|
419
418
|
}
|
|
@@ -461,12 +460,12 @@ var Downloader = class {
|
|
|
461
460
|
return `[${filledBar}${emptyBar}] ${percentage}`;
|
|
462
461
|
}
|
|
463
462
|
static downloadFileWithProgress(url, outputPath, prefix) {
|
|
464
|
-
return new Promise((
|
|
463
|
+
return new Promise((resolve5, reject) => {
|
|
465
464
|
const request = https.get(url, { timeout: 0 }, (response) => {
|
|
466
465
|
if (response.statusCode === 302 || response.statusCode === 301) {
|
|
467
466
|
const redirectUrl = response.headers.location;
|
|
468
467
|
if (redirectUrl) {
|
|
469
|
-
return this.downloadFileWithProgress(redirectUrl, outputPath, prefix).then(
|
|
468
|
+
return this.downloadFileWithProgress(redirectUrl, outputPath, prefix).then(resolve5).catch(reject);
|
|
470
469
|
}
|
|
471
470
|
}
|
|
472
471
|
if (response.statusCode !== 200) {
|
|
@@ -489,7 +488,7 @@ var Downloader = class {
|
|
|
489
488
|
}
|
|
490
489
|
});
|
|
491
490
|
response.on("end", () => {
|
|
492
|
-
file.end(() =>
|
|
491
|
+
file.end(() => resolve5());
|
|
493
492
|
});
|
|
494
493
|
response.on("error", (err) => {
|
|
495
494
|
file.close();
|
|
@@ -521,7 +520,7 @@ var Downloader = class {
|
|
|
521
520
|
this.mainSpinner.text = `\u{1F4E5} ${import_chalk.default.bold(binary)} - ${progressText}`;
|
|
522
521
|
}
|
|
523
522
|
static extractBinary(zipPath, outputPath, prefix) {
|
|
524
|
-
return new Promise((
|
|
523
|
+
return new Promise((resolve5, reject) => {
|
|
525
524
|
const outDir = path.dirname(outputPath);
|
|
526
525
|
let extracted = 0;
|
|
527
526
|
const pending = [];
|
|
@@ -556,7 +555,7 @@ var Downloader = class {
|
|
|
556
555
|
if (extracted === 0) {
|
|
557
556
|
reject(new Error(`No se encontr\xF3 archivo v\xE1lido en el ZIP para ${prefix}`));
|
|
558
557
|
} else {
|
|
559
|
-
|
|
558
|
+
resolve5();
|
|
560
559
|
}
|
|
561
560
|
}).catch((err) => {
|
|
562
561
|
this.cleanupFile(zipPath);
|
|
@@ -876,22 +875,22 @@ var DaemonClient = class _DaemonClient {
|
|
|
876
875
|
child.unref();
|
|
877
876
|
}
|
|
878
877
|
tryConnect(port) {
|
|
879
|
-
return new Promise((
|
|
878
|
+
return new Promise((resolve5) => {
|
|
880
879
|
const socket = import_net.default.createConnection({ host: "127.0.0.1", port }, async () => {
|
|
881
880
|
socket.setNoDelay(true);
|
|
882
881
|
this.attach(socket);
|
|
883
882
|
try {
|
|
884
883
|
const pong = await this.send({ action: "ping" }, 2e3);
|
|
885
|
-
|
|
884
|
+
resolve5(pong.status === 200);
|
|
886
885
|
} catch {
|
|
887
886
|
this.detach();
|
|
888
|
-
|
|
887
|
+
resolve5(false);
|
|
889
888
|
}
|
|
890
889
|
});
|
|
891
|
-
socket.once("error", () =>
|
|
890
|
+
socket.once("error", () => resolve5(false));
|
|
892
891
|
socket.setTimeout(3e3, () => {
|
|
893
892
|
socket.destroy();
|
|
894
|
-
|
|
893
|
+
resolve5(false);
|
|
895
894
|
});
|
|
896
895
|
});
|
|
897
896
|
}
|
|
@@ -939,7 +938,7 @@ var DaemonClient = class _DaemonClient {
|
|
|
939
938
|
* single socket, so pending requests resolve in send order.
|
|
940
939
|
*/
|
|
941
940
|
send(payload, timeoutMs) {
|
|
942
|
-
return new Promise((
|
|
941
|
+
return new Promise((resolve5, reject) => {
|
|
943
942
|
if (!this.socket || this.socket.destroyed) {
|
|
944
943
|
reject(new Error("Daemon not connected"));
|
|
945
944
|
return;
|
|
@@ -950,7 +949,7 @@ var DaemonClient = class _DaemonClient {
|
|
|
950
949
|
reject(new Error("Daemon request timeout"));
|
|
951
950
|
this.detach();
|
|
952
951
|
}, timeoutMs ?? this.requestTimeout);
|
|
953
|
-
this.pending.push({ resolve:
|
|
952
|
+
this.pending.push({ resolve: resolve5, reject, timer });
|
|
954
953
|
this.socket.write(JSON.stringify(payload) + "\n");
|
|
955
954
|
});
|
|
956
955
|
}
|
|
@@ -1154,7 +1153,7 @@ var Engine = class {
|
|
|
1154
1153
|
if (!this.binary) {
|
|
1155
1154
|
throw new Error("Binary not initialized");
|
|
1156
1155
|
}
|
|
1157
|
-
return new Promise((
|
|
1156
|
+
return new Promise((resolve5, reject) => {
|
|
1158
1157
|
const child = (0, import_child_process2.spawn)(this.binary[binary], [...this.arguments, ...args]);
|
|
1159
1158
|
let stdoutBuffer = "";
|
|
1160
1159
|
let stderrBuffer = "";
|
|
@@ -1170,7 +1169,7 @@ var Engine = class {
|
|
|
1170
1169
|
if (!isResolved) {
|
|
1171
1170
|
isResolved = true;
|
|
1172
1171
|
clearTimeout(timeoutId);
|
|
1173
|
-
|
|
1172
|
+
resolve5(response);
|
|
1174
1173
|
}
|
|
1175
1174
|
};
|
|
1176
1175
|
const tryParseLines = (buffer) => {
|
|
@@ -1367,10 +1366,10 @@ function loadKoffiBackend() {
|
|
|
1367
1366
|
return { status: 500, message: `Invalid embedded response: ${e.message}`, data: null };
|
|
1368
1367
|
}
|
|
1369
1368
|
};
|
|
1370
|
-
const call = (fn, ...args) => new Promise((
|
|
1369
|
+
const call = (fn, ...args) => new Promise((resolve5, reject) => {
|
|
1371
1370
|
fn.async(...args, (err, ptr) => {
|
|
1372
1371
|
if (err) return reject(err);
|
|
1373
|
-
|
|
1372
|
+
resolve5(take(ptr));
|
|
1374
1373
|
});
|
|
1375
1374
|
});
|
|
1376
1375
|
return {
|
|
@@ -1504,9 +1503,9 @@ var QueryEngine = class {
|
|
|
1504
1503
|
timeout;
|
|
1505
1504
|
connectionId;
|
|
1506
1505
|
tcpPort;
|
|
1507
|
-
constructor(name, timeout = 3e4) {
|
|
1506
|
+
constructor(name, timeout = 3e4, explicitConfig) {
|
|
1508
1507
|
this.name = name;
|
|
1509
|
-
this.config = this.setConfig(name);
|
|
1508
|
+
this.config = explicitConfig ?? this.setConfig(name);
|
|
1510
1509
|
this.arguments = this.setArguments();
|
|
1511
1510
|
this.timeout = this.config?.daemon?.requestTimeoutMs ?? timeout;
|
|
1512
1511
|
this.connectionId = `${name}_query_engine_${this.config.type}_${this.config.config.DATABASE}_${this.config.config.HOST || "localhost"}`;
|
|
@@ -1524,12 +1523,12 @@ var QueryEngine = class {
|
|
|
1524
1523
|
throw new Error("No available ports found in range 9900-9944");
|
|
1525
1524
|
}
|
|
1526
1525
|
isPortAvailable(port) {
|
|
1527
|
-
return new Promise((
|
|
1526
|
+
return new Promise((resolve5) => {
|
|
1528
1527
|
const tester = net2.createServer();
|
|
1529
|
-
tester.once("error", () =>
|
|
1528
|
+
tester.once("error", () => resolve5(false));
|
|
1530
1529
|
tester.once("listening", () => {
|
|
1531
1530
|
tester.close();
|
|
1532
|
-
|
|
1531
|
+
resolve5(true);
|
|
1533
1532
|
});
|
|
1534
1533
|
tester.listen(port, "127.0.0.1");
|
|
1535
1534
|
});
|
|
@@ -1762,7 +1761,7 @@ var QueryEngine = class {
|
|
|
1762
1761
|
throw e;
|
|
1763
1762
|
}
|
|
1764
1763
|
}
|
|
1765
|
-
return new Promise((
|
|
1764
|
+
return new Promise((resolve5) => pool.waiters.push(resolve5));
|
|
1766
1765
|
}
|
|
1767
1766
|
releaseSocket(socket, broken) {
|
|
1768
1767
|
const pool = socketPools.get(this.connectionId);
|
|
@@ -1801,25 +1800,25 @@ var QueryEngine = class {
|
|
|
1801
1800
|
throw new Error("TCP server failed to become ready within timeout");
|
|
1802
1801
|
}
|
|
1803
1802
|
async isServerResponding(port) {
|
|
1804
|
-
return new Promise((
|
|
1803
|
+
return new Promise((resolve5) => {
|
|
1805
1804
|
const client = new net2.Socket();
|
|
1806
1805
|
const timeout = setTimeout(() => {
|
|
1807
1806
|
client.destroy();
|
|
1808
|
-
|
|
1807
|
+
resolve5(false);
|
|
1809
1808
|
}, 1e3);
|
|
1810
1809
|
client.connect(port, "127.0.0.1", () => {
|
|
1811
1810
|
clearTimeout(timeout);
|
|
1812
1811
|
client.destroy();
|
|
1813
|
-
|
|
1812
|
+
resolve5(true);
|
|
1814
1813
|
});
|
|
1815
1814
|
client.on("error", () => {
|
|
1816
1815
|
clearTimeout(timeout);
|
|
1817
|
-
|
|
1816
|
+
resolve5(false);
|
|
1818
1817
|
});
|
|
1819
1818
|
});
|
|
1820
1819
|
}
|
|
1821
1820
|
sleep(ms) {
|
|
1822
|
-
return new Promise((
|
|
1821
|
+
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
1823
1822
|
}
|
|
1824
1823
|
getCachedDML(dmlJson) {
|
|
1825
1824
|
if (queryCache.has(dmlJson)) {
|
|
@@ -1839,7 +1838,7 @@ var QueryEngine = class {
|
|
|
1839
1838
|
throw new Error("Binary not initialized");
|
|
1840
1839
|
}
|
|
1841
1840
|
this.tcpPort = await this.findAvailablePort(this.tcpPort);
|
|
1842
|
-
return new Promise((
|
|
1841
|
+
return new Promise((resolve5, reject) => {
|
|
1843
1842
|
const serverArgs = [...this.arguments, "--action", "server", "--tcp-port", this.tcpPort.toString()];
|
|
1844
1843
|
const serverProcess = (0, import_child_process3.spawn)(this.binary["query_engine"], serverArgs);
|
|
1845
1844
|
let started = false;
|
|
@@ -1859,7 +1858,7 @@ var QueryEngine = class {
|
|
|
1859
1858
|
port: this.tcpPort,
|
|
1860
1859
|
process: serverProcess
|
|
1861
1860
|
});
|
|
1862
|
-
|
|
1861
|
+
resolve5();
|
|
1863
1862
|
}
|
|
1864
1863
|
}
|
|
1865
1864
|
});
|
|
@@ -1878,7 +1877,7 @@ var QueryEngine = class {
|
|
|
1878
1877
|
});
|
|
1879
1878
|
}
|
|
1880
1879
|
async createNewConnection(port) {
|
|
1881
|
-
return new Promise((
|
|
1880
|
+
return new Promise((resolve5, reject) => {
|
|
1882
1881
|
const client = new net2.Socket();
|
|
1883
1882
|
client.setNoDelay(true);
|
|
1884
1883
|
client.setKeepAlive(true, 6e4);
|
|
@@ -1888,7 +1887,7 @@ var QueryEngine = class {
|
|
|
1888
1887
|
}, 5e3);
|
|
1889
1888
|
client.connect(port, "127.0.0.1", () => {
|
|
1890
1889
|
clearTimeout(timeout);
|
|
1891
|
-
|
|
1890
|
+
resolve5(client);
|
|
1892
1891
|
});
|
|
1893
1892
|
client.on("error", (error) => {
|
|
1894
1893
|
clearTimeout(timeout);
|
|
@@ -1897,7 +1896,7 @@ var QueryEngine = class {
|
|
|
1897
1896
|
});
|
|
1898
1897
|
}
|
|
1899
1898
|
async executeOnConnection(connection, command) {
|
|
1900
|
-
return new Promise((
|
|
1899
|
+
return new Promise((resolve5, reject) => {
|
|
1901
1900
|
let responseBuffer = "";
|
|
1902
1901
|
let isResolved = false;
|
|
1903
1902
|
const timeout = setTimeout(() => {
|
|
@@ -1922,7 +1921,7 @@ var QueryEngine = class {
|
|
|
1922
1921
|
connection.removeListener("error", onError);
|
|
1923
1922
|
try {
|
|
1924
1923
|
const response = JSON.parse(line.slice(marker + "PROCESS_RESPONSE:".length));
|
|
1925
|
-
|
|
1924
|
+
resolve5({
|
|
1926
1925
|
status: response.status,
|
|
1927
1926
|
message: response.message,
|
|
1928
1927
|
data: response.data
|
|
@@ -1951,7 +1950,7 @@ var QueryEngine = class {
|
|
|
1951
1950
|
if (!this.binary) {
|
|
1952
1951
|
throw new Error("Binary not initialized");
|
|
1953
1952
|
}
|
|
1954
|
-
return new Promise((
|
|
1953
|
+
return new Promise((resolve5, reject) => {
|
|
1955
1954
|
const child = (0, import_child_process3.spawn)(this.binary[binary], [...this.arguments, ...args]);
|
|
1956
1955
|
let stdoutBuffer = "";
|
|
1957
1956
|
let stderrBuffer = "";
|
|
@@ -1967,7 +1966,7 @@ var QueryEngine = class {
|
|
|
1967
1966
|
if (!isResolved) {
|
|
1968
1967
|
isResolved = true;
|
|
1969
1968
|
clearTimeout(timeoutId);
|
|
1970
|
-
|
|
1969
|
+
resolve5(response);
|
|
1971
1970
|
}
|
|
1972
1971
|
};
|
|
1973
1972
|
const tryParseLines = (buffer) => {
|
|
@@ -2053,347 +2052,70 @@ var QueryEngine = class {
|
|
|
2053
2052
|
}
|
|
2054
2053
|
};
|
|
2055
2054
|
|
|
2056
|
-
// src/lib/SqliteExecutor.ts
|
|
2057
|
-
var import_child_process4 = require("child_process");
|
|
2058
|
-
var path7 = __toESM(require("path"));
|
|
2059
|
-
var fs5 = __toESM(require("fs"));
|
|
2060
|
-
var import_util = require("util");
|
|
2061
|
-
var import_module3 = require("module");
|
|
2062
|
-
var import_url3 = require("url");
|
|
2063
|
-
var import_path6 = require("path");
|
|
2064
|
-
var import_meta3 = {};
|
|
2065
|
-
var execAsync = (0, import_util.promisify)(import_child_process4.exec);
|
|
2066
|
-
var SqliteExecutor = class {
|
|
2067
|
-
binaryPath;
|
|
2068
|
-
dbPath;
|
|
2069
|
-
constructor(dbPath) {
|
|
2070
|
-
this.dbPath = dbPath;
|
|
2071
|
-
this.binaryPath = this.getBinaryPath();
|
|
2072
|
-
}
|
|
2073
|
-
findVersionedBinary(binDir, platform2) {
|
|
2074
|
-
try {
|
|
2075
|
-
const files = fs5.readdirSync(binDir);
|
|
2076
|
-
const extension = platform2 === "win32" ? ".exe" : "";
|
|
2077
|
-
const platformName = platform2 === "win32" ? "windows" : platform2 === "darwin" ? "macos" : "linux";
|
|
2078
|
-
const pattern = new RegExp(`^sqlite-engine-v\\d+\\.\\d+\\.\\d+-${platformName}-x64${extension.replace(".", "\\.")}$`);
|
|
2079
|
-
const matchingFile = files.find((f) => pattern.test(f));
|
|
2080
|
-
if (matchingFile) {
|
|
2081
|
-
return path7.join(binDir, matchingFile);
|
|
2082
|
-
}
|
|
2083
|
-
} catch (error) {
|
|
2084
|
-
}
|
|
2085
|
-
return null;
|
|
2086
|
-
}
|
|
2087
|
-
getBinaryPath() {
|
|
2088
|
-
const __filename2 = typeof import_meta3 !== "undefined" && import_meta3.url ? (0, import_url3.fileURLToPath)(import_meta3.url) : "";
|
|
2089
|
-
const __dirname = __filename2 ? (0, import_path6.dirname)(__filename2) : process.cwd();
|
|
2090
|
-
const possibleDirs = [
|
|
2091
|
-
path7.resolve(process.cwd(), ".dbcube", "bin"),
|
|
2092
|
-
path7.resolve(process.cwd(), "node_modules", ".dbcube", "bin"),
|
|
2093
|
-
path7.resolve(__dirname, "..", "bin")
|
|
2094
|
-
];
|
|
2095
|
-
const platform2 = process.platform;
|
|
2096
|
-
const extension = platform2 === "win32" ? ".exe" : "";
|
|
2097
|
-
const platformName = platform2 === "win32" ? "windows" : platform2 === "darwin" ? "macos" : "linux";
|
|
2098
|
-
for (const dir of possibleDirs) {
|
|
2099
|
-
const versionedPath = this.findVersionedBinary(dir, platform2);
|
|
2100
|
-
if (versionedPath && fs5.existsSync(versionedPath)) {
|
|
2101
|
-
return versionedPath;
|
|
2102
|
-
}
|
|
2103
|
-
}
|
|
2104
|
-
const binaryName = `sqlite-engine-${platformName}-x64${extension}`;
|
|
2105
|
-
for (const dir of possibleDirs) {
|
|
2106
|
-
const fullPath = path7.join(dir, binaryName);
|
|
2107
|
-
if (fs5.existsSync(fullPath)) {
|
|
2108
|
-
return fullPath;
|
|
2109
|
-
}
|
|
2110
|
-
}
|
|
2111
|
-
const fallbackName = `sqlite-engine${extension}`;
|
|
2112
|
-
for (const dir of possibleDirs) {
|
|
2113
|
-
const fullPath = path7.join(dir, fallbackName);
|
|
2114
|
-
if (fs5.existsSync(fullPath)) {
|
|
2115
|
-
return fullPath;
|
|
2116
|
-
}
|
|
2117
|
-
}
|
|
2118
|
-
return path7.join(possibleDirs[0], binaryName);
|
|
2119
|
-
}
|
|
2120
|
-
async executeBinary(args) {
|
|
2121
|
-
const escapedArgs = args.map((arg) => {
|
|
2122
|
-
if (arg.includes(" ") || arg.includes('"') || arg.includes("(") || arg.includes(")")) {
|
|
2123
|
-
return `"${arg.replace(/"/g, '\\"')}"`;
|
|
2124
|
-
}
|
|
2125
|
-
return arg;
|
|
2126
|
-
});
|
|
2127
|
-
const command = `"${this.binaryPath}" ${escapedArgs.join(" ")}`;
|
|
2128
|
-
try {
|
|
2129
|
-
const { stdout, stderr } = await execAsync(command, {
|
|
2130
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
2131
|
-
// 10MB buffer
|
|
2132
|
-
timeout: 3e4
|
|
2133
|
-
// 30s timeout
|
|
2134
|
-
});
|
|
2135
|
-
if (stderr && stderr.trim()) {
|
|
2136
|
-
console.warn("SQLite Engine Warning:", stderr);
|
|
2137
|
-
}
|
|
2138
|
-
const result = JSON.parse(stdout.trim());
|
|
2139
|
-
return result;
|
|
2140
|
-
} catch (error) {
|
|
2141
|
-
if (error.stdout) {
|
|
2142
|
-
try {
|
|
2143
|
-
const result = JSON.parse(error.stdout.trim());
|
|
2144
|
-
return result;
|
|
2145
|
-
} catch (parseError) {
|
|
2146
|
-
}
|
|
2147
|
-
}
|
|
2148
|
-
throw new Error(`SQLite execution failed: ${error.message}`);
|
|
2149
|
-
}
|
|
2150
|
-
}
|
|
2151
|
-
async connect() {
|
|
2152
|
-
try {
|
|
2153
|
-
const result = await this.executeBinary([
|
|
2154
|
-
"--action",
|
|
2155
|
-
"connect",
|
|
2156
|
-
"--database",
|
|
2157
|
-
this.dbPath
|
|
2158
|
-
]);
|
|
2159
|
-
return result.status === "success";
|
|
2160
|
-
} catch (error) {
|
|
2161
|
-
return false;
|
|
2162
|
-
}
|
|
2163
|
-
}
|
|
2164
|
-
async exists() {
|
|
2165
|
-
try {
|
|
2166
|
-
const result = await this.executeBinary([
|
|
2167
|
-
"--action",
|
|
2168
|
-
"exists",
|
|
2169
|
-
"--database",
|
|
2170
|
-
this.dbPath
|
|
2171
|
-
]);
|
|
2172
|
-
return result.status === "success" && result.data === true;
|
|
2173
|
-
} catch (error) {
|
|
2174
|
-
return false;
|
|
2175
|
-
}
|
|
2176
|
-
}
|
|
2177
|
-
async query(sql, params) {
|
|
2178
|
-
const args = [
|
|
2179
|
-
"--action",
|
|
2180
|
-
"query",
|
|
2181
|
-
"--database",
|
|
2182
|
-
this.dbPath,
|
|
2183
|
-
"--query",
|
|
2184
|
-
sql
|
|
2185
|
-
];
|
|
2186
|
-
if (params && params.length > 0) {
|
|
2187
|
-
args.push("--params", JSON.stringify(params));
|
|
2188
|
-
}
|
|
2189
|
-
return this.executeBinary(args);
|
|
2190
|
-
}
|
|
2191
|
-
// Método para múltiples queries (como lo hace better-sqlite3)
|
|
2192
|
-
async queryMultiple(sql) {
|
|
2193
|
-
return this.query(sql);
|
|
2194
|
-
}
|
|
2195
|
-
// Método prepare que simula prepared statements
|
|
2196
|
-
prepare(sql) {
|
|
2197
|
-
return {
|
|
2198
|
-
all: async (...params) => {
|
|
2199
|
-
const result = await this.query(sql, params);
|
|
2200
|
-
if (result.status === "error") {
|
|
2201
|
-
throw new Error(result.message);
|
|
2202
|
-
}
|
|
2203
|
-
return Array.isArray(result.data) ? result.data : [];
|
|
2204
|
-
},
|
|
2205
|
-
run: async (...params) => {
|
|
2206
|
-
const result = await this.query(sql, params);
|
|
2207
|
-
if (result.status === "error") {
|
|
2208
|
-
throw new Error(result.message);
|
|
2209
|
-
}
|
|
2210
|
-
if (typeof result.data === "object" && result.data.hasOwnProperty("changes") && result.data.hasOwnProperty("lastID")) {
|
|
2211
|
-
return result.data;
|
|
2212
|
-
}
|
|
2213
|
-
return { changes: 0, lastID: 0 };
|
|
2214
|
-
}
|
|
2215
|
-
};
|
|
2216
|
-
}
|
|
2217
|
-
// Para compatibilidad con better-sqlite3 API sincrona usando deasync si es necesario
|
|
2218
|
-
prepareSync(sql) {
|
|
2219
|
-
const __filename2 = typeof import_meta3 !== "undefined" && import_meta3.url ? (0, import_url3.fileURLToPath)(import_meta3.url) : "";
|
|
2220
|
-
const requireUrl = __filename2 || import_meta3.url;
|
|
2221
|
-
const require2 = (0, import_module3.createRequire)(requireUrl);
|
|
2222
|
-
const deasync = require2("deasync");
|
|
2223
|
-
return {
|
|
2224
|
-
all: (...params) => {
|
|
2225
|
-
let result;
|
|
2226
|
-
let done = false;
|
|
2227
|
-
let error;
|
|
2228
|
-
this.query(sql, params).then((res) => {
|
|
2229
|
-
if (res.status === "error") {
|
|
2230
|
-
error = new Error(res.message);
|
|
2231
|
-
} else {
|
|
2232
|
-
result = Array.isArray(res.data) ? res.data : [];
|
|
2233
|
-
}
|
|
2234
|
-
done = true;
|
|
2235
|
-
}).catch((err) => {
|
|
2236
|
-
error = err;
|
|
2237
|
-
done = true;
|
|
2238
|
-
});
|
|
2239
|
-
deasync.loopWhile(() => !done);
|
|
2240
|
-
if (error) throw error;
|
|
2241
|
-
return result;
|
|
2242
|
-
},
|
|
2243
|
-
run: (...params) => {
|
|
2244
|
-
let result;
|
|
2245
|
-
let done = false;
|
|
2246
|
-
let error;
|
|
2247
|
-
this.query(sql, params).then((res) => {
|
|
2248
|
-
if (res.status === "error") {
|
|
2249
|
-
error = new Error(res.message);
|
|
2250
|
-
} else if (typeof res.data === "object" && res.data.hasOwnProperty("changes") && res.data.hasOwnProperty("lastID")) {
|
|
2251
|
-
result = res.data;
|
|
2252
|
-
} else {
|
|
2253
|
-
result = { changes: 0, lastID: 0 };
|
|
2254
|
-
}
|
|
2255
|
-
done = true;
|
|
2256
|
-
}).catch((err) => {
|
|
2257
|
-
error = err;
|
|
2258
|
-
done = true;
|
|
2259
|
-
});
|
|
2260
|
-
deasync.loopWhile(() => !done);
|
|
2261
|
-
if (error) throw error;
|
|
2262
|
-
return result;
|
|
2263
|
-
}
|
|
2264
|
-
};
|
|
2265
|
-
}
|
|
2266
|
-
};
|
|
2267
|
-
|
|
2268
2055
|
// src/lib/DbConfig.ts
|
|
2269
|
-
var
|
|
2056
|
+
var path7 = __toESM(require("path"));
|
|
2270
2057
|
var import_fs2 = __toESM(require("fs"));
|
|
2271
|
-
var rootPath =
|
|
2058
|
+
var rootPath = path7.resolve(process.cwd(), ".dbcube");
|
|
2272
2059
|
var SQLite = class {
|
|
2273
|
-
executor = null;
|
|
2274
2060
|
database;
|
|
2061
|
+
engine = null;
|
|
2275
2062
|
constructor(config) {
|
|
2276
|
-
this.database = config.DATABASE;
|
|
2063
|
+
this.database = config.DATABASE || "config";
|
|
2064
|
+
}
|
|
2065
|
+
/** Ruta del archivo SQLite interno (.dbcube/<database>.db). */
|
|
2066
|
+
dbFilePath() {
|
|
2067
|
+
return path7.join(rootPath, this.database + ".db");
|
|
2068
|
+
}
|
|
2069
|
+
/** QueryEngine sqlite apuntando al archivo interno, con config explícito
|
|
2070
|
+
* (no vive en dbcube.config.js). La ruta relativa `.dbcube/<db>` deja que
|
|
2071
|
+
* QueryEngine le añada `.db` → `.dbcube/<db>.db`, relativo al CWD. */
|
|
2072
|
+
getEngine() {
|
|
2073
|
+
if (!this.engine) {
|
|
2074
|
+
const relativeDb = path7.join(".dbcube", this.database).replace(/\\/g, "/");
|
|
2075
|
+
this.engine = new QueryEngine(`dbcube-internal-${this.database}`, 3e4, {
|
|
2076
|
+
type: "sqlite",
|
|
2077
|
+
config: { DATABASE: relativeDb }
|
|
2078
|
+
});
|
|
2079
|
+
}
|
|
2080
|
+
return this.engine;
|
|
2277
2081
|
}
|
|
2278
2082
|
async ifExist() {
|
|
2279
|
-
if (
|
|
2280
|
-
|
|
2281
|
-
const configPath = path8.join(rootPath, dbPath + ".db");
|
|
2282
|
-
if (!import_fs2.default.existsSync(rootPath)) {
|
|
2283
|
-
import_fs2.default.mkdirSync(rootPath, { recursive: true });
|
|
2284
|
-
}
|
|
2285
|
-
if (import_fs2.default.existsSync(configPath)) {
|
|
2286
|
-
return true;
|
|
2287
|
-
}
|
|
2288
|
-
if (!this.executor) {
|
|
2289
|
-
this.executor = new SqliteExecutor(configPath);
|
|
2290
|
-
}
|
|
2291
|
-
return await this.executor.exists();
|
|
2083
|
+
if (!import_fs2.default.existsSync(rootPath)) {
|
|
2084
|
+
import_fs2.default.mkdirSync(rootPath, { recursive: true });
|
|
2292
2085
|
}
|
|
2293
|
-
return
|
|
2086
|
+
return import_fs2.default.existsSync(this.dbFilePath());
|
|
2294
2087
|
}
|
|
2295
2088
|
async connect() {
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
const configPath = path8.join(rootPath, dbPath + ".db");
|
|
2301
|
-
if (!import_fs2.default.existsSync(rootPath)) {
|
|
2302
|
-
import_fs2.default.mkdirSync(rootPath, { recursive: true });
|
|
2303
|
-
}
|
|
2304
|
-
this.executor = new SqliteExecutor(configPath);
|
|
2305
|
-
const connected = await this.executor.connect();
|
|
2306
|
-
if (!connected) {
|
|
2307
|
-
throw new Error("Failed to connect to SQLite database");
|
|
2308
|
-
}
|
|
2309
|
-
}
|
|
2310
|
-
resolve6(this.executor);
|
|
2311
|
-
} catch (error) {
|
|
2312
|
-
reject(error);
|
|
2313
|
-
}
|
|
2314
|
-
});
|
|
2089
|
+
if (!import_fs2.default.existsSync(rootPath)) {
|
|
2090
|
+
import_fs2.default.mkdirSync(rootPath, { recursive: true });
|
|
2091
|
+
}
|
|
2092
|
+
return this.getEngine();
|
|
2315
2093
|
}
|
|
2316
2094
|
async disconnect() {
|
|
2317
|
-
return new Promise((resolve6) => {
|
|
2318
|
-
if (this.executor) {
|
|
2319
|
-
this.executor = null;
|
|
2320
|
-
}
|
|
2321
|
-
resolve6();
|
|
2322
|
-
});
|
|
2323
2095
|
}
|
|
2324
2096
|
async query(sqlQuery) {
|
|
2325
|
-
return
|
|
2326
|
-
try {
|
|
2327
|
-
if (typeof sqlQuery !== "string") {
|
|
2328
|
-
throw new Error("The SQL query must be a string.");
|
|
2329
|
-
}
|
|
2330
|
-
if (!this.executor) {
|
|
2331
|
-
await this.connect();
|
|
2332
|
-
}
|
|
2333
|
-
if (!this.executor) {
|
|
2334
|
-
throw new Error("Database connection is not available.");
|
|
2335
|
-
}
|
|
2336
|
-
const result = await this.executor.queryMultiple(sqlQuery);
|
|
2337
|
-
if (result.status === "error") {
|
|
2338
|
-
resolve6({
|
|
2339
|
-
status: "error",
|
|
2340
|
-
message: result.message,
|
|
2341
|
-
data: null
|
|
2342
|
-
});
|
|
2343
|
-
} else {
|
|
2344
|
-
resolve6({
|
|
2345
|
-
status: "success",
|
|
2346
|
-
message: "Query executed successfully",
|
|
2347
|
-
data: result.data
|
|
2348
|
-
});
|
|
2349
|
-
}
|
|
2350
|
-
} catch (error) {
|
|
2351
|
-
resolve6({
|
|
2352
|
-
status: "error",
|
|
2353
|
-
message: error.message || "An error occurred while executing the query.",
|
|
2354
|
-
data: null
|
|
2355
|
-
});
|
|
2356
|
-
}
|
|
2357
|
-
});
|
|
2097
|
+
return this.queryWithParameters(sqlQuery, []);
|
|
2358
2098
|
}
|
|
2359
2099
|
async queryWithParameters(sqlQuery, params = []) {
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
throw new Error("The SQL query must be a string.");
|
|
2364
|
-
}
|
|
2365
|
-
if (!Array.isArray(params)) {
|
|
2366
|
-
throw new Error("Parameters must be an array.");
|
|
2367
|
-
}
|
|
2368
|
-
if (!this.executor) {
|
|
2369
|
-
await this.connect();
|
|
2370
|
-
}
|
|
2371
|
-
if (!this.executor) {
|
|
2372
|
-
throw new Error("Database connection is not available.");
|
|
2373
|
-
}
|
|
2374
|
-
const result = await this.executor.query(sqlQuery, params);
|
|
2375
|
-
if (result.status === "error") {
|
|
2376
|
-
resolve6({
|
|
2377
|
-
status: "error",
|
|
2378
|
-
message: result.message,
|
|
2379
|
-
data: null
|
|
2380
|
-
});
|
|
2381
|
-
} else {
|
|
2382
|
-
resolve6({
|
|
2383
|
-
status: "success",
|
|
2384
|
-
message: "Query executed successfully",
|
|
2385
|
-
data: result.data
|
|
2386
|
-
});
|
|
2387
|
-
}
|
|
2388
|
-
} catch (error) {
|
|
2389
|
-
console.log(error);
|
|
2390
|
-
resolve6({
|
|
2391
|
-
status: "error",
|
|
2392
|
-
message: error.message || "An error occurred while executing the query.",
|
|
2393
|
-
data: null
|
|
2394
|
-
});
|
|
2100
|
+
try {
|
|
2101
|
+
if (typeof sqlQuery !== "string") {
|
|
2102
|
+
throw new Error("The SQL query must be a string.");
|
|
2395
2103
|
}
|
|
2396
|
-
|
|
2104
|
+
if (!Array.isArray(params)) {
|
|
2105
|
+
throw new Error("Parameters must be an array.");
|
|
2106
|
+
}
|
|
2107
|
+
const response = await this.getEngine().rawQuery(sqlQuery, params);
|
|
2108
|
+
if (response.status !== 200) {
|
|
2109
|
+
return { status: "error", message: response.message || "Query failed", data: null };
|
|
2110
|
+
}
|
|
2111
|
+
return { status: "success", message: "Query executed successfully", data: response.data };
|
|
2112
|
+
} catch (error) {
|
|
2113
|
+
return {
|
|
2114
|
+
status: "error",
|
|
2115
|
+
message: error.message || "An error occurred while executing the query.",
|
|
2116
|
+
data: null
|
|
2117
|
+
};
|
|
2118
|
+
}
|
|
2397
2119
|
}
|
|
2398
2120
|
convertToParameterizedQuery(sql) {
|
|
2399
2121
|
const normalizedSql = sql.replace(/\s+/g, " ").trim();
|
|
@@ -2481,8 +2203,8 @@ var DbConfig = new SQLite({ DATABASE: "config" });
|
|
|
2481
2203
|
var DbConfig_default = DbConfig;
|
|
2482
2204
|
|
|
2483
2205
|
// src/lib/FileLogger.ts
|
|
2484
|
-
var
|
|
2485
|
-
var
|
|
2206
|
+
var fs6 = __toESM(require("fs"));
|
|
2207
|
+
var path8 = __toESM(require("path"));
|
|
2486
2208
|
var import_events = require("events");
|
|
2487
2209
|
var FileLogger = class _FileLogger extends import_events.EventEmitter {
|
|
2488
2210
|
static watchers = /* @__PURE__ */ new Map();
|
|
@@ -2497,9 +2219,9 @@ var FileLogger = class _FileLogger extends import_events.EventEmitter {
|
|
|
2497
2219
|
*/
|
|
2498
2220
|
static async write(filePath, message, level = "INFO", append = true) {
|
|
2499
2221
|
try {
|
|
2500
|
-
const dir =
|
|
2501
|
-
if (!
|
|
2502
|
-
|
|
2222
|
+
const dir = path8.dirname(filePath);
|
|
2223
|
+
if (!fs6.existsSync(dir)) {
|
|
2224
|
+
fs6.mkdirSync(dir, { recursive: true });
|
|
2503
2225
|
}
|
|
2504
2226
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
2505
2227
|
const formattedMessage = `[${timestamp}] [${level}] ${message}
|
|
@@ -2509,9 +2231,9 @@ var FileLogger = class _FileLogger extends import_events.EventEmitter {
|
|
|
2509
2231
|
return true;
|
|
2510
2232
|
}
|
|
2511
2233
|
if (append) {
|
|
2512
|
-
await
|
|
2234
|
+
await fs6.promises.appendFile(filePath, formattedMessage, "utf8");
|
|
2513
2235
|
} else {
|
|
2514
|
-
await
|
|
2236
|
+
await fs6.promises.writeFile(filePath, formattedMessage, "utf8");
|
|
2515
2237
|
}
|
|
2516
2238
|
return true;
|
|
2517
2239
|
} catch (error) {
|
|
@@ -2536,12 +2258,12 @@ var FileLogger = class _FileLogger extends import_events.EventEmitter {
|
|
|
2536
2258
|
const buffer = _FileLogger.buffers.get(filePath);
|
|
2537
2259
|
if (buffer && buffer.length > 0) {
|
|
2538
2260
|
try {
|
|
2539
|
-
const dir =
|
|
2540
|
-
if (!
|
|
2541
|
-
|
|
2261
|
+
const dir = path8.dirname(filePath);
|
|
2262
|
+
if (!fs6.existsSync(dir)) {
|
|
2263
|
+
fs6.mkdirSync(dir, { recursive: true });
|
|
2542
2264
|
}
|
|
2543
2265
|
const content = buffer.join("");
|
|
2544
|
-
await
|
|
2266
|
+
await fs6.promises.appendFile(filePath, content, "utf8");
|
|
2545
2267
|
_FileLogger.buffers.delete(filePath);
|
|
2546
2268
|
return true;
|
|
2547
2269
|
} catch (error) {
|
|
@@ -2677,10 +2399,10 @@ var FileLogger = class _FileLogger extends import_events.EventEmitter {
|
|
|
2677
2399
|
// Si debe retornar como array de líneas
|
|
2678
2400
|
} = options;
|
|
2679
2401
|
try {
|
|
2680
|
-
if (!
|
|
2402
|
+
if (!fs6.existsSync(filePath)) {
|
|
2681
2403
|
return asArray ? [] : "";
|
|
2682
2404
|
}
|
|
2683
|
-
let content = await
|
|
2405
|
+
let content = await fs6.promises.readFile(filePath, "utf8");
|
|
2684
2406
|
if (asArray) {
|
|
2685
2407
|
let linesArray = content.split("\n").filter((line) => line.trim() !== "");
|
|
2686
2408
|
if (lines !== null) {
|
|
@@ -2723,15 +2445,15 @@ var FileLogger = class _FileLogger extends import_events.EventEmitter {
|
|
|
2723
2445
|
} = options;
|
|
2724
2446
|
let lastSize = 0;
|
|
2725
2447
|
let lastPosition = 0;
|
|
2726
|
-
if (
|
|
2727
|
-
const stats =
|
|
2448
|
+
if (fs6.existsSync(filePath)) {
|
|
2449
|
+
const stats = fs6.statSync(filePath);
|
|
2728
2450
|
lastSize = stats.size;
|
|
2729
2451
|
lastPosition = fromEnd ? stats.size : 0;
|
|
2730
2452
|
}
|
|
2731
2453
|
const listener = async (curr, prev) => {
|
|
2732
2454
|
try {
|
|
2733
2455
|
if (curr.size > lastSize) {
|
|
2734
|
-
const stream =
|
|
2456
|
+
const stream = fs6.createReadStream(filePath, {
|
|
2735
2457
|
start: lastPosition,
|
|
2736
2458
|
end: curr.size - 1,
|
|
2737
2459
|
encoding: "utf8"
|
|
@@ -2759,7 +2481,7 @@ var FileLogger = class _FileLogger extends import_events.EventEmitter {
|
|
|
2759
2481
|
console.error("Error en watcher:", error);
|
|
2760
2482
|
}
|
|
2761
2483
|
};
|
|
2762
|
-
|
|
2484
|
+
fs6.watchFile(filePath, { persistent, interval }, listener);
|
|
2763
2485
|
const watcherId = `${filePath}_${Date.now()}`;
|
|
2764
2486
|
_FileLogger.watchers.set(watcherId, listener);
|
|
2765
2487
|
return {
|
|
@@ -2767,7 +2489,7 @@ var FileLogger = class _FileLogger extends import_events.EventEmitter {
|
|
|
2767
2489
|
stop: () => {
|
|
2768
2490
|
const storedListener = _FileLogger.watchers.get(watcherId);
|
|
2769
2491
|
if (storedListener) {
|
|
2770
|
-
|
|
2492
|
+
fs6.unwatchFile(filePath, storedListener);
|
|
2771
2493
|
_FileLogger.watchers.delete(watcherId);
|
|
2772
2494
|
}
|
|
2773
2495
|
},
|
|
@@ -2780,7 +2502,7 @@ var FileLogger = class _FileLogger extends import_events.EventEmitter {
|
|
|
2780
2502
|
static stopAllWatchers() {
|
|
2781
2503
|
for (const [watcherId] of _FileLogger.watchers) {
|
|
2782
2504
|
const filePath = watcherId.split("_")[0];
|
|
2783
|
-
|
|
2505
|
+
fs6.unwatchFile(filePath);
|
|
2784
2506
|
}
|
|
2785
2507
|
_FileLogger.watchers.clear();
|
|
2786
2508
|
}
|
|
@@ -2810,7 +2532,7 @@ var FileLogger = class _FileLogger extends import_events.EventEmitter {
|
|
|
2810
2532
|
if (lines.length > maxLines) {
|
|
2811
2533
|
const keepLines = lines.slice(-maxLines);
|
|
2812
2534
|
const content = keepLines.join("\n") + "\n";
|
|
2813
|
-
await
|
|
2535
|
+
await fs6.promises.writeFile(filePath, content, "utf8");
|
|
2814
2536
|
return lines.length - maxLines;
|
|
2815
2537
|
}
|
|
2816
2538
|
return 0;
|
|
@@ -2825,8 +2547,8 @@ var FileLogger = class _FileLogger extends import_events.EventEmitter {
|
|
|
2825
2547
|
*/
|
|
2826
2548
|
static async deleteLogFile(filePath) {
|
|
2827
2549
|
try {
|
|
2828
|
-
if (
|
|
2829
|
-
await
|
|
2550
|
+
if (fs6.existsSync(filePath)) {
|
|
2551
|
+
await fs6.promises.unlink(filePath);
|
|
2830
2552
|
return true;
|
|
2831
2553
|
}
|
|
2832
2554
|
return false;
|