@mostajs/orm 1.0.0 → 1.2.0

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.
@@ -0,0 +1,31 @@
1
+ import type { DialectType } from '../core/types.js';
2
+ export interface JdbcDriverInfo {
3
+ /** Glob prefix to find the JAR in jar_files/ (e.g. 'hsqldb' matches hsqldb*.jar) */
4
+ jarPrefix: string;
5
+ /** JDBC URL template — {host}, {port}, {db} are replaced at runtime */
6
+ jdbcUrlTemplate: string;
7
+ /** Default SGBD port */
8
+ defaultPort: number;
9
+ /** Default JDBC user */
10
+ defaultUser: string;
11
+ /** Default JDBC password */
12
+ defaultPassword: string;
13
+ /** JDBC driver class name (for logging) */
14
+ driverClass: string;
15
+ /** Human-readable label */
16
+ label: string;
17
+ }
18
+ /**
19
+ * Registry of JDBC-bridge-eligible dialects.
20
+ * Only dialects that benefit from the JDBC bridge are listed here.
21
+ * Dialects with good npm drivers (pg, mysql2, mongoose...) are NOT listed.
22
+ */
23
+ export declare const JDBC_REGISTRY: Partial<Record<DialectType, JdbcDriverInfo>>;
24
+ /**
25
+ * Check if a dialect has a JDBC bridge entry.
26
+ */
27
+ export declare function hasJdbcDriver(dialect: DialectType): boolean;
28
+ /**
29
+ * Get JDBC driver info for a dialect. Returns undefined if not bridge-eligible.
30
+ */
31
+ export declare function getJdbcDriverInfo(dialect: DialectType): JdbcDriverInfo | undefined;
@@ -0,0 +1,67 @@
1
+ // JDBC Driver Registry — maps dialect → JAR pattern → JDBC URL template
2
+ // Used by JdbcNormalizer to auto-detect JARs and compose JDBC URLs
3
+ // Author: Dr Hamid MADANI drmdh@msn.com
4
+ /**
5
+ * Registry of JDBC-bridge-eligible dialects.
6
+ * Only dialects that benefit from the JDBC bridge are listed here.
7
+ * Dialects with good npm drivers (pg, mysql2, mongoose...) are NOT listed.
8
+ */
9
+ export const JDBC_REGISTRY = {
10
+ hsqldb: {
11
+ jarPrefix: 'hsqldb',
12
+ jdbcUrlTemplate: 'jdbc:hsqldb:hsql://{host}:{port}/{db}',
13
+ defaultPort: 9001,
14
+ defaultUser: 'SA',
15
+ defaultPassword: '',
16
+ driverClass: 'org.hsqldb.jdbc.JDBCDriver',
17
+ label: 'HyperSQL (HSQLDB)',
18
+ },
19
+ oracle: {
20
+ jarPrefix: 'ojdbc',
21
+ jdbcUrlTemplate: 'jdbc:oracle:thin:@//{host}:{port}/{db}',
22
+ defaultPort: 1521,
23
+ defaultUser: 'system',
24
+ defaultPassword: 'oracle',
25
+ driverClass: 'oracle.jdbc.OracleDriver',
26
+ label: 'Oracle Database',
27
+ },
28
+ db2: {
29
+ jarPrefix: 'db2jcc',
30
+ jdbcUrlTemplate: 'jdbc:db2://{host}:{port}/{db}',
31
+ defaultPort: 50000,
32
+ defaultUser: 'db2inst1',
33
+ defaultPassword: 'db2inst1',
34
+ driverClass: 'com.ibm.db2.jcc.DB2Driver',
35
+ label: 'IBM DB2',
36
+ },
37
+ sybase: {
38
+ jarPrefix: 'jconn',
39
+ jdbcUrlTemplate: 'jdbc:sybase:Tds:{host}:{port}/{db}',
40
+ defaultPort: 5000,
41
+ defaultUser: 'sa',
42
+ defaultPassword: '',
43
+ driverClass: 'com.sybase.jdbc4.jdbc.SybDriver',
44
+ label: 'Sybase ASE',
45
+ },
46
+ hana: {
47
+ jarPrefix: 'ngdbc',
48
+ jdbcUrlTemplate: 'jdbc:sap://{host}:{port}',
49
+ defaultPort: 30015,
50
+ defaultUser: 'SYSTEM',
51
+ defaultPassword: 'manager',
52
+ driverClass: 'com.sap.db.jdbc.Driver',
53
+ label: 'SAP HANA',
54
+ },
55
+ };
56
+ /**
57
+ * Check if a dialect has a JDBC bridge entry.
58
+ */
59
+ export function hasJdbcDriver(dialect) {
60
+ return dialect in JDBC_REGISTRY;
61
+ }
62
+ /**
63
+ * Get JDBC driver info for a dialect. Returns undefined if not bridge-eligible.
64
+ */
65
+ export function getJdbcDriverInfo(dialect) {
66
+ return JDBC_REGISTRY[dialect];
67
+ }
@@ -13,10 +13,16 @@ export declare abstract class AbstractSqlDialect implements IDialect {
13
13
  abstract fieldToSqlType(field: FieldDef): string;
14
14
  /** Get the SQL column type for the primary key (id) column */
15
15
  abstract getIdColumnType(): string;
16
- /** Execute a SELECT query, return rows */
17
- abstract executeQuery<T>(sql: string, params: unknown[]): Promise<T[]>;
18
- /** Execute a non-SELECT statement (INSERT/UPDATE/DELETE), return changes count */
19
- abstract executeRun(sql: string, params: unknown[]): Promise<{
16
+ /** Execute a SELECT query via the dialect's native driver (npm) */
17
+ abstract doExecuteQuery<T>(sql: string, params: unknown[]): Promise<T[]>;
18
+ /** Execute a non-SELECT statement via the dialect's native driver (npm) */
19
+ abstract doExecuteRun(sql: string, params: unknown[]): Promise<{
20
+ changes: number;
21
+ }>;
22
+ /** Execute a SELECT query — routes to JDBC bridge or native driver */
23
+ executeQuery<T>(sql: string, params: unknown[]): Promise<T[]>;
24
+ /** Execute a non-SELECT statement — routes to JDBC bridge or native driver */
25
+ executeRun(sql: string, params: unknown[]): Promise<{
20
26
  changes: number;
21
27
  }>;
22
28
  /** Establish the actual database connection */
@@ -32,6 +38,8 @@ export declare abstract class AbstractSqlDialect implements IDialect {
32
38
  protected showSql: boolean;
33
39
  protected formatSql: boolean;
34
40
  private paramCounter;
41
+ private bridgeInstance;
42
+ private jdbcBridgeActive;
35
43
  /** Whether this dialect supports CREATE TABLE IF NOT EXISTS */
36
44
  protected supportsIfNotExists(): boolean;
37
45
  /** Whether this dialect supports RETURNING clause on INSERT */
@@ -85,6 +93,20 @@ export declare abstract class AbstractSqlDialect implements IDialect {
85
93
  connect(config: ConnectionConfig): Promise<void>;
86
94
  disconnect(): Promise<void>;
87
95
  testConnection(): Promise<boolean>;
96
+ /**
97
+ * Execute a SELECT query via the JDBC bridge.
98
+ * Called transparently when jdbcBridgeActive is true.
99
+ */
100
+ protected bridgeExecuteQuery<T>(sql: string, params: unknown[]): Promise<T[]>;
101
+ /**
102
+ * Execute a non-SELECT statement via the JDBC bridge.
103
+ * Called transparently when jdbcBridgeActive is true.
104
+ */
105
+ protected bridgeExecuteRun(sql: string, params: unknown[]): Promise<{
106
+ changes: number;
107
+ }>;
108
+ /** Whether the JDBC bridge is active for this dialect instance */
109
+ protected get isJdbcBridgeActive(): boolean;
88
110
  initSchema(schemas: EntitySchema[]): Promise<void>;
89
111
  find<T>(schema: EntitySchema, filter: DALFilter, options?: QueryOptions): Promise<T[]>;
90
112
  findOne<T>(schema: EntitySchema, filter: DALFilter, options?: QueryOptions): Promise<T | null>;
@@ -1,8 +1,12 @@
1
1
  // Abstract SQL Dialect — base class for all SQL dialects
2
2
  // Inspired by org.hibernate.dialect.Dialect (Hibernate ORM 6.4)
3
3
  // Extracts ~80% of shared SQL logic from sqlite.dialect.ts
4
+ // Includes JDBC bridge support via JdbcNormalizer (transparent interception)
4
5
  // Author: Dr Hamid MADANI drmdh@msn.com
5
6
  import { randomUUID } from 'crypto';
7
+ import { JdbcNormalizer } from '../bridge/JdbcNormalizer.js';
8
+ import { hasJdbcDriver } from '../bridge/jdbc-registry.js';
9
+ import { BridgeManager } from '../bridge/BridgeManager.js';
6
10
  // ============================================================
7
11
  // SQL Logging — inspired by hibernate.show_sql / hibernate.format_sql
8
12
  // ============================================================
@@ -57,12 +61,28 @@ function regexToLike(regex) {
57
61
  // AbstractSqlDialect — base for all SQL dialects
58
62
  // ============================================================
59
63
  export class AbstractSqlDialect {
64
+ // --- Concrete query methods with JDBC bridge interception ---
65
+ /** Execute a SELECT query — routes to JDBC bridge or native driver */
66
+ async executeQuery(sql, params) {
67
+ if (this.jdbcBridgeActive)
68
+ return this.bridgeExecuteQuery(sql, params);
69
+ return this.doExecuteQuery(sql, params);
70
+ }
71
+ /** Execute a non-SELECT statement — routes to JDBC bridge or native driver */
72
+ async executeRun(sql, params) {
73
+ if (this.jdbcBridgeActive)
74
+ return this.bridgeExecuteRun(sql, params);
75
+ return this.doExecuteRun(sql, params);
76
+ }
60
77
  // --- Protected state ---
61
78
  config = null;
62
79
  schemas = [];
63
80
  showSql = false;
64
81
  formatSql = false;
65
82
  paramCounter = 0;
83
+ // --- JDBC Bridge state (transparent interception) ---
84
+ bridgeInstance = null;
85
+ jdbcBridgeActive = false;
66
86
  // --- Hooks (overridable by subclasses) ---
67
87
  /** Whether this dialect supports CREATE TABLE IF NOT EXISTS */
68
88
  supportsIfNotExists() { return true; }
@@ -523,8 +543,25 @@ export class AbstractSqlDialect {
523
543
  this.config = config;
524
544
  this.showSql = config.showSql ?? false;
525
545
  this.formatSql = config.formatSql ?? false;
526
- await this.doConnect(config);
527
- this.log('CONNECT', config.uri);
546
+ // --- JDBC Bridge interception via BridgeManager ---
547
+ // If a JDBC JAR is available for this dialect, use the bridge
548
+ // instead of calling the dialect's doConnect() (npm driver).
549
+ // BridgeManager handles multi-bridge, port management, PID files, autostart.
550
+ const jarDir = config.options?.jarDir;
551
+ if (hasJdbcDriver(this.dialectType) && JdbcNormalizer.isAvailable(this.dialectType, jarDir)) {
552
+ const manager = BridgeManager.getInstance();
553
+ this.bridgeInstance = await manager.getOrCreate(this.dialectType, config.uri, {
554
+ jarDir,
555
+ bridgeJavaFile: config.options?.bridgeJavaFile,
556
+ });
557
+ this.jdbcBridgeActive = true;
558
+ this.log('CONNECT', `${config.uri} [via JDBC bridge on port ${this.bridgeInstance.port}]`);
559
+ }
560
+ else {
561
+ // No JAR found — use the dialect's native npm driver
562
+ await this.doConnect(config);
563
+ this.log('CONNECT', config.uri);
564
+ }
528
565
  if (config.schemaStrategy === 'create') {
529
566
  this.log('SCHEMA', 'create — dropping existing tables');
530
567
  await this.dropAllTables();
@@ -535,19 +572,56 @@ export class AbstractSqlDialect {
535
572
  this.log('SCHEMA', 'create-drop — dropping all tables on shutdown');
536
573
  await this.dropAllTables();
537
574
  }
538
- await this.doDisconnect();
575
+ if (this.jdbcBridgeActive && this.bridgeInstance) {
576
+ // Do NOT stop the bridge — BridgeManager manages its lifecycle.
577
+ // Other dialect instances may reuse the same bridge.
578
+ // Bridges are stopped by BridgeManager.stopAll() on app exit.
579
+ this.bridgeInstance = null;
580
+ this.jdbcBridgeActive = false;
581
+ }
582
+ else {
583
+ await this.doDisconnect();
584
+ }
539
585
  this.config = null;
540
586
  this.schemas = [];
541
587
  this.log('DISCONNECT', '');
542
588
  }
543
589
  async testConnection() {
544
590
  try {
591
+ if (this.jdbcBridgeActive && this.bridgeInstance) {
592
+ const result = await this.bridgeInstance.normalizer.query('SELECT 1', []);
593
+ return Array.isArray(result);
594
+ }
545
595
  return await this.doTestConnection();
546
596
  }
547
597
  catch {
548
598
  return false;
549
599
  }
550
600
  }
601
+ // --- JDBC Bridge query methods (used by executeQuery/executeRun interception) ---
602
+ /**
603
+ * Execute a SELECT query via the JDBC bridge.
604
+ * Called transparently when jdbcBridgeActive is true.
605
+ */
606
+ async bridgeExecuteQuery(sql, params) {
607
+ if (!this.bridgeInstance)
608
+ throw new Error('JDBC bridge not initialized');
609
+ return this.bridgeInstance.normalizer.query(sql, params);
610
+ }
611
+ /**
612
+ * Execute a non-SELECT statement via the JDBC bridge.
613
+ * Called transparently when jdbcBridgeActive is true.
614
+ */
615
+ async bridgeExecuteRun(sql, params) {
616
+ if (!this.bridgeInstance)
617
+ throw new Error('JDBC bridge not initialized');
618
+ const result = await this.bridgeInstance.normalizer.query(sql, params);
619
+ return { changes: result?.changes ?? 0 };
620
+ }
621
+ /** Whether the JDBC bridge is active for this dialect instance */
622
+ get isJdbcBridgeActive() {
623
+ return this.jdbcBridgeActive;
624
+ }
551
625
  // --- Schema management (hibernate.hbm2ddl.auto) ---
552
626
  async initSchema(schemas) {
553
627
  this.schemas = schemas;
@@ -97,7 +97,7 @@ class DB2Dialect extends AbstractSqlDialect {
97
97
  return Array.isArray(rows);
98
98
  }
99
99
  // --- Query execution ---
100
- async executeQuery(sql, params) {
100
+ async doExecuteQuery(sql, params) {
101
101
  if (!this.conn)
102
102
  throw new Error('DB2 not connected. Call connect() first.');
103
103
  return new Promise((resolve, reject) => {
@@ -109,7 +109,7 @@ class DB2Dialect extends AbstractSqlDialect {
109
109
  });
110
110
  });
111
111
  }
112
- async executeRun(sql, params) {
112
+ async doExecuteRun(sql, params) {
113
113
  if (!this.conn)
114
114
  throw new Error('DB2 not connected. Call connect() first.');
115
115
  return new Promise((resolve, reject) => {
@@ -92,7 +92,7 @@ class HANADialect extends AbstractSqlDialect {
92
92
  return Array.isArray(rows);
93
93
  }
94
94
  // --- Query execution ---
95
- async executeQuery(sql, params) {
95
+ async doExecuteQuery(sql, params) {
96
96
  if (!this.conn)
97
97
  throw new Error('HANA not connected. Call connect() first.');
98
98
  return new Promise((resolve, reject) => {
@@ -104,7 +104,7 @@ class HANADialect extends AbstractSqlDialect {
104
104
  });
105
105
  });
106
106
  }
107
- async executeRun(sql, params) {
107
+ async doExecuteRun(sql, params) {
108
108
  if (!this.conn)
109
109
  throw new Error('HANA not connected. Call connect() first.');
110
110
  return new Promise((resolve, reject) => {
@@ -1,7 +1,7 @@
1
1
  // HyperSQL (HSQLDB) Dialect — extends AbstractSqlDialect
2
2
  // Equivalent to org.hibernate.dialect.HSQLDialect (Hibernate ORM 6.4)
3
- // HSQLDB is a Java databaseaccessed via HTTP/JDBC bridge or REST API
4
- // Driver: HTTP fetch (no npm driver uses Java HTTP API bridge)
3
+ // Driver: JDBC bridge (no npm driver Java database)
4
+ // Connection handled transparently by AbstractSqlDialect JDBC bridge interception
5
5
  // Author: Dr Hamid MADANI drmdh@msn.com
6
6
  import { AbstractSqlDialect } from './abstract-sql.dialect.js';
7
7
  // ============================================================
@@ -16,13 +16,12 @@ const HSQL_TYPE_MAP = {
16
16
  array: 'CLOB',
17
17
  };
18
18
  // ============================================================
19
- // HSQLDialect
19
+ // HSQLDialect — SQL definition only (like Hibernate HSQLDialect)
20
+ // Connection is handled by AbstractSqlDialect via JDBC bridge
20
21
  // ============================================================
21
22
  class HSQLDialect extends AbstractSqlDialect {
22
23
  dialectType = 'hsqldb';
23
- baseUrl = '';
24
- connected = false;
25
- // --- Abstract implementations ---
24
+ // --- Abstract implementations (SQL definition) ---
26
25
  quoteIdentifier(name) {
27
26
  return `"${name}"`;
28
27
  }
@@ -47,62 +46,29 @@ class HSQLDialect extends AbstractSqlDialect {
47
46
  }
48
47
  // HSQLDB supports LIMIT/OFFSET natively
49
48
  // (default buildLimitOffset from AbstractSqlDialect works)
50
- // --- Connection (HTTP bridge to HSQLDB server) ---
51
- async doConnect(config) {
52
- // URI format: http://host:port/dbname or hsqldb://host:port/dbname
53
- this.baseUrl = config.uri
54
- .replace(/^hsqldb:\/\//, 'http://')
55
- .replace(/\/$/, '');
56
- // Test connectivity
57
- try {
58
- await this.httpPost('SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS', []);
59
- this.connected = true;
60
- }
61
- catch (e) {
62
- throw new Error(`HSQLDB HTTP bridge not reachable at ${this.baseUrl}.\n` +
63
- `Ensure the HSQLDB server is running with HTTP API enabled.\n` +
64
- `Original error: ${e instanceof Error ? e.message : String(e)}`);
65
- }
49
+ // --- Connection (native driver fallback) ---
50
+ // HSQLDB is a Java database — no npm driver exists.
51
+ // Normal path: AbstractSqlDialect detects hsqldb*.jar and uses JDBC bridge.
52
+ // These methods are only called if no JAR is found (fallback impossible).
53
+ async doConnect(_config) {
54
+ throw new Error('HSQLDB requires a JDBC bridge.\n' +
55
+ 'Place hsqldb*.jar in the jar_files/ directory.\n' +
56
+ 'No npm driver exists for HSQLDB.');
66
57
  }
67
58
  async doDisconnect() {
68
- this.connected = false;
69
- this.baseUrl = '';
59
+ // Nothing to clean up — bridge is managed by AbstractSqlDialect
70
60
  }
71
61
  async doTestConnection() {
72
- if (!this.connected)
73
- return false;
74
- try {
75
- await this.httpPost('SELECT 1 FROM INFORMATION_SCHEMA.SYSTEM_USERS', []);
76
- return true;
77
- }
78
- catch {
79
- return false;
80
- }
62
+ // Bridge test is handled by AbstractSqlDialect.testConnection()
63
+ return false;
81
64
  }
82
- // --- Query execution via HTTP bridge ---
83
- async executeQuery(sql, params) {
84
- if (!this.connected)
85
- throw new Error('HSQLDB not connected. Call connect() first.');
86
- return this.httpPost(sql, params);
65
+ // --- Query execution (native driver fallback) ---
66
+ // Only called when JDBC bridge is NOT active (impossible for HSQLDB).
67
+ async doExecuteQuery(_sql, _params) {
68
+ throw new Error('HSQLDB requires a JDBC bridge. Place hsqldb*.jar in jar_files/.');
87
69
  }
88
- async executeRun(sql, params) {
89
- if (!this.connected)
90
- throw new Error('HSQLDB not connected. Call connect() first.');
91
- const result = await this.httpPost(sql, params);
92
- return { changes: result?.changes ?? 0 };
93
- }
94
- /** Send SQL to HSQLDB HTTP bridge */
95
- async httpPost(sql, params) {
96
- const response = await fetch(`${this.baseUrl}/query`, {
97
- method: 'POST',
98
- headers: { 'Content-Type': 'application/json' },
99
- body: JSON.stringify({ sql, params }),
100
- });
101
- if (!response.ok) {
102
- const text = await response.text();
103
- throw new Error(`HSQLDB query failed (${response.status}): ${text}`);
104
- }
105
- return response.json();
70
+ async doExecuteRun(_sql, _params) {
71
+ throw new Error('HSQLDB requires a JDBC bridge. Place hsqldb*.jar in jar_files/.');
106
72
  }
107
73
  getDialectLabel() { return 'HSQLDB'; }
108
74
  }
@@ -34,7 +34,7 @@ class MariaDBDialect extends MySQLDialect {
34
34
  }
35
35
  }
36
36
  // Override executeQuery to handle mariadb driver's different API
37
- async executeQuery(sql, params) {
37
+ async doExecuteQuery(sql, params) {
38
38
  if (!this.pool)
39
39
  throw new Error('MariaDB not connected. Call connect() first.');
40
40
  try {
@@ -50,7 +50,7 @@ class MariaDBDialect extends MySQLDialect {
50
50
  return super.executeQuery(sql, params);
51
51
  }
52
52
  }
53
- async executeRun(sql, params) {
53
+ async doExecuteRun(sql, params) {
54
54
  if (!this.pool)
55
55
  throw new Error('MariaDB not connected. Call connect() first.');
56
56
  try {
@@ -18,8 +18,8 @@ export declare class MSSQLDialect extends AbstractSqlDialect {
18
18
  doConnect(config: ConnectionConfig): Promise<void>;
19
19
  doDisconnect(): Promise<void>;
20
20
  doTestConnection(): Promise<boolean>;
21
- executeQuery<T>(sql: string, params: unknown[]): Promise<T[]>;
22
- executeRun(sql: string, params: unknown[]): Promise<{
21
+ doExecuteQuery<T>(sql: string, params: unknown[]): Promise<T[]>;
22
+ doExecuteRun(sql: string, params: unknown[]): Promise<{
23
23
  changes: number;
24
24
  }>;
25
25
  protected getDialectLabel(): string;
@@ -96,7 +96,7 @@ export class MSSQLDialect extends AbstractSqlDialect {
96
96
  return true;
97
97
  }
98
98
  // --- Query execution ---
99
- async executeQuery(sql, params) {
99
+ async doExecuteQuery(sql, params) {
100
100
  if (!this.pool)
101
101
  throw new Error('SQL Server not connected. Call connect() first.');
102
102
  const request = this.pool.request();
@@ -107,7 +107,7 @@ export class MSSQLDialect extends AbstractSqlDialect {
107
107
  const result = await request.query(sql);
108
108
  return result.recordset;
109
109
  }
110
- async executeRun(sql, params) {
110
+ async doExecuteRun(sql, params) {
111
111
  if (!this.pool)
112
112
  throw new Error('SQL Server not connected. Call connect() first.');
113
113
  const request = this.pool.request();
@@ -15,8 +15,8 @@ export declare class MySQLDialect extends AbstractSqlDialect {
15
15
  doConnect(config: ConnectionConfig): Promise<void>;
16
16
  doDisconnect(): Promise<void>;
17
17
  doTestConnection(): Promise<boolean>;
18
- executeQuery<T>(sql: string, params: unknown[]): Promise<T[]>;
19
- executeRun(sql: string, params: unknown[]): Promise<{
18
+ doExecuteQuery<T>(sql: string, params: unknown[]): Promise<T[]>;
19
+ doExecuteRun(sql: string, params: unknown[]): Promise<{
20
20
  changes: number;
21
21
  }>;
22
22
  protected getDialectLabel(): string;
@@ -79,13 +79,13 @@ export class MySQLDialect extends AbstractSqlDialect {
79
79
  }
80
80
  }
81
81
  // --- Query execution ---
82
- async executeQuery(sql, params) {
82
+ async doExecuteQuery(sql, params) {
83
83
  if (!this.pool)
84
84
  throw new Error('MySQL not connected. Call connect() first.');
85
85
  const [rows] = await this.pool.execute(sql, params);
86
86
  return rows;
87
87
  }
88
- async executeRun(sql, params) {
88
+ async doExecuteRun(sql, params) {
89
89
  if (!this.pool)
90
90
  throw new Error('MySQL not connected. Call connect() first.');
91
91
  const [result] = await this.pool.execute(sql, params);
@@ -111,7 +111,7 @@ class OracleDialect extends AbstractSqlDialect {
111
111
  }
112
112
  }
113
113
  // --- Query execution ---
114
- async executeQuery(sql, params) {
114
+ async doExecuteQuery(sql, params) {
115
115
  if (!this.pool)
116
116
  throw new Error('Oracle not connected. Call connect() first.');
117
117
  const conn = await this.pool.getConnection();
@@ -123,7 +123,7 @@ class OracleDialect extends AbstractSqlDialect {
123
123
  await conn.close();
124
124
  }
125
125
  }
126
- async executeRun(sql, params) {
126
+ async doExecuteRun(sql, params) {
127
127
  if (!this.pool)
128
128
  throw new Error('Oracle not connected. Call connect() first.');
129
129
  const conn = await this.pool.getConnection();
@@ -17,8 +17,8 @@ export declare class PostgresDialect extends AbstractSqlDialect {
17
17
  doConnect(config: ConnectionConfig): Promise<void>;
18
18
  doDisconnect(): Promise<void>;
19
19
  doTestConnection(): Promise<boolean>;
20
- executeQuery<T>(sql: string, params: unknown[]): Promise<T[]>;
21
- executeRun(sql: string, params: unknown[]): Promise<{
20
+ doExecuteQuery<T>(sql: string, params: unknown[]): Promise<T[]>;
21
+ doExecuteRun(sql: string, params: unknown[]): Promise<{
22
22
  changes: number;
23
23
  }>;
24
24
  protected getDialectLabel(): string;
@@ -83,13 +83,13 @@ export class PostgresDialect extends AbstractSqlDialect {
83
83
  }
84
84
  }
85
85
  // --- Query execution ---
86
- async executeQuery(sql, params) {
86
+ async doExecuteQuery(sql, params) {
87
87
  if (!this.pool)
88
88
  throw new Error('PostgreSQL not connected. Call connect() first.');
89
89
  const result = await this.pool.query(sql, params);
90
90
  return result.rows;
91
91
  }
92
- async executeRun(sql, params) {
92
+ async doExecuteRun(sql, params) {
93
93
  if (!this.pool)
94
94
  throw new Error('PostgreSQL not connected. Call connect() first.');
95
95
  const result = await this.pool.query(sql, params);
@@ -135,7 +135,7 @@ class SpannerDialect extends AbstractSqlDialect {
135
135
  }
136
136
  }
137
137
  // --- Query execution ---
138
- async executeQuery(sql, params) {
138
+ async doExecuteQuery(sql, params) {
139
139
  if (!this.database)
140
140
  throw new Error('Spanner not connected. Call connect() first.');
141
141
  // Build named params object: { p1: val1, p2: val2, ... }
@@ -152,7 +152,7 @@ class SpannerDialect extends AbstractSqlDialect {
152
152
  return row;
153
153
  });
154
154
  }
155
- async executeRun(sql, params) {
155
+ async doExecuteRun(sql, params) {
156
156
  if (!this.database)
157
157
  throw new Error('Spanner not connected. Call connect() first.');
158
158
  // For DML operations, Spanner requires using transactions
@@ -67,7 +67,7 @@ class SybaseDialect extends MSSQLDialect {
67
67
  await this.pool.query('SELECT 1');
68
68
  return true;
69
69
  }
70
- async executeQuery(sql, params) {
70
+ async doExecuteQuery(sql, params) {
71
71
  if (!this.pool)
72
72
  throw new Error('Sybase not connected. Call connect() first.');
73
73
  // Sybase driver doesn't support named params — replace @pN with values
@@ -75,7 +75,7 @@ class SybaseDialect extends MSSQLDialect {
75
75
  const result = await this.pool.query(resolvedSql);
76
76
  return Array.isArray(result) ? result : [];
77
77
  }
78
- async executeRun(sql, params) {
78
+ async doExecuteRun(sql, params) {
79
79
  if (!this.pool)
80
80
  throw new Error('Sybase not connected. Call connect() first.');
81
81
  const resolvedSql = this.resolveParams(sql, params);
package/dist/index.d.ts CHANGED
@@ -5,4 +5,10 @@ export { registerSchema, registerSchemas, getSchema, getSchemaByCollection, getA
5
5
  export { getDialect, getConfigFromEnv, getCurrentDialectType, disconnectDialect, testConnection, createConnection, } from './core/factory.js';
6
6
  export { BaseRepository } from './core/base-repository.js';
7
7
  export { normalizeDoc, normalizeDocs } from './core/normalizer.js';
8
+ export { JdbcNormalizer, parseUri } from './bridge/JdbcNormalizer.js';
9
+ export { JDBC_REGISTRY, hasJdbcDriver, getJdbcDriverInfo } from './bridge/jdbc-registry.js';
10
+ export { BridgeManager } from './bridge/BridgeManager.js';
11
+ export type { BridgeInstance } from './bridge/BridgeManager.js';
12
+ export type { JdbcDriverInfo } from './bridge/jdbc-registry.js';
13
+ export type { JdbcBridgeConfig } from './bridge/JdbcNormalizer.js';
8
14
  export { MostaORMError, EntityNotFoundError, ConnectionError, ValidationError, DialectNotFoundError, } from './core/errors.js';
package/dist/index.js CHANGED
@@ -21,6 +21,12 @@ export { BaseRepository } from './core/base-repository.js';
21
21
  // ============================================================
22
22
  export { normalizeDoc, normalizeDocs } from './core/normalizer.js';
23
23
  // ============================================================
24
+ // JDBC Bridge
25
+ // ============================================================
26
+ export { JdbcNormalizer, parseUri } from './bridge/JdbcNormalizer.js';
27
+ export { JDBC_REGISTRY, hasJdbcDriver, getJdbcDriverInfo } from './bridge/jdbc-registry.js';
28
+ export { BridgeManager } from './bridge/BridgeManager.js';
29
+ // ============================================================
24
30
  // Errors
25
31
  // ============================================================
26
32
  export { MostaORMError, EntityNotFoundError, ConnectionError, ValidationError, DialectNotFoundError, } from './core/errors.js';