@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.
Files changed (44) hide show
  1. package/package.json +1 -2
  2. package/src/DatabaseManager.js +0 -565
  3. package/src/core/ConnectionManager.js +0 -351
  4. package/src/core/DatabaseFactory.js +0 -188
  5. package/src/core/MongoQueryBuilder.js +0 -576
  6. package/src/core/PluginManager.js +0 -968
  7. package/src/core/QueryBuilder.js +0 -4398
  8. package/src/core/TransactionManager.js +0 -40
  9. package/src/drivers/clickhouse-driver.js +0 -272
  10. package/src/drivers/index.js +0 -273
  11. package/src/drivers/mongodb-driver.js +0 -87
  12. package/src/drivers/mssql-driver.js +0 -117
  13. package/src/drivers/mysql-driver.js +0 -169
  14. package/src/drivers/oracle-driver.js +0 -101
  15. package/src/drivers/postgres-driver.js +0 -234
  16. package/src/drivers/redis-driver.js +0 -52
  17. package/src/drivers/sqlite-driver.js +0 -67
  18. package/src/middleware/connection-pool.js +0 -455
  19. package/src/middleware/performance-monitor.js +0 -652
  20. package/src/middleware/query-cache.js +0 -500
  21. package/src/middleware/query-logger.js +0 -262
  22. package/src/plugins/AuditPlugin.js +0 -447
  23. package/src/plugins/BasePlugin.js +0 -418
  24. package/src/plugins/BatchOperationPlugin.js +0 -165
  25. package/src/plugins/CachePlugin.js +0 -407
  26. package/src/plugins/CtePlugin.js +0 -523
  27. package/src/plugins/DistributedPlugin.js +0 -543
  28. package/src/plugins/EncryptionPlugin.js +0 -211
  29. package/src/plugins/FullTextSearchPlugin.js +0 -164
  30. package/src/plugins/GeospatialPlugin.js +0 -219
  31. package/src/plugins/GraphQLPlugin.js +0 -162
  32. package/src/plugins/HookPlugin.js +0 -211
  33. package/src/plugins/JsonPlugin.js +0 -366
  34. package/src/plugins/OptimisticLockPlugin.js +0 -374
  35. package/src/plugins/PerformancePlugin.js +0 -175
  36. package/src/plugins/ResiliencePlugin.js +0 -114
  37. package/src/plugins/ShardingPlugin.js +0 -227
  38. package/src/plugins/SoftDeletePlugin.js +0 -258
  39. package/src/plugins/SyncPlugin.js +0 -373
  40. package/src/plugins/VersioningPlugin.js +0 -314
  41. package/src/plugins/WindowFunctionPlugin.js +0 -343
  42. package/src/utils/config-loader.js +0 -632
  43. package/src/utils/error-handler.js +0 -724
  44. package/src/utils/migration-runner.js +0 -1066
@@ -1,366 +0,0 @@
1
- /**
2
- * @license MIT
3
- * Copyright (c) 2026-present AetherFramework Contributors.
4
- * SPDX-License-Identifier: MIT
5
- * @module @aetherframework/database/plugin/JsonPlugin
6
- */
7
- import { BasePlugin } from './BasePlugin.js';
8
-
9
- /**
10
- * Json Plugin - Provides database-agnostic JSON field operations.
11
- * Translates JSON methods to the appropriate SQL functions for the current dialect.
12
- */
13
- export class JsonPlugin extends BasePlugin {
14
- constructor(queryBuilder) {
15
- super(queryBuilder);
16
- }
17
-
18
- _registerMethods() {
19
- // Register JSON methods to QueryBuilder
20
- this.queryBuilder.whereJsonContains = this.whereJsonContains.bind(this);
21
- this.queryBuilder.whereJsonLength = this.whereJsonLength.bind(this);
22
- this.queryBuilder.whereJsonHasKey = this.whereJsonHasKey.bind(this);
23
- this.queryBuilder.jsonSet = this.jsonSet.bind(this);
24
- this.queryBuilder.selectJson = this.selectJson.bind(this);
25
- this.queryBuilder.jsonExtract = this.jsonExtract.bind(this); // 修复:添加 jsonExtract 方法
26
- this.queryBuilder.jsonInsert = this.jsonInsert.bind(this);
27
- this.queryBuilder.jsonReplace = this.jsonReplace.bind(this);
28
- this.queryBuilder.jsonRemove = this.jsonRemove.bind(this);
29
- this.queryBuilder.jsonMerge = this.jsonMerge.bind(this);
30
- this.queryBuilder.whereJsonContainsPath = this.whereJsonContainsPath.bind(this);
31
- }
32
-
33
- /**
34
- * WHERE clause: Check if a JSON column contains a specific value.
35
- * @param {string} column - The JSON column name.
36
- * @param {*} value - The value to check for.
37
- * @returns {QueryBuilder} The QueryBuilder instance for chaining.
38
- */
39
- whereJsonContains(column, value) {
40
- const wrappedColumn = this.queryBuilder.wrapColumn(column);
41
- const jsonValue = JSON.stringify(value);
42
-
43
- switch (this.queryBuilder.dialect) {
44
- case 'mysql':
45
- case 'mariadb':
46
- this.queryBuilder.whereRaw(`JSON_CONTAINS(${wrappedColumn}, ?)`, [jsonValue]);
47
- break;
48
- case 'postgresql':
49
- case 'postgres':
50
- case 'pg':
51
- case 'cockroachdb':
52
- this.queryBuilder.whereRaw(`${wrappedColumn} @> ?::jsonb`, [jsonValue]);
53
- break;
54
- default:
55
- throw new Error(`JSON_CONTAINS operation not supported for dialect: ${this.queryBuilder.dialect}`);
56
- }
57
- return this.queryBuilder;
58
- }
59
-
60
- /**
61
- * WHERE clause: Compare the length of a JSON array.
62
- * @param {string} column - The JSON column name.
63
- * @param {string} operator - Comparison operator (>, <, =, >=, <=).
64
- * @param {number} value - The length value to compare against.
65
- * @returns {QueryBuilder} The QueryBuilder instance for chaining.
66
- */
67
- whereJsonLength(column, operator, value) {
68
- const wrappedColumn = this.queryBuilder.wrapColumn(column);
69
-
70
- switch (this.queryBuilder.dialect) {
71
- case 'mysql':
72
- case 'mariadb':
73
- this.queryBuilder.whereRaw(`JSON_LENGTH(${wrappedColumn}) ${operator} ?`, [value]);
74
- break;
75
- case 'postgresql':
76
- case 'postgres':
77
- case 'pg':
78
- case 'cockroachdb':
79
- this.queryBuilder.whereRaw(`jsonb_array_length(${wrappedColumn}) ${operator} ?`, [value]);
80
- break;
81
- default:
82
- throw new Error(`JSON_LENGTH operation not supported for dialect: ${this.queryBuilder.dialect}`);
83
- }
84
- return this.queryBuilder;
85
- }
86
-
87
- /**
88
- * WHERE clause: Check if a JSON column has a specific key.
89
- * @param {string} column - The JSON column name.
90
- * @param {string} key - The key to check for.
91
- * @returns {QueryBuilder} The QueryBuilder instance for chaining.
92
- */
93
- whereJsonHasKey(column, key) {
94
- const wrappedColumn = this.queryBuilder.wrapColumn(column);
95
-
96
- switch (this.queryBuilder.dialect) {
97
- case 'mysql':
98
- case 'mariadb':
99
- this.queryBuilder.whereRaw(`JSON_CONTAINS_PATH(${wrappedColumn}, 'one', ?)`, [`$.${key}`]);
100
- break;
101
- case 'postgresql':
102
- case 'postgres':
103
- case 'pg':
104
- case 'cockroachdb':
105
- this.queryBuilder.whereRaw(`${wrappedColumn} ?? ?`, [key]);
106
- break;
107
- default:
108
- throw new Error(`JSON_HAS_KEY operation not supported for dialect: ${this.queryBuilder.dialect}`);
109
- }
110
- return this.queryBuilder;
111
- }
112
-
113
- /**
114
- * SET clause: Update a specific path within a JSON column.
115
- * @param {string} column - The JSON column name.
116
- * @param {string} path - The JSON path (e.g., 'user.name').
117
- * @param {*} value - The value to set at the path.
118
- * @returns {QueryBuilder} The QueryBuilder instance for chaining.
119
- */
120
- jsonSet(column, path, value) {
121
- if (!this.queryBuilder.query.jsonUpdates) {
122
- this.queryBuilder.query.jsonUpdates = [];
123
- }
124
- this.queryBuilder.query.jsonUpdates.push({ column, path, value, operation: 'set' });
125
- return this.queryBuilder;
126
- }
127
-
128
- /**
129
- * SELECT clause: Extract a value from a JSON column.
130
- * @param {string} column - The JSON column name.
131
- * @param {string} path - The JSON path to extract (e.g., 'user.name').
132
- * @param {string} alias - Optional alias for the selected value.
133
- * @returns {QueryBuilder} The QueryBuilder instance for chaining.
134
- */
135
- selectJson(column, path, alias = null) {
136
- const wrappedColumn = this.queryBuilder.wrapColumn(column);
137
- const jsonPath = `$.${path}`;
138
- let selectExpr;
139
-
140
- switch (this.queryBuilder.dialect) {
141
- case 'mysql':
142
- case 'mariadb':
143
- selectExpr = `JSON_UNQUOTE(JSON_EXTRACT(${wrappedColumn}, ?))`;
144
- this.queryBuilder.bindings.push(jsonPath);
145
- break;
146
- case 'postgresql':
147
- case 'postgres':
148
- case 'pg':
149
- case 'cockroachdb':
150
- selectExpr = `${wrappedColumn}->>?`;
151
- this.queryBuilder.bindings.push(path);
152
- break;
153
- case 'mssql':
154
- case 'sqlserver':
155
- selectExpr = `JSON_VALUE(${wrappedColumn}, ?)`;
156
- this.queryBuilder.bindings.push(`$${path}`);
157
- break;
158
- default:
159
- throw new Error(`JSON_EXTRACT operation not supported for dialect: ${this.queryBuilder.dialect}`);
160
- }
161
-
162
- const finalAlias = alias || `${column}_${path.replace(/\./g, '_')}`;
163
- const finalSelectExpr = `${selectExpr} AS ${finalAlias}`;
164
-
165
- if (this.queryBuilder.query.columns.length === 0 || this.queryBuilder.query.columns === '*') {
166
- this.queryBuilder.query.columns = [finalSelectExpr];
167
- } else {
168
- this.queryBuilder.query.columns.push(finalSelectExpr);
169
- }
170
-
171
- return this.queryBuilder;
172
- }
173
-
174
- /**
175
- * Extract a value from a JSON column (alias for selectJson)
176
- * @param {string} column - The JSON column name
177
- * @param {string} path - The JSON path to extract
178
- * @param {string} [alias] - Optional alias for the extracted value
179
- * @returns {QueryBuilder} The QueryBuilder instance for chaining
180
- */
181
- jsonExtract(column, path, alias = null) {
182
- // 直接调用 selectJson 方法,因为功能相同
183
- return this.selectJson(column, path, alias);
184
- }
185
-
186
- /**
187
- * WHERE clause: Check if a JSON column contains a specific path.
188
- * @param {string} column - The JSON column name.
189
- * @param {string} path - The JSON path to check (e.g., 'user.address.city').
190
- * @returns {QueryBuilder} The QueryBuilder instance for chaining.
191
- */
192
- whereJsonContainsPath(column, path) {
193
- const wrappedColumn = this.queryBuilder.wrapColumn(column);
194
- const jsonPath = `$.${path}`;
195
-
196
- switch (this.queryBuilder.dialect) {
197
- case 'mysql':
198
- case 'mariadb':
199
- this.queryBuilder.whereRaw(`JSON_CONTAINS_PATH(${wrappedColumn}, 'one', ?)`, [jsonPath]);
200
- break;
201
- case 'postgresql':
202
- case 'postgres':
203
- case 'pg':
204
- case 'cockroachdb':
205
- this.queryBuilder.whereRaw(`${wrappedColumn} ?? ?`, [path]);
206
- break;
207
- default:
208
- throw new Error(`JSON_CONTAINS_PATH operation not supported for dialect: ${this.queryBuilder.dialect}`);
209
- }
210
- return this.queryBuilder;
211
- }
212
-
213
- // --- The following methods would require modifying the SQL building process ---
214
- // They are registered but their implementation would need to integrate with
215
- // the QueryBuilder's `toSQL()` or `buildUpdateSQL()` methods.
216
-
217
- /**
218
- * JSON_INSERT operation (insert if path does not exist).
219
- * @param {string} column - The JSON column name.
220
- * @param {string} path - The JSON path.
221
- * @param {*} value - The value to insert.
222
- * @returns {QueryBuilder} The QueryBuilder instance for chaining.
223
- */
224
- jsonInsert(column, path, value) {
225
- if (!this.queryBuilder.query.jsonUpdates) {
226
- this.queryBuilder.query.jsonUpdates = [];
227
- }
228
- this.queryBuilder.query.jsonUpdates.push({ column, path, value, operation: 'json_insert' });
229
- return this.queryBuilder;
230
- }
231
-
232
- /**
233
- * JSON_REPLACE operation (replace if path exists).
234
- * @param {string} column - The JSON column name.
235
- * @param {string} path - The JSON path.
236
- * @param {*} value - The value to replace with.
237
- * @returns {QueryBuilder} The QueryBuilder instance for chaining.
238
- */
239
- jsonReplace(column, path, value) {
240
- if (!this.queryBuilder.query.jsonUpdates) {
241
- this.queryBuilder.query.jsonUpdates = [];
242
- }
243
- this.queryBuilder.query.jsonUpdates.push({ column, path, value, operation: 'json_replace' });
244
- return this.queryBuilder;
245
- }
246
-
247
- /**
248
- * JSON_REMOVE operation.
249
- * @param {string} column - The JSON column name.
250
- * @param {string} path - The JSON path to remove.
251
- * @returns {QueryBuilder} The QueryBuilder instance for chaining.
252
- */
253
- jsonRemove(column, path) {
254
- if (!this.queryBuilder.query.jsonUpdates) {
255
- this.queryBuilder.query.jsonUpdates = [];
256
- }
257
- this.queryBuilder.query.jsonUpdates.push({ column, path, operation: 'json_remove' });
258
- return this.queryBuilder;
259
- }
260
-
261
- /**
262
- * JSON_MERGE operation (merge two JSON documents).
263
- * @param {string} column - The JSON column name.
264
- * @param {Object|Array} value - The JSON value to merge.
265
- * @returns {QueryBuilder} The QueryBuilder instance for chaining.
266
- */
267
- jsonMerge(column, value) {
268
- if (!this.queryBuilder.query.jsonUpdates) {
269
- this.queryBuilder.query.jsonUpdates = [];
270
- }
271
- this.queryBuilder.query.jsonUpdates.push({ column, value, operation: 'json_merge' });
272
- return this.queryBuilder;
273
- }
274
-
275
- /**
276
- * Helper method to be called by QueryBuilder when building UPDATE SQL for JSON operations.
277
- * This should be integrated into the main QueryBuilder's `buildUpdateSQL` method.
278
- * @private
279
- */
280
- _buildJsonUpdateClause() {
281
- if (!this.queryBuilder.query.jsonUpdates || this.queryBuilder.query.jsonUpdates.length === 0) {
282
- return '';
283
- }
284
-
285
- const updates = [];
286
- this.queryBuilder.query.jsonUpdates.forEach(update => {
287
- const wrappedColumn = this.queryBuilder.wrapColumn(update.column);
288
- const jsonPath = `$.${update.path}`;
289
- const placeholder = '?';
290
-
291
- switch (update.operation) {
292
- case 'set':
293
- // This is the most common operation, syntax varies by DB
294
- switch (this.queryBuilder.dialect) {
295
- case 'mysql':
296
- case 'mariadb':
297
- updates.push(`${wrappedColumn} = JSON_SET(${wrappedColumn}, ?, ?)`);
298
- this.queryBuilder.bindings.push(jsonPath, JSON.stringify(update.value));
299
- break;
300
- case 'postgresql':
301
- case 'postgres':
302
- case 'pg':
303
- case 'cockroachdb':
304
- updates.push(`${wrappedColumn} = jsonb_set(${wrappedColumn}, ?, ?)`);
305
- this.queryBuilder.bindings.push(`{${update.path.split('.').join(',')}}`, JSON.stringify(update.value));
306
- break;
307
- }
308
- break;
309
- case 'json_insert':
310
- case 'json_replace':
311
- case 'json_remove':
312
- case 'json_merge':
313
- // Implementations for these would follow similar patterns
314
- // For brevity, they are omitted here but would be added in a full implementation.
315
- console.warn(`JSON operation '${update.operation}' not fully implemented in plugin example.`);
316
- break;
317
- }
318
- });
319
-
320
- return updates.join(', ');
321
- }
322
-
323
- /**
324
- * Returns the plugin's capabilities for the current dialect.
325
- * @returns {Object} An object describing supported JSON features.
326
- */
327
- getCapabilities() {
328
- const capabilities = {
329
- jsonContains: false,
330
- jsonLength: false,
331
- jsonHasKey: false,
332
- jsonSet: false,
333
- jsonExtract: false
334
- };
335
-
336
- switch (this.queryBuilder.dialect) {
337
- case 'mysql':
338
- case 'mariadb':
339
- capabilities.jsonContains = true;
340
- capabilities.jsonLength = true;
341
- capabilities.jsonHasKey = true;
342
- capabilities.jsonSet = true;
343
- capabilities.jsonExtract = true;
344
- break;
345
- case 'postgresql':
346
- case 'postgres':
347
- case 'pg':
348
- case 'cockroachdb':
349
- capabilities.jsonContains = true;
350
- capabilities.jsonLength = true;
351
- capabilities.jsonHasKey = true;
352
- capabilities.jsonSet = true;
353
- capabilities.jsonExtract = true;
354
- break;
355
- case 'mssql':
356
- case 'sqlserver':
357
- capabilities.jsonContains = false; // Limited support
358
- capabilities.jsonLength = false;
359
- capabilities.jsonHasKey = false;
360
- capabilities.jsonSet = true; // Via JSON_MODIFY
361
- capabilities.jsonExtract = true; // Via JSON_VALUE
362
- break;
363
- }
364
- return capabilities;
365
- }
366
- }