@dbcube/core 3.0.3 → 3.0.5

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.d.mts CHANGED
@@ -7,24 +7,41 @@ interface ResponseEngine {
7
7
  }
8
8
 
9
9
  declare class Engine {
10
+ private name;
11
+ private config;
12
+ private arguments;
13
+ private binary;
14
+ private timeout;
15
+ constructor(name: string, timeout?: number);
16
+ initializeBinary(): Promise<void>;
17
+ setArguments(): any[];
18
+ setConfig(name: string): {
19
+ [x: string]: any;
20
+ } | null;
21
+ getConfig(): any;
22
+ run(binary: string, args: []): Promise<ResponseEngine>;
23
+ }
24
+
25
+ declare class QueryEngine {
10
26
  private name;
11
27
  private config;
12
28
  private arguments;
13
29
  private binary;
14
30
  private timeout;
15
31
  private connectionId;
16
- private isConnected;
32
+ private tcpPort;
17
33
  constructor(name: string, timeout?: number);
18
- private generateConnectionId;
34
+ private generatePort;
19
35
  initializeBinary(): Promise<void>;
20
36
  setArguments(): any[];
21
37
  setConfig(name: string): {
22
38
  [x: string]: any;
23
39
  } | null;
24
40
  getConfig(): any;
25
- ensurePersistentConnection(): Promise<void>;
26
41
  run(binary: string, args: string[]): Promise<ResponseEngine>;
27
- private executeWithPersistentConnection;
42
+ private executeWithTcpServer;
43
+ private startTcpServer;
44
+ private sendTcpRequest;
28
45
  private createProcess;
29
46
  disconnect(): Promise<ResponseEngine>;
30
47
  }
@@ -352,4 +369,4 @@ declare class TriggerProcessor {
352
369
  static getTriggers(name: string): Promise<any[]>;
353
370
  }
354
371
 
355
- export { Arquitecture, Binary, ComputedFieldProcessor, Config, DbConfig, Engine, FileLogger, type InterceptController, TableProcessor, TriggerProcessor };
372
+ export { Arquitecture, Binary, ComputedFieldProcessor, Config, DbConfig, Engine, FileLogger, type InterceptController, QueryEngine, TableProcessor, TriggerProcessor };
package/dist/index.d.ts CHANGED
@@ -7,24 +7,41 @@ interface ResponseEngine {
7
7
  }
8
8
 
9
9
  declare class Engine {
10
+ private name;
11
+ private config;
12
+ private arguments;
13
+ private binary;
14
+ private timeout;
15
+ constructor(name: string, timeout?: number);
16
+ initializeBinary(): Promise<void>;
17
+ setArguments(): any[];
18
+ setConfig(name: string): {
19
+ [x: string]: any;
20
+ } | null;
21
+ getConfig(): any;
22
+ run(binary: string, args: []): Promise<ResponseEngine>;
23
+ }
24
+
25
+ declare class QueryEngine {
10
26
  private name;
11
27
  private config;
12
28
  private arguments;
13
29
  private binary;
14
30
  private timeout;
15
31
  private connectionId;
16
- private isConnected;
32
+ private tcpPort;
17
33
  constructor(name: string, timeout?: number);
18
- private generateConnectionId;
34
+ private generatePort;
19
35
  initializeBinary(): Promise<void>;
20
36
  setArguments(): any[];
21
37
  setConfig(name: string): {
22
38
  [x: string]: any;
23
39
  } | null;
24
40
  getConfig(): any;
25
- ensurePersistentConnection(): Promise<void>;
26
41
  run(binary: string, args: string[]): Promise<ResponseEngine>;
27
- private executeWithPersistentConnection;
42
+ private executeWithTcpServer;
43
+ private startTcpServer;
44
+ private sendTcpRequest;
28
45
  private createProcess;
29
46
  disconnect(): Promise<ResponseEngine>;
30
47
  }
@@ -352,4 +369,4 @@ declare class TriggerProcessor {
352
369
  static getTriggers(name: string): Promise<any[]>;
353
370
  }
354
371
 
355
- export { Arquitecture, Binary, ComputedFieldProcessor, Config, DbConfig, Engine, FileLogger, type InterceptController, TableProcessor, TriggerProcessor };
372
+ export { Arquitecture, Binary, ComputedFieldProcessor, Config, DbConfig, Engine, FileLogger, type InterceptController, QueryEngine, TableProcessor, TriggerProcessor };
package/dist/index.js CHANGED
@@ -556,17 +556,11 @@ var Engine = class {
556
556
  arguments;
557
557
  binary = null;
558
558
  timeout;
559
- connectionId;
560
- isConnected = false;
561
559
  constructor(name, timeout = 3e4) {
562
560
  this.name = name;
563
561
  this.config = this.setConfig(name);
564
562
  this.arguments = this.setArguments();
565
563
  this.timeout = timeout;
566
- this.connectionId = this.generateConnectionId();
567
- }
568
- generateConnectionId() {
569
- return `${this.name}_${this.config.type}_${this.config.config.DATABASE}_${this.config.config.HOST || "localhost"}`;
570
564
  }
571
565
  async initializeBinary() {
572
566
  if (!this.binary) {
@@ -633,33 +627,297 @@ var Engine = class {
633
627
  getConfig() {
634
628
  return this.config;
635
629
  }
636
- async ensurePersistentConnection() {
637
- if (!this.isConnected) {
638
- console.log("\u{1F50C} Creating persistent connection...");
639
- const response = await this.createProcess("query_engine", [
640
- "--action",
641
- "connect"
642
- ]);
643
- if (response.status === 200) {
644
- this.isConnected = true;
645
- console.log("\u2705 Persistent connection established");
630
+ async run(binary, args) {
631
+ await this.initializeBinary();
632
+ if (!this.binary) {
633
+ throw new Error("Binary not initialized");
634
+ }
635
+ return new Promise((resolve5, reject) => {
636
+ const child = spawn(this.binary[binary], [...this.arguments, ...args]);
637
+ let stdoutBuffer = "";
638
+ let stderrBuffer = "";
639
+ let isResolved = false;
640
+ const timeoutId = setTimeout(() => {
641
+ if (!isResolved) {
642
+ isResolved = true;
643
+ child.kill();
644
+ reject(new Error("Process timeout"));
645
+ }
646
+ }, this.timeout);
647
+ const resolveOnce = (response) => {
648
+ if (!isResolved) {
649
+ isResolved = true;
650
+ clearTimeout(timeoutId);
651
+ resolve5(response);
652
+ }
653
+ };
654
+ child.stdout.on("data", (data) => {
655
+ stdoutBuffer += data.toString();
656
+ const match = stdoutBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
657
+ if (match) {
658
+ try {
659
+ const response = JSON.parse(match[1]);
660
+ resolveOnce({
661
+ status: response.status,
662
+ message: response.message,
663
+ data: response.data
664
+ });
665
+ } catch (error) {
666
+ resolveOnce({
667
+ status: 500,
668
+ message: "Failed to parse response JSON",
669
+ data: null
670
+ });
671
+ }
672
+ }
673
+ });
674
+ child.stderr.on("data", (data) => {
675
+ stderrBuffer += data.toString();
676
+ const match = stderrBuffer.match(/PROCESS_RESPONSE:(\{.*\})/);
677
+ if (match) {
678
+ try {
679
+ const response = JSON.parse(match[1]);
680
+ resolveOnce({
681
+ status: response.status,
682
+ message: response.message,
683
+ data: response.data
684
+ });
685
+ } catch (error) {
686
+ resolveOnce({
687
+ status: 500,
688
+ message: "Failed to parse response JSON",
689
+ data: null
690
+ });
691
+ }
692
+ }
693
+ });
694
+ child.on("close", (code) => {
695
+ clearTimeout(timeoutId);
696
+ if (!isResolved) {
697
+ resolveOnce({
698
+ status: code === 0 ? 200 : 500,
699
+ message: code === 0 ? "Process completed" : `Process exited with code ${code}`,
700
+ data: null
701
+ });
702
+ }
703
+ });
704
+ child.on("error", (error) => {
705
+ clearTimeout(timeoutId);
706
+ if (!isResolved) {
707
+ resolveOnce({
708
+ status: 500,
709
+ message: `Process error: ${error.message}`,
710
+ data: null
711
+ });
712
+ }
713
+ });
714
+ child.unref();
715
+ });
716
+ }
717
+ };
718
+
719
+ // src/lib/QueryEngine.ts
720
+ import path4 from "path";
721
+ import { createRequire as createRequire2 } from "module";
722
+ import * as net from "net";
723
+ import { spawn as spawn2 } from "child_process";
724
+ var globalTcpServers = /* @__PURE__ */ new Map();
725
+ var QueryEngine = class {
726
+ name;
727
+ config;
728
+ arguments;
729
+ binary = null;
730
+ timeout;
731
+ connectionId;
732
+ tcpPort;
733
+ constructor(name, timeout = 3e4) {
734
+ this.name = name;
735
+ this.config = this.setConfig(name);
736
+ this.arguments = this.setArguments();
737
+ this.timeout = timeout;
738
+ this.connectionId = `${name}_${this.config.type}_${this.config.config.DATABASE}_${this.config.config.HOST || "localhost"}`;
739
+ this.tcpPort = this.generatePort();
740
+ }
741
+ generatePort() {
742
+ let hash = 0;
743
+ for (let i = 0; i < this.connectionId.length; i++) {
744
+ const char = this.connectionId.charCodeAt(i);
745
+ hash = (hash << 5) - hash + char;
746
+ hash = hash & hash;
747
+ }
748
+ return 8100 + Math.abs(hash % 900);
749
+ }
750
+ async initializeBinary() {
751
+ if (!this.binary) {
752
+ this.binary = await Binary.get();
753
+ }
754
+ }
755
+ setArguments() {
756
+ let args = [];
757
+ if (this.config.type == "sqlite") {
758
+ args = [
759
+ "--id",
760
+ "dbcube-" + this.name,
761
+ "--database-ref",
762
+ this.name,
763
+ "--database",
764
+ this.config.config.DATABASE + ".db",
765
+ "--motor",
766
+ this.config.type
767
+ ];
768
+ } else {
769
+ args = [
770
+ "--id",
771
+ "dbcube-" + this.name,
772
+ "--database-ref",
773
+ this.name,
774
+ "--database",
775
+ this.config.config.DATABASE,
776
+ "--host",
777
+ this.config.config.HOST,
778
+ "--port",
779
+ this.config.config.PORT,
780
+ "--user",
781
+ this.config.config.USER,
782
+ "--password",
783
+ this.config.config.PASSWORD,
784
+ "--motor",
785
+ this.config.type
786
+ ];
787
+ }
788
+ return args;
789
+ }
790
+ setConfig(name) {
791
+ const configInstance = new Config();
792
+ try {
793
+ const configFilePath = path4.resolve(process.cwd(), "dbcube.config.js");
794
+ const requireUrl = typeof __filename !== "undefined" ? __filename : process.cwd();
795
+ const require2 = createRequire2(requireUrl);
796
+ delete require2.cache[require2.resolve(configFilePath)];
797
+ const configModule = require2(configFilePath);
798
+ const configFn = configModule.default || configModule;
799
+ if (typeof configFn === "function") {
800
+ configFn(configInstance);
646
801
  } else {
647
- throw new Error(`Failed to create persistent connection: ${response.message}`);
802
+ console.error("\u274C El archivo dbcube.config.js no exporta una funci\xF3n.");
803
+ }
804
+ } catch (error) {
805
+ console.error("\u274C Error loading config file:", error.message);
806
+ if (error.code === "MODULE_NOT_FOUND") {
807
+ console.error("\u274C Config file not found, please create a dbcube.config.js file");
648
808
  }
649
809
  }
810
+ return configInstance.getDatabase(name);
811
+ }
812
+ getConfig() {
813
+ return this.config;
650
814
  }
651
815
  async run(binary, args) {
652
- const actionIndex = args.indexOf("--action");
816
+ const actionIndex = args.findIndex((arg) => arg === "--action");
653
817
  const isExecuteAction = actionIndex !== -1 && args[actionIndex + 1] === "execute";
654
818
  if (isExecuteAction) {
655
- await this.ensurePersistentConnection();
656
- return this.executeWithPersistentConnection(args);
819
+ return this.executeWithTcpServer(args);
657
820
  } else {
658
821
  return this.createProcess(binary, args);
659
822
  }
660
823
  }
661
- async executeWithPersistentConnection(args) {
662
- return this.createProcess("query_engine", args);
824
+ async executeWithTcpServer(args) {
825
+ const serverInfo = globalTcpServers.get(this.connectionId);
826
+ if (!serverInfo || !serverInfo.process || serverInfo.process.killed) {
827
+ console.log("\u{1F680} Starting TCP server for ultra-fast queries...");
828
+ await this.startTcpServer();
829
+ }
830
+ console.log("\u26A1 Using TCP server (ultra-fast)");
831
+ return this.sendTcpRequest(args);
832
+ }
833
+ async startTcpServer() {
834
+ await this.initializeBinary();
835
+ if (!this.binary) {
836
+ throw new Error("Binary not initialized");
837
+ }
838
+ return new Promise((resolve5, reject) => {
839
+ const serverArgs = [...this.arguments, "--action", "server", "--port", this.tcpPort.toString()];
840
+ const serverProcess = spawn2(this.binary["query_engine"], serverArgs);
841
+ let started = false;
842
+ const timeout = setTimeout(() => {
843
+ if (!started) {
844
+ serverProcess.kill();
845
+ reject(new Error("TCP server startup timeout"));
846
+ }
847
+ }, 1e4);
848
+ serverProcess.stdout.on("data", (data) => {
849
+ const output = data.toString();
850
+ console.log(`[TCP Server] ${output.trim()}`);
851
+ if (output.includes("TCP Server listening on")) {
852
+ if (!started) {
853
+ started = true;
854
+ clearTimeout(timeout);
855
+ globalTcpServers.set(this.connectionId, {
856
+ port: this.tcpPort,
857
+ process: serverProcess
858
+ });
859
+ resolve5();
860
+ }
861
+ }
862
+ });
863
+ serverProcess.stderr.on("data", (data) => {
864
+ console.error(`[TCP Server Error] ${data.toString().trim()}`);
865
+ });
866
+ serverProcess.on("close", (code) => {
867
+ console.log(`[TCP Server] Process exited with code ${code}`);
868
+ globalTcpServers.delete(this.connectionId);
869
+ });
870
+ serverProcess.on("error", (error) => {
871
+ if (!started) {
872
+ clearTimeout(timeout);
873
+ reject(error);
874
+ }
875
+ });
876
+ });
877
+ }
878
+ async sendTcpRequest(args) {
879
+ return new Promise((resolve5, reject) => {
880
+ const client = new net.Socket();
881
+ let responseBuffer = "";
882
+ const timeout = setTimeout(() => {
883
+ client.destroy();
884
+ reject(new Error("TCP request timeout"));
885
+ }, this.timeout);
886
+ client.connect(this.tcpPort, "127.0.0.1", () => {
887
+ const command = {
888
+ action: "execute",
889
+ args
890
+ };
891
+ client.write(JSON.stringify(command) + "\n");
892
+ });
893
+ client.on("data", (data) => {
894
+ responseBuffer += data.toString();
895
+ if (responseBuffer.includes("\n")) {
896
+ clearTimeout(timeout);
897
+ client.destroy();
898
+ try {
899
+ const response = JSON.parse(responseBuffer.trim());
900
+ resolve5({
901
+ status: response.status || 200,
902
+ message: response.message || "Success",
903
+ data: response.data
904
+ });
905
+ } catch (error) {
906
+ reject(new Error("Failed to parse TCP response"));
907
+ }
908
+ }
909
+ });
910
+ client.on("error", (error) => {
911
+ clearTimeout(timeout);
912
+ reject(error);
913
+ });
914
+ client.on("close", () => {
915
+ clearTimeout(timeout);
916
+ if (responseBuffer && !responseBuffer.includes("\n")) {
917
+ reject(new Error("Incomplete TCP response"));
918
+ }
919
+ });
920
+ });
663
921
  }
664
922
  async createProcess(binary, args) {
665
923
  await this.initializeBinary();
@@ -667,7 +925,7 @@ var Engine = class {
667
925
  throw new Error("Binary not initialized");
668
926
  }
669
927
  return new Promise((resolve5, reject) => {
670
- const child = spawn(this.binary[binary], [...this.arguments, ...args]);
928
+ const child = spawn2(this.binary[binary], [...this.arguments, ...args]);
671
929
  let stdoutBuffer = "";
672
930
  let stderrBuffer = "";
673
931
  let isResolved = false;
@@ -749,21 +1007,20 @@ var Engine = class {
749
1007
  });
750
1008
  }
751
1009
  async disconnect() {
752
- if (this.isConnected) {
753
- console.log("\u{1F50C} Disconnecting persistent connection...");
754
- const response = await this.createProcess("query_engine", [
755
- "--action",
756
- "disconnect"
757
- ]);
758
- if (response.status === 200) {
759
- this.isConnected = false;
760
- console.log("\u2705 Persistent connection closed");
761
- }
762
- return response;
1010
+ const serverInfo = globalTcpServers.get(this.connectionId);
1011
+ if (serverInfo && serverInfo.process && !serverInfo.process.killed) {
1012
+ console.log("\u{1F50C} Stopping TCP server...");
1013
+ serverInfo.process.kill();
1014
+ globalTcpServers.delete(this.connectionId);
1015
+ return {
1016
+ status: 200,
1017
+ message: "TCP server stopped",
1018
+ data: null
1019
+ };
763
1020
  }
764
1021
  return {
765
1022
  status: 200,
766
- message: "No persistent connection to disconnect",
1023
+ message: "No TCP server to stop",
767
1024
  data: null
768
1025
  };
769
1026
  }
@@ -771,10 +1028,10 @@ var Engine = class {
771
1028
 
772
1029
  // src/lib/SqliteExecutor.ts
773
1030
  import { exec } from "child_process";
774
- import * as path4 from "path";
1031
+ import * as path5 from "path";
775
1032
  import * as fs3 from "fs";
776
1033
  import { promisify } from "util";
777
- import { createRequire as createRequire2 } from "module";
1034
+ import { createRequire as createRequire3 } from "module";
778
1035
  var execAsync = promisify(exec);
779
1036
  var SqliteExecutor = class {
780
1037
  binaryPath;
@@ -785,27 +1042,27 @@ var SqliteExecutor = class {
785
1042
  }
786
1043
  getBinaryPath() {
787
1044
  const possibleDirs = [
788
- path4.resolve(process.cwd(), ".dbcube", "bin"),
789
- path4.resolve(process.cwd(), "node_modules", ".dbcube", "bin"),
790
- path4.resolve(__dirname, "..", "bin")
1045
+ path5.resolve(process.cwd(), ".dbcube", "bin"),
1046
+ path5.resolve(process.cwd(), "node_modules", ".dbcube", "bin"),
1047
+ path5.resolve(__dirname, "..", "bin")
791
1048
  ];
792
1049
  const platform2 = process.platform;
793
1050
  const extension = platform2 === "win32" ? ".exe" : "";
794
1051
  const binaryName = `sqlite-engine-${platform2 === "win32" ? "windows" : platform2 === "darwin" ? "macos" : "linux"}-x64${extension}`;
795
1052
  for (const dir of possibleDirs) {
796
- const fullPath = path4.join(dir, binaryName);
1053
+ const fullPath = path5.join(dir, binaryName);
797
1054
  if (fs3.existsSync(fullPath)) {
798
1055
  return fullPath;
799
1056
  }
800
1057
  }
801
1058
  const fallbackName = `sqlite-engine${extension}`;
802
1059
  for (const dir of possibleDirs) {
803
- const fullPath = path4.join(dir, fallbackName);
1060
+ const fullPath = path5.join(dir, fallbackName);
804
1061
  if (fs3.existsSync(fullPath)) {
805
1062
  return fullPath;
806
1063
  }
807
1064
  }
808
- return path4.join(possibleDirs[0], binaryName);
1065
+ return path5.join(possibleDirs[0], binaryName);
809
1066
  }
810
1067
  async executeBinary(args) {
811
1068
  const escapedArgs = args.map((arg) => {
@@ -907,7 +1164,7 @@ var SqliteExecutor = class {
907
1164
  // Para compatibilidad con better-sqlite3 API sincrona usando deasync si es necesario
908
1165
  prepareSync(sql) {
909
1166
  const requireUrl = typeof __filename !== "undefined" ? __filename : process.cwd();
910
- const require2 = createRequire2(requireUrl);
1167
+ const require2 = createRequire3(requireUrl);
911
1168
  const deasync = require2("deasync");
912
1169
  return {
913
1170
  all: (...params) => {
@@ -955,9 +1212,9 @@ var SqliteExecutor = class {
955
1212
  };
956
1213
 
957
1214
  // src/lib/DbConfig.ts
958
- import * as path5 from "path";
1215
+ import * as path6 from "path";
959
1216
  import fs4 from "fs";
960
- var rootPath = path5.resolve(process.cwd(), ".dbcube");
1217
+ var rootPath = path6.resolve(process.cwd(), ".dbcube");
961
1218
  var SQLite = class {
962
1219
  executor = null;
963
1220
  database;
@@ -967,7 +1224,7 @@ var SQLite = class {
967
1224
  async ifExist() {
968
1225
  if (this.database) {
969
1226
  const dbPath = this.database || ":memory:";
970
- const configPath = path5.join(rootPath, dbPath + ".db");
1227
+ const configPath = path6.join(rootPath, dbPath + ".db");
971
1228
  if (!fs4.existsSync(rootPath)) {
972
1229
  fs4.mkdirSync(rootPath, { recursive: true });
973
1230
  }
@@ -986,7 +1243,7 @@ var SQLite = class {
986
1243
  try {
987
1244
  if (!this.executor) {
988
1245
  const dbPath = this.database || ":memory:";
989
- const configPath = path5.join(rootPath, dbPath + ".db");
1246
+ const configPath = path6.join(rootPath, dbPath + ".db");
990
1247
  if (!fs4.existsSync(rootPath)) {
991
1248
  fs4.mkdirSync(rootPath, { recursive: true });
992
1249
  }
@@ -1171,7 +1428,7 @@ var DbConfig_default = DbConfig;
1171
1428
 
1172
1429
  // src/lib/FileLogger.ts
1173
1430
  import * as fs5 from "fs";
1174
- import * as path6 from "path";
1431
+ import * as path7 from "path";
1175
1432
  import { EventEmitter } from "events";
1176
1433
  var FileLogger = class _FileLogger extends EventEmitter {
1177
1434
  static watchers = /* @__PURE__ */ new Map();
@@ -1186,7 +1443,7 @@ var FileLogger = class _FileLogger extends EventEmitter {
1186
1443
  */
1187
1444
  static async write(filePath, message, level = "INFO", append = true) {
1188
1445
  try {
1189
- const dir = path6.dirname(filePath);
1446
+ const dir = path7.dirname(filePath);
1190
1447
  if (!fs5.existsSync(dir)) {
1191
1448
  fs5.mkdirSync(dir, { recursive: true });
1192
1449
  }
@@ -1225,7 +1482,7 @@ var FileLogger = class _FileLogger extends EventEmitter {
1225
1482
  const buffer = _FileLogger.buffers.get(filePath);
1226
1483
  if (buffer && buffer.length > 0) {
1227
1484
  try {
1228
- const dir = path6.dirname(filePath);
1485
+ const dir = path7.dirname(filePath);
1229
1486
  if (!fs5.existsSync(dir)) {
1230
1487
  fs5.mkdirSync(dir, { recursive: true });
1231
1488
  }
@@ -1948,6 +2205,7 @@ export {
1948
2205
  DbConfig,
1949
2206
  Engine,
1950
2207
  FileLogger,
2208
+ QueryEngine,
1951
2209
  TableProcessor,
1952
2210
  TriggerProcessor
1953
2211
  };