@aetherframework/database 1.0.9 → 1.1.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.
- package/package.json +1 -2
- package/src/DatabaseManager.js +0 -565
- package/src/core/ConnectionManager.js +0 -351
- package/src/core/DatabaseFactory.js +0 -188
- package/src/core/MongoQueryBuilder.js +0 -576
- package/src/core/PluginManager.js +0 -968
- package/src/core/QueryBuilder.js +0 -4398
- package/src/core/TransactionManager.js +0 -40
- package/src/drivers/clickhouse-driver.js +0 -272
- package/src/drivers/index.js +0 -273
- package/src/drivers/mongodb-driver.js +0 -87
- package/src/drivers/mssql-driver.js +0 -117
- package/src/drivers/mysql-driver.js +0 -169
- package/src/drivers/oracle-driver.js +0 -101
- package/src/drivers/postgres-driver.js +0 -234
- package/src/drivers/redis-driver.js +0 -52
- package/src/drivers/sqlite-driver.js +0 -67
- package/src/middleware/connection-pool.js +0 -455
- package/src/middleware/performance-monitor.js +0 -652
- package/src/middleware/query-cache.js +0 -500
- package/src/middleware/query-logger.js +0 -262
- package/src/plugins/AuditPlugin.js +0 -447
- package/src/plugins/BasePlugin.js +0 -418
- package/src/plugins/BatchOperationPlugin.js +0 -165
- package/src/plugins/CachePlugin.js +0 -407
- package/src/plugins/CtePlugin.js +0 -523
- package/src/plugins/DistributedPlugin.js +0 -543
- package/src/plugins/EncryptionPlugin.js +0 -211
- package/src/plugins/FullTextSearchPlugin.js +0 -164
- package/src/plugins/GeospatialPlugin.js +0 -219
- package/src/plugins/GraphQLPlugin.js +0 -162
- package/src/plugins/HookPlugin.js +0 -211
- package/src/plugins/JsonPlugin.js +0 -366
- package/src/plugins/OptimisticLockPlugin.js +0 -374
- package/src/plugins/PerformancePlugin.js +0 -175
- package/src/plugins/ResiliencePlugin.js +0 -114
- package/src/plugins/ShardingPlugin.js +0 -227
- package/src/plugins/SoftDeletePlugin.js +0 -258
- package/src/plugins/SyncPlugin.js +0 -373
- package/src/plugins/VersioningPlugin.js +0 -314
- package/src/plugins/WindowFunctionPlugin.js +0 -343
- package/src/utils/config-loader.js +0 -632
- package/src/utils/error-handler.js +0 -724
- package/src/utils/migration-runner.js +0 -1066
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license MIT
|
|
3
|
-
* Copyright (c) 2026-present AetherFramework Contributors.
|
|
4
|
-
* SPDX-License-Identifier: MIT
|
|
5
|
-
* @module @aetherframework/database/core/TransactionManager
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
class TransactionManager {
|
|
9
|
-
constructor(driver) {
|
|
10
|
-
this.driver = driver;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
async transaction(callback) {
|
|
14
|
-
const connection = await this.driver.pool.getConnection();
|
|
15
|
-
try {
|
|
16
|
-
await this.driver.beginTransaction(connection);
|
|
17
|
-
|
|
18
|
-
const trx = {
|
|
19
|
-
query: (sql, params) => this.driver.query(connection, sql, params),
|
|
20
|
-
rawQuery: (sql) => this.driver.rawQuery(connection, sql),
|
|
21
|
-
execute: (sql, params) => this.driver.execute(connection, sql, params),
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const result = await callback(trx);
|
|
25
|
-
|
|
26
|
-
await this.driver.commitTransaction(connection);
|
|
27
|
-
|
|
28
|
-
return result;
|
|
29
|
-
|
|
30
|
-
} catch (error) {
|
|
31
|
-
|
|
32
|
-
await this.driver.rollbackTransaction(connection).catch(() => {});
|
|
33
|
-
throw error;
|
|
34
|
-
} finally {
|
|
35
|
-
connection.release();
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export default TransactionManager;
|
|
@@ -1,272 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license MIT
|
|
3
|
-
* Copyright (c) 2026-present AetherFramework Contributors.
|
|
4
|
-
* SPDX-License-Identifier: MIT
|
|
5
|
-
* @module @aetherframework/database/drivers/clickhouse-driver
|
|
6
|
-
*/
|
|
7
|
-
import { createClient } from '@clickhouse/client';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* ClickHouse Driver
|
|
11
|
-
* Implements ClickHouse database driver with environment variable control
|
|
12
|
-
*/
|
|
13
|
-
class ClickHouseDriver {
|
|
14
|
-
constructor(config) {
|
|
15
|
-
this.config = config;
|
|
16
|
-
this.client = null;
|
|
17
|
-
this.isConnected = false;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Initialize the ClickHouse client
|
|
22
|
-
* @returns {Promise<Object>} ClickHouse connection
|
|
23
|
-
*/
|
|
24
|
-
async connect() {
|
|
25
|
-
// Check if ClickHouse is enabled via environment variable
|
|
26
|
-
if (process.env.ENABLE_CLICKHOUSE !== 'true') {
|
|
27
|
-
throw new Error('ClickHouse driver is disabled. Set ENABLE_CLICKHOUSE=true to enable.');
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (this.isConnected) return this.client;
|
|
31
|
-
|
|
32
|
-
try {
|
|
33
|
-
this.client = createClient({
|
|
34
|
-
host: this.config.host || 'http://localhost:8123',
|
|
35
|
-
username: this.config.user || 'default',
|
|
36
|
-
password: this.config.password || '',
|
|
37
|
-
database: this.config.database || 'default',
|
|
38
|
-
// ClickHouse specific options
|
|
39
|
-
clickhouse_settings: {
|
|
40
|
-
async_insert: 1, // Enable async insert for better performance
|
|
41
|
-
wait_for_async_insert: 0,
|
|
42
|
-
},
|
|
43
|
-
// Connection pool settings
|
|
44
|
-
max_open_connections: this.config.pool?.max || 10,
|
|
45
|
-
request_timeout: this.config.pool?.acquireTimeout || 10000,
|
|
46
|
-
compression: {
|
|
47
|
-
response: true,
|
|
48
|
-
request: true
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
// Test connection
|
|
53
|
-
await this.client.ping();
|
|
54
|
-
this.isConnected = true;
|
|
55
|
-
return this.client;
|
|
56
|
-
} catch (error) {
|
|
57
|
-
console.error('❌ ClickHouse connection failed:', error.message);
|
|
58
|
-
throw error;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Create connection pool (ClickHouse doesn't have traditional connection pool)
|
|
64
|
-
* @returns {Promise<Object>} ClickHouse client
|
|
65
|
-
*/
|
|
66
|
-
async createPool() {
|
|
67
|
-
// ClickHouse client handles connection pooling internally
|
|
68
|
-
return await this.connect();
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Execute SELECT query
|
|
73
|
-
* @param {Object} connection - ClickHouse client
|
|
74
|
-
* @param {string} sql - SQL query
|
|
75
|
-
* @param {Array} params - Query parameters
|
|
76
|
-
* @returns {Promise<Object>} Query result
|
|
77
|
-
*/
|
|
78
|
-
async query(connection, sql, params = []) {
|
|
79
|
-
await this.ensureConnected();
|
|
80
|
-
|
|
81
|
-
try {
|
|
82
|
-
// ClickHouse uses parameterized queries differently
|
|
83
|
-
// We need to handle parameters manually
|
|
84
|
-
let finalSql = sql;
|
|
85
|
-
if (params && params.length > 0) {
|
|
86
|
-
// Replace ? placeholders with ClickHouse format
|
|
87
|
-
params.forEach((param, index) => {
|
|
88
|
-
const placeholder = `{param${index}:${this.getClickHouseType(param)}}`;
|
|
89
|
-
finalSql = finalSql.replace('?', placeholder);
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const resultSet = await connection.query({
|
|
94
|
-
query: finalSql,
|
|
95
|
-
format: 'JSONEachRow', // Return data as JSON array
|
|
96
|
-
clickhouse_settings: {
|
|
97
|
-
allow_experimental_object_type: 1
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
const rows = await resultSet.json();
|
|
102
|
-
return {
|
|
103
|
-
rows,
|
|
104
|
-
rowCount: rows.length,
|
|
105
|
-
metaData: resultSet.meta || []
|
|
106
|
-
};
|
|
107
|
-
} catch (error) {
|
|
108
|
-
console.error('❌ ClickHouse query error:', error.message);
|
|
109
|
-
throw error;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Execute INSERT/UPDATE/DELETE operation
|
|
115
|
-
* Note: ClickHouse has limited UPDATE/DELETE support
|
|
116
|
-
* @param {Object} connection - ClickHouse client
|
|
117
|
-
* @param {string} sql - SQL statement
|
|
118
|
-
* @param {Array} params - Query parameters
|
|
119
|
-
* @returns {Promise<Object>} Execution result
|
|
120
|
-
*/
|
|
121
|
-
async execute(connection, sql, params = []) {
|
|
122
|
-
await this.ensureConnected();
|
|
123
|
-
|
|
124
|
-
try {
|
|
125
|
-
let finalSql = sql;
|
|
126
|
-
if (params && params.length > 0) {
|
|
127
|
-
// Replace ? placeholders with ClickHouse format
|
|
128
|
-
params.forEach((param, index) => {
|
|
129
|
-
const placeholder = `{param${index}:${this.getClickHouseType(param)}}`;
|
|
130
|
-
finalSql = finalSql.replace('?', placeholder);
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// For INSERT operations, ClickHouse has optimized methods
|
|
135
|
-
if (sql.toUpperCase().startsWith('INSERT')) {
|
|
136
|
-
// Extract table name from INSERT statement
|
|
137
|
-
const tableMatch = sql.match(/INSERT\s+INTO\s+(\w+)/i);
|
|
138
|
-
if (tableMatch && tableMatch) {
|
|
139
|
-
const tableName = tableMatch;
|
|
140
|
-
// If params is an array of objects, use insert method
|
|
141
|
-
if (params.length > 0 && typeof params === 'object') {
|
|
142
|
-
await connection.insert({
|
|
143
|
-
table: tableName,
|
|
144
|
-
values: params,
|
|
145
|
-
format: 'JSONEachRow'
|
|
146
|
-
});
|
|
147
|
-
return { affectedRows: params.length };
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// For other operations, use command
|
|
153
|
-
await connection.command({ query: finalSql });
|
|
154
|
-
return { affectedRows: 1 };
|
|
155
|
-
} catch (error) {
|
|
156
|
-
console.error('❌ ClickHouse execute error:', error.message);
|
|
157
|
-
throw error;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Get ClickHouse type for parameter
|
|
163
|
-
* @param {*} value - Parameter value
|
|
164
|
-
* @returns {string} ClickHouse type string
|
|
165
|
-
*/
|
|
166
|
-
getClickHouseType(value) {
|
|
167
|
-
if (value === null || value === undefined) return 'Nullable(Nothing)';
|
|
168
|
-
if (typeof value === 'number') {
|
|
169
|
-
return Number.isInteger(value) ? 'Int64' : 'Float64';
|
|
170
|
-
}
|
|
171
|
-
if (typeof value === 'boolean') return 'UInt8';
|
|
172
|
-
if (typeof value === 'string') return 'String';
|
|
173
|
-
if (value instanceof Date) return 'DateTime';
|
|
174
|
-
if (Array.isArray(value)) return 'Array(String)';
|
|
175
|
-
if (typeof value === 'object') return 'JSON';
|
|
176
|
-
return 'String';
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Begin transaction (ClickHouse has limited transaction support)
|
|
181
|
-
* @param {Object} connection - ClickHouse client
|
|
182
|
-
* @returns {Promise<Object>} Transaction object
|
|
183
|
-
*/
|
|
184
|
-
async beginTransaction(connection) {
|
|
185
|
-
console.warn('⚠️ ClickHouse has limited transaction support. Transactions may not work as expected.');
|
|
186
|
-
// ClickHouse doesn't support traditional transactions for all operations
|
|
187
|
-
return { sessionId: Date.now() };
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Commit transaction
|
|
192
|
-
* @param {Object} transaction - Transaction object
|
|
193
|
-
*/
|
|
194
|
-
async commitTransaction(transaction) {
|
|
195
|
-
// ClickHouse doesn't support traditional commit
|
|
196
|
-
console.warn('⚠️ ClickHouse transaction committed (no-op)');
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Rollback transaction
|
|
201
|
-
* @param {Object} transaction - Transaction object
|
|
202
|
-
*/
|
|
203
|
-
async rollbackTransaction(transaction) {
|
|
204
|
-
// ClickHouse doesn't support traditional rollback
|
|
205
|
-
console.warn('⚠️ ClickHouse transaction rolled back (no-op)');
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Close connection
|
|
210
|
-
* @param {Object} connection - ClickHouse client
|
|
211
|
-
*/
|
|
212
|
-
async close(connection) {
|
|
213
|
-
if (this.client) {
|
|
214
|
-
await this.client.close();
|
|
215
|
-
this.isConnected = false;
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Close pool (ClickHouse doesn't have traditional connection pool)
|
|
221
|
-
* @param {Object} pool - Not used for ClickHouse
|
|
222
|
-
*/
|
|
223
|
-
async closePool(pool) {
|
|
224
|
-
await this.close();
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Get pool statistics
|
|
229
|
-
* @returns {Object} Pool statistics
|
|
230
|
-
*/
|
|
231
|
-
getPoolStats() {
|
|
232
|
-
return {
|
|
233
|
-
isConnected: this.isConnected,
|
|
234
|
-
// ClickHouse doesn't expose connection pool stats
|
|
235
|
-
note: 'ClickHouse uses HTTP connection pooling internally'
|
|
236
|
-
};
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* Health check
|
|
241
|
-
* @param {Object} connection - ClickHouse client
|
|
242
|
-
* @returns {Promise<boolean>} Health status
|
|
243
|
-
*/
|
|
244
|
-
async healthCheck(connection) {
|
|
245
|
-
try {
|
|
246
|
-
await connection.ping();
|
|
247
|
-
return true;
|
|
248
|
-
} catch (error) {
|
|
249
|
-
return false;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
/**
|
|
254
|
-
* Ensure connection is established
|
|
255
|
-
* @private
|
|
256
|
-
*/
|
|
257
|
-
async ensureConnected() {
|
|
258
|
-
if (!this.isConnected) {
|
|
259
|
-
await this.connect();
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Get dialect name
|
|
265
|
-
* @returns {string} Dialect name
|
|
266
|
-
*/
|
|
267
|
-
getDialect() {
|
|
268
|
-
return 'clickhouse';
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
export default ClickHouseDriver;
|
package/src/drivers/index.js
DELETED
|
@@ -1,273 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license MIT
|
|
3
|
-
* Copyright (c) 2026-present AetherFramework Contributors.
|
|
4
|
-
* SPDX-License-Identifier: MIT
|
|
5
|
-
* @module @aetherframework/database/drivers/index
|
|
6
|
-
*/
|
|
7
|
-
// Driver registry mapping database types to driver classes
|
|
8
|
-
const drivers = {};
|
|
9
|
-
|
|
10
|
-
// Driver file path mapping
|
|
11
|
-
const driverPaths = {
|
|
12
|
-
mysql: './mysql-driver.js',
|
|
13
|
-
mariadb: './mysql-driver.js',
|
|
14
|
-
postgresql: './postgres-driver.js',
|
|
15
|
-
postgres: './postgres-driver.js',
|
|
16
|
-
pg: './postgres-driver.js',
|
|
17
|
-
sqlite: './sqlite-driver.js',
|
|
18
|
-
sqlite3: './sqlite-driver.js',
|
|
19
|
-
mongodb: './mongodb-driver.js',
|
|
20
|
-
mongo: './mongodb-driver.js',
|
|
21
|
-
mssql: './mssql-driver.js',
|
|
22
|
-
sqlserver: './mssql-driver.js',
|
|
23
|
-
oracle: './oracle-driver.js',
|
|
24
|
-
// Add CockroachDB support (reuse PostgreSQL driver)
|
|
25
|
-
cockroachdb: './postgres-driver.js',
|
|
26
|
-
cockroach: './postgres-driver.js',
|
|
27
|
-
// Add ClickHouse support (requires separate driver)
|
|
28
|
-
clickhouse: './clickhouse-driver.js'
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Get driver class by database type name using dynamic imports
|
|
33
|
-
* @param {string} name - Database type name (mysql, postgresql, sqlite, etc.)
|
|
34
|
-
* @returns {Promise<Class|null>} Driver class or null if not found
|
|
35
|
-
*/
|
|
36
|
-
export async function getDriver(name) {
|
|
37
|
-
const normalizedName = name.toLowerCase();
|
|
38
|
-
|
|
39
|
-
// Return cached driver if already loaded
|
|
40
|
-
if (drivers[normalizedName]) {
|
|
41
|
-
return drivers[normalizedName];
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Check if it's MySQL (your current database)
|
|
45
|
-
if (normalizedName === 'mysql' || normalizedName === 'mariadb') {
|
|
46
|
-
try {
|
|
47
|
-
// Only dynamically import MySQL driver
|
|
48
|
-
const { default: MySQLDriver } = await import('./mysql-driver.js');
|
|
49
|
-
drivers[normalizedName] = MySQLDriver;
|
|
50
|
-
return MySQLDriver;
|
|
51
|
-
} catch (error) {
|
|
52
|
-
console.error(`❌ Failed to load MySQL driver:`, error.message);
|
|
53
|
-
return null;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Check if it's MongoDB
|
|
58
|
-
if (normalizedName === 'mongodb' || normalizedName === 'mongo') {
|
|
59
|
-
try {
|
|
60
|
-
// Dynamically import MongoDB driver
|
|
61
|
-
const { default: MongoDBDriver } = await import('./mongodb-driver.js');
|
|
62
|
-
drivers[normalizedName] = MongoDBDriver;
|
|
63
|
-
return MongoDBDriver;
|
|
64
|
-
} catch (error) {
|
|
65
|
-
console.error(`❌ Failed to load MongoDB driver:`, error.message);
|
|
66
|
-
return null;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Check if it's CockroachDB (reuse PostgreSQL driver)
|
|
71
|
-
if (normalizedName === 'cockroachdb' || normalizedName === 'cockroach') {
|
|
72
|
-
// Check if CockroachDB support is enabled via environment variable
|
|
73
|
-
if (process.env.ENABLE_COCKROACHDB !== 'true') {
|
|
74
|
-
console.warn(`⚠️ CockroachDB driver is disabled. Set ENABLE_COCKROACHDB=true to enable.`);
|
|
75
|
-
return null;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
try {
|
|
79
|
-
// CockroachDB is PostgreSQL compatible, reuse PostgreSQL driver
|
|
80
|
-
const { default: PostgreSQLDriver } = await import('./postgres-driver.js');
|
|
81
|
-
drivers[normalizedName] = PostgreSQLDriver;
|
|
82
|
-
|
|
83
|
-
return PostgreSQLDriver;
|
|
84
|
-
} catch (error) {
|
|
85
|
-
console.error(`❌ Failed to load CockroachDB driver:`, error.message);
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Check if it's ClickHouse
|
|
91
|
-
if (normalizedName === 'clickhouse') {
|
|
92
|
-
// Check if ClickHouse support is enabled via environment variable
|
|
93
|
-
if (process.env.ENABLE_CLICKHOUSE !== 'true') {
|
|
94
|
-
console.warn(`⚠️ ClickHouse driver is disabled. Set ENABLE_CLICKHOUSE=true to enable.`);
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
try {
|
|
99
|
-
// Dynamically import ClickHouse driver
|
|
100
|
-
const { default: ClickHouseDriver } = await import('./clickhouse-driver.js');
|
|
101
|
-
drivers[normalizedName] = ClickHouseDriver;
|
|
102
|
-
|
|
103
|
-
return ClickHouseDriver;
|
|
104
|
-
} catch (error) {
|
|
105
|
-
console.error(`❌ Failed to load ClickHouse driver:`, error.message);
|
|
106
|
-
return null;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// For other drivers, return null and prompt for installation
|
|
111
|
-
console.warn(`⚠️ Driver "${name}" not loaded. To use this driver, install required package:`);
|
|
112
|
-
|
|
113
|
-
const packageMap = {
|
|
114
|
-
postgresql: 'pg',
|
|
115
|
-
postgres: 'pg',
|
|
116
|
-
pg: 'pg',
|
|
117
|
-
sqlite: 'sqlite3',
|
|
118
|
-
sqlite3: 'sqlite3',
|
|
119
|
-
mongodb: 'mongodb',
|
|
120
|
-
mongo: 'mongodb',
|
|
121
|
-
redis: 'redis',
|
|
122
|
-
mssql: 'mssql',
|
|
123
|
-
sqlserver: 'mssql',
|
|
124
|
-
oracle: 'oracledb',
|
|
125
|
-
cockroachdb: 'pg', // CockroachDB uses PostgreSQL driver
|
|
126
|
-
cockroach: 'pg', // CockroachDB uses PostgreSQL driver
|
|
127
|
-
clickhouse: '@clickhouse/client' // ClickHouse client package
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
if (packageMap[normalizedName]) {
|
|
131
|
-
console.warn(` npm install ${packageMap[normalizedName]}`);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return null;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Check if driver exists
|
|
138
|
-
export function hasDriver(name) {
|
|
139
|
-
const normalizedName = name.toLowerCase();
|
|
140
|
-
return !!drivers[normalizedName];
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// Get all available driver names
|
|
144
|
-
export function getAvailableDrivers() {
|
|
145
|
-
return Object.keys(driverPaths);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Register custom driver
|
|
149
|
-
export function registerDriver(name, driverClass) {
|
|
150
|
-
const normalizedName = name.toLowerCase();
|
|
151
|
-
if (drivers[normalizedName]) {
|
|
152
|
-
console.warn(`⚠️ Driver "${name}" is already registered, overriding existing driver`);
|
|
153
|
-
}
|
|
154
|
-
drivers[normalizedName] = driverClass;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// Remove registered driver
|
|
158
|
-
export function unregisterDriver(name) {
|
|
159
|
-
const normalizedName = name.toLowerCase();
|
|
160
|
-
if (drivers[normalizedName]) {
|
|
161
|
-
delete drivers[normalizedName];
|
|
162
|
-
} else {
|
|
163
|
-
console.warn(`⚠️ Driver "${name}" not found, nothing to unregister`);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// Preload all drivers
|
|
168
|
-
export async function preloadDrivers() {
|
|
169
|
-
const driverNames = getAvailableDrivers();
|
|
170
|
-
const promises = driverNames.map(async (name) => {
|
|
171
|
-
try {
|
|
172
|
-
await getDriver(name);
|
|
173
|
-
} catch (error) {
|
|
174
|
-
console.error(`❌ Failed to preload driver "${name}":`, error.message);
|
|
175
|
-
}
|
|
176
|
-
});
|
|
177
|
-
await Promise.all(promises);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// Clear driver cache
|
|
181
|
-
export function clearDriverCache() {
|
|
182
|
-
drivers.clear();
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// On-demand export of individual drivers
|
|
186
|
-
export async function getMySQLDriver() {
|
|
187
|
-
return await getDriver('mysql');
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
export async function getPostgreSQLDriver() {
|
|
191
|
-
return await getDriver('postgresql');
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
export async function getSQLiteDriver() {
|
|
195
|
-
return await getDriver('sqlite');
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
export async function getMongoDBDriver() {
|
|
199
|
-
return await getDriver('mongodb');
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
export async function getMSSQLDriver() {
|
|
203
|
-
return await getDriver('mssql');
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
export async function getOracleDriver() {
|
|
207
|
-
return await getDriver('oracle');
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// New: Export CockroachDB driver (environment variable controlled)
|
|
211
|
-
export async function getCockroachDBDriver() {
|
|
212
|
-
// Check if CockroachDB support is enabled
|
|
213
|
-
if (process.env.ENABLE_COCKROACHDB !== 'true') {
|
|
214
|
-
console.warn(`⚠️ CockroachDB driver is disabled. Set ENABLE_COCKROACHDB=true to enable.`);
|
|
215
|
-
return null;
|
|
216
|
-
}
|
|
217
|
-
return await getDriver('cockroachdb');
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
// New: Export ClickHouse driver (environment variable controlled)
|
|
221
|
-
export async function getClickHouseDriver() {
|
|
222
|
-
// Check if ClickHouse support is enabled
|
|
223
|
-
if (process.env.ENABLE_CLICKHOUSE !== 'true') {
|
|
224
|
-
console.warn(`⚠️ ClickHouse driver is disabled. Set ENABLE_CLICKHOUSE=true to enable.`);
|
|
225
|
-
return null;
|
|
226
|
-
}
|
|
227
|
-
return await getDriver('clickhouse');
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
// New: Export Redis driver
|
|
231
|
-
export async function getRedisDriver() {
|
|
232
|
-
return await getDriver('redis');
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// New: Export all drivers as an object
|
|
236
|
-
export async function getAllDrivers() {
|
|
237
|
-
const driverNames = getAvailableDrivers();
|
|
238
|
-
const driversObj = {};
|
|
239
|
-
|
|
240
|
-
for (const name of driverNames) {
|
|
241
|
-
try {
|
|
242
|
-
const driver = await getDriver(name);
|
|
243
|
-
if (driver) {
|
|
244
|
-
driversObj[name] = driver;
|
|
245
|
-
}
|
|
246
|
-
} catch (error) {
|
|
247
|
-
console.warn(`⚠️ Failed to load driver "${name}":`, error.message);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
return driversObj;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// New: Check if specific driver is available
|
|
255
|
-
export async function isDriverAvailable(name) {
|
|
256
|
-
try {
|
|
257
|
-
const driver = await getDriver(name);
|
|
258
|
-
return driver !== null;
|
|
259
|
-
} catch (error) {
|
|
260
|
-
return false;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// New: Get driver with fallback
|
|
265
|
-
export async function getDriverWithFallback(name, fallbackName = 'mysql') {
|
|
266
|
-
const driver = await getDriver(name);
|
|
267
|
-
if (driver) {
|
|
268
|
-
return driver;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
console.warn(`⚠️ Driver "${name}" not available, falling back to "${fallbackName}"`);
|
|
272
|
-
return await getDriver(fallbackName);
|
|
273
|
-
}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license MIT
|
|
3
|
-
* Copyright (c) 2026-present AetherFramework Contributors.
|
|
4
|
-
* SPDX-License-Identifier: MIT
|
|
5
|
-
* @module @aetherframework/database/drivers/mongodb-driver
|
|
6
|
-
*/
|
|
7
|
-
import { MongoClient } from 'mongodb';
|
|
8
|
-
|
|
9
|
-
class MongoDBDriver {
|
|
10
|
-
constructor(config) {
|
|
11
|
-
this.config = config;
|
|
12
|
-
this.client = null;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
async connect(config) {
|
|
16
|
-
const url = `mongodb://${config.user}:${config.password}@${config.host}:${config.port}/${config.database}?authSource=${config.authSource || 'admin'}`;
|
|
17
|
-
this.client = new MongoClient(url, {
|
|
18
|
-
useNewUrlParser: true,
|
|
19
|
-
useUnifiedTopology: true,
|
|
20
|
-
maxPoolSize: config.pool?.max || 10,
|
|
21
|
-
minPoolSize: config.pool?.min || 2,
|
|
22
|
-
maxIdleTimeMS: config.pool?.idleTimeout || 30000,
|
|
23
|
-
serverSelectionTimeoutMS: config.pool?.acquireTimeout || 10000
|
|
24
|
-
});
|
|
25
|
-
await this.client.connect();
|
|
26
|
-
return this.client.db(config.database);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
async query(connection, collectionName, query = {}, options = {}) {
|
|
30
|
-
const collection = connection.collection(collectionName);
|
|
31
|
-
const cursor = collection.find(query, options);
|
|
32
|
-
const rows = await cursor.toArray();
|
|
33
|
-
return { rows, rowCount: rows.length };
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async execute(connection, collectionName, operation, data, options = {}) {
|
|
37
|
-
const collection = connection.collection(collectionName);
|
|
38
|
-
let result;
|
|
39
|
-
|
|
40
|
-
switch (operation) {
|
|
41
|
-
case 'insert':
|
|
42
|
-
result = await collection.insertOne(data, options);
|
|
43
|
-
return { insertedId: result.insertedId, insertedCount: result.insertedCount };
|
|
44
|
-
case 'update':
|
|
45
|
-
result = await collection.updateOne(data.filter, data.update, options);
|
|
46
|
-
return { matchedCount: result.matchedCount, modifiedCount: result.modifiedCount };
|
|
47
|
-
case 'delete':
|
|
48
|
-
result = await collection.deleteOne(data.filter, options);
|
|
49
|
-
return { deletedCount: result.deletedCount };
|
|
50
|
-
default:
|
|
51
|
-
throw new Error(`Unsupported MongoDB operation: ${operation}`);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
async beginTransaction(connection) {
|
|
56
|
-
const session = this.client.startSession();
|
|
57
|
-
session.startTransaction();
|
|
58
|
-
return session;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
async commitTransaction(session) {
|
|
62
|
-
await session.commitTransaction();
|
|
63
|
-
session.endSession();
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
async rollbackTransaction(session) {
|
|
67
|
-
await session.abortTransaction();
|
|
68
|
-
session.endSession();
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
async close() {
|
|
72
|
-
if (this.client) {
|
|
73
|
-
await this.client.close();
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
async healthCheck(connection) {
|
|
78
|
-
try {
|
|
79
|
-
await connection.command({ ping: 1 });
|
|
80
|
-
return true;
|
|
81
|
-
} catch (error) {
|
|
82
|
-
return false;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export default MongoDBDriver;
|