@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,407 +0,0 @@
1
- /**
2
- * @license MIT
3
- * Copyright (c) 2026-present AetherFramework Contributors.
4
- * SPDX-License-Identifier: MIT
5
- * @module @aetherframework/database/plugin/CachePlugin
6
- */
7
- import crypto from 'crypto';
8
- import { BasePlugin } from './BasePlugin.js';
9
-
10
- /**
11
- * Cache Plugin - Provides query caching functionality with multiple cache drivers
12
- * Supports Redis, Memcached, Memory, and custom cache implementations
13
- */
14
- export class CachePlugin extends BasePlugin {
15
- constructor(queryBuilder) {
16
- super(queryBuilder);
17
- this.cacheDriver = null;
18
- this.cacheEnabled = false;
19
- this.cacheConfig = {
20
- defaultTtl: 300, // 5 minutes
21
- prefix: 'query:',
22
- tagsEnabled: false,
23
- compression: false
24
- };
25
- this.cacheStats = {
26
- hits: 0,
27
- misses: 0,
28
- sets: 0,
29
- deletes: 0
30
- };
31
- }
32
-
33
- _registerMethods() {
34
- // Register cache methods to QueryBuilder
35
- this.queryBuilder.setCacheDriver = this.setCacheDriver.bind(this);
36
- this.queryBuilder.cache = this.cache.bind(this);
37
- this.queryBuilder.cacheWithTags = this.cacheWithTags.bind(this);
38
- this.queryBuilder.executeWithCache = this.executeWithCache.bind(this);
39
- this.queryBuilder.clearTableCache = this.clearTableCache.bind(this);
40
- this.queryBuilder.clearCache = this.clearCache.bind(this);
41
- this.queryBuilder.getCacheStats = this.getCacheStats.bind(this);
42
- this.queryBuilder.generateCacheKey = this.generateCacheKey.bind(this);
43
- this.queryBuilder.cacheTags = this.cacheTags.bind(this);
44
- this.queryBuilder.remember = this.remember.bind(this);
45
- }
46
-
47
- /**
48
- * Set cache driver
49
- * @param {Object} cacheDriver - Cache driver instance
50
- * @param {Object} options - Cache configuration
51
- * @returns {QueryBuilder} Query builder instance
52
- */
53
- setCacheDriver(cacheDriver, options = {}) {
54
- this.cacheDriver = cacheDriver;
55
- this.cacheConfig = {
56
- ...this.cacheConfig,
57
- ...options
58
- };
59
- this.cacheEnabled = true;
60
-
61
- // Validate cache driver interface
62
- this._validateCacheDriver();
63
-
64
- return this.queryBuilder;
65
- }
66
-
67
- /**
68
- * Enable query caching
69
- * @param {number} ttl - Time to live in seconds
70
- * @param {string} key - Custom cache key
71
- * @returns {QueryBuilder} Query builder instance
72
- */
73
- cache(ttl = null, key = null) {
74
- if (!this.cacheEnabled) {
75
- throw new Error('Cache is not enabled. Call setCacheDriver() first.');
76
- }
77
-
78
- this.queryBuilder.query.cache = true;
79
- this.queryBuilder.query.cacheTtl = ttl || this.cacheConfig.defaultTtl;
80
- this.queryBuilder.query.cacheKey = key || this.generateCacheKey();
81
- this.queryBuilder.query.cacheTags = [];
82
-
83
- return this.queryBuilder;
84
- }
85
-
86
- /**
87
- * Enable caching with tags
88
- * @param {number} ttl - Time to live in seconds
89
- * @param {Array} tags - Cache tags
90
- * @returns {QueryBuilder} Query builder instance
91
- */
92
- cacheWithTags(ttl = 300, tags = []) {
93
- if (!this.cacheConfig.tagsEnabled) {
94
- console.warn('Cache tags are not enabled in cache configuration');
95
- }
96
-
97
- this.queryBuilder.query.cache = true;
98
- this.queryBuilder.query.cacheTtl = ttl;
99
- this.queryBuilder.query.cacheTags = tags;
100
- this.queryBuilder.query.cacheKey = this.generateCacheKey();
101
-
102
- return this.queryBuilder;
103
- }
104
-
105
- /**
106
- * Add tags to cache
107
- * @param {...string} tags - Cache tags
108
- * @returns {QueryBuilder} Query builder instance
109
- */
110
- cacheTags(...tags) {
111
- if (!this.queryBuilder.query.cacheTags) {
112
- this.queryBuilder.query.cacheTags = [];
113
- }
114
- this.queryBuilder.query.cacheTags.push(...tags);
115
- return this.queryBuilder;
116
- }
117
-
118
- /**
119
- * Generate cache key from query
120
- * @returns {string} Cache key
121
- */
122
- generateCacheKey() {
123
- const { sql, bindings } = this.queryBuilder.toSQL();
124
- const queryHash = crypto
125
- .createHash('sha256')
126
- .update(sql + JSON.stringify(bindings) + this.queryBuilder.dialect)
127
- .digest('hex');
128
-
129
- const keyParts = [
130
- this.cacheConfig.prefix,
131
- this.queryBuilder.tableName,
132
- this.queryBuilder.query.type,
133
- queryHash
134
- ];
135
-
136
- return keyParts.join(':');
137
- }
138
-
139
- /**
140
- * Execute query with caching
141
- * @returns {Promise<Object>} Query result
142
- */
143
- async executeWithCache() {
144
- if (!this.queryBuilder.query.cache || !this.cacheDriver) {
145
- return this.queryBuilder.execute();
146
- }
147
-
148
- // Determine TTL based on query type
149
- let ttl = this.queryBuilder.query.cacheTtl || this.cacheConfig.defaultTtl;
150
- if (this.queryBuilder.query.type === 'select') {
151
- ttl = Math.max(ttl, 600); // At least 10 minutes for SELECT
152
- } else if (
153
- this.queryBuilder.query.type === 'insert' ||
154
- this.queryBuilder.query.type === 'update' ||
155
- this.queryBuilder.query.type === 'delete'
156
- ) {
157
- ttl = Math.min(ttl, 30); // Maximum 30 seconds for DML
158
- }
159
-
160
- const cacheKey = this.queryBuilder.query.cacheKey;
161
-
162
- // Try to get from cache
163
- try {
164
- const cached = await this.cacheDriver.get(cacheKey);
165
- if (cached !== null && cached !== undefined) {
166
- this.cacheStats.hits++;
167
- this.queryBuilder.emit('cache:hit', {
168
- key: cacheKey,
169
- ttl: ttl
170
- });
171
-
172
- // Parse cached data
173
- const result = typeof cached === 'string' ? JSON.parse(cached) : cached;
174
-
175
- // Add cache metadata
176
- if (result && typeof result === 'object') {
177
- result._cache = {
178
- hit: true,
179
- key: cacheKey,
180
- ttl: ttl,
181
- cachedAt: new Date().toISOString()
182
- };
183
- }
184
-
185
- return result;
186
- }
187
- } catch (error) {
188
- console.warn('Cache get error:', error.message);
189
- }
190
-
191
- // Cache miss - execute query
192
- this.cacheStats.misses++;
193
- const result = await this.queryBuilder.execute();
194
-
195
- // Store in cache
196
- try {
197
- const cacheValue = JSON.stringify(result);
198
-
199
- if (this.queryBuilder.query.cacheTags?.length > 0 &&
200
- this.cacheDriver.setWithTags) {
201
- await this.cacheDriver.setWithTags(
202
- cacheKey,
203
- cacheValue,
204
- ttl,
205
- this.queryBuilder.query.cacheTags
206
- );
207
- } else {
208
- await this.cacheDriver.set(cacheKey, cacheValue, ttl);
209
- }
210
-
211
- this.cacheStats.sets++;
212
- this.queryBuilder.emit('cache:miss', {
213
- key: cacheKey,
214
- ttl: ttl
215
- });
216
-
217
- // Add cache metadata to result
218
- if (result && typeof result === 'object') {
219
- result._cache = {
220
- hit: false,
221
- key: cacheKey,
222
- ttl: ttl,
223
- cachedAt: new Date().toISOString()
224
- };
225
- }
226
- } catch (error) {
227
- console.warn('Cache set error:', error.message);
228
- }
229
-
230
- return result;
231
- }
232
-
233
- /**
234
- * Remember pattern - get from cache or execute and cache
235
- * @param {string} key - Cache key
236
- * @param {number} ttl - Time to live in seconds
237
- * @param {Function} callback - Function to execute if not cached
238
- * @returns {Promise<*>} Cached or fresh result
239
- */
240
- async remember(key, ttl, callback) {
241
- if (!this.cacheEnabled || !this.cacheDriver) {
242
- return callback();
243
- }
244
-
245
- const cacheKey = `${this.cacheConfig.prefix}${key}`;
246
-
247
- try {
248
- const cached = await this.cacheDriver.get(cacheKey);
249
- if (cached !== null && cached !== undefined) {
250
- this.cacheStats.hits++;
251
- return typeof cached === 'string' ? JSON.parse(cached) : cached;
252
- }
253
- } catch (error) {
254
- console.warn('Cache get error:', error.message);
255
- }
256
-
257
- // Execute callback and cache result
258
- const result = await callback();
259
-
260
- try {
261
- await this.cacheDriver.set(cacheKey, JSON.stringify(result), ttl);
262
- this.cacheStats.sets++;
263
- } catch (error) {
264
- console.warn('Cache set error:', error.message);
265
- }
266
-
267
- return result;
268
- }
269
-
270
- /**
271
- * Clear cache for this table
272
- * @param {string} pattern - Cache key pattern
273
- * @returns {Promise<void>}
274
- */
275
- async clearTableCache(pattern = null) {
276
- if (!this.cacheDriver) {
277
- return;
278
- }
279
-
280
- const cachePattern = pattern || `query:${this.queryBuilder.tableName}:*`;
281
-
282
- try {
283
- if (this.cacheDriver.clearPattern) {
284
- await this.cacheDriver.clearPattern(cachePattern);
285
- } else if (this.cacheDriver.del) {
286
- // For Redis-like drivers
287
- const keys = await this.cacheDriver.keys(cachePattern);
288
- if (keys.length > 0) {
289
- await this.cacheDriver.del(...keys);
290
- }
291
- }
292
-
293
- this.cacheStats.deletes++;
294
- this.queryBuilder.emit('cache:cleared', { pattern: cachePattern });
295
- } catch (error) {
296
- console.error('Failed to clear cache:', error.message);
297
- }
298
- }
299
-
300
- /**
301
- * Clear specific cache key
302
- * @param {string} key - Cache key to clear
303
- * @returns {Promise<void>}
304
- */
305
- async clearCache(key = null) {
306
- if (!this.cacheDriver) {
307
- return;
308
- }
309
-
310
- const cacheKey = key || this.queryBuilder.query.cacheKey;
311
- if (!cacheKey) {
312
- return;
313
- }
314
-
315
- try {
316
- await this.cacheDriver.del(cacheKey);
317
- this.cacheStats.deletes++;
318
- this.queryBuilder.emit('cache:cleared', { key: cacheKey });
319
- } catch (error) {
320
- console.error('Failed to clear cache:', error.message);
321
- }
322
- }
323
-
324
- /**
325
- * Clear cache by tags
326
- * @param {...string} tags - Cache tags
327
- * @returns {Promise<void>}
328
- */
329
- async clearCacheByTags(...tags) {
330
- if (!this.cacheDriver || !this.cacheDriver.clearByTags) {
331
- console.warn('Cache driver does not support tag-based clearing');
332
- return;
333
- }
334
-
335
- try {
336
- await this.cacheDriver.clearByTags(...tags);
337
- this.cacheStats.deletes++;
338
- this.queryBuilder.emit('cache:cleared:tags', { tags });
339
- } catch (error) {
340
- console.error('Failed to clear cache by tags:', error.message);
341
- }
342
- }
343
-
344
- /**
345
- * Get cache statistics
346
- * @returns {Object} Cache statistics
347
- */
348
- getCacheStats() {
349
- return {
350
- ...this.cacheStats,
351
- enabled: this.cacheEnabled,
352
- driver: this.cacheDriver?.constructor?.name || 'none',
353
- config: this.cacheConfig
354
- };
355
- }
356
-
357
- /**
358
- * Reset cache statistics
359
- * @returns {Object} Reset statistics
360
- */
361
- resetCacheStats() {
362
- const oldStats = { ...this.cacheStats };
363
- this.cacheStats = { hits: 0, misses: 0, sets: 0, deletes: 0 };
364
- return oldStats;
365
- }
366
-
367
- /**
368
- * Validate cache driver interface
369
- * @private
370
- */
371
- _validateCacheDriver() {
372
- const requiredMethods = ['get', 'set', 'del'];
373
- const missingMethods = [];
374
-
375
- for (const method of requiredMethods) {
376
- if (typeof this.cacheDriver[method] !== 'function') {
377
- missingMethods.push(method);
378
- }
379
- }
380
-
381
- if (missingMethods.length > 0) {
382
- throw new Error(
383
- `Cache driver missing required methods: ${missingMethods.join(', ')}`
384
- );
385
- }
386
- }
387
-
388
- /**
389
- * Get plugin metadata
390
- * @returns {Object} Plugin metadata
391
- */
392
- getMetadata() {
393
- return {
394
- name: 'CachePlugin',
395
- version: '1.0.0',
396
- description: 'Advanced query caching with multiple driver support',
397
- features: [
398
- 'Multi-driver support (Redis, Memcached, Memory)',
399
- 'Tag-based caching',
400
- 'Automatic TTL management',
401
- 'Cache statistics',
402
- 'Pattern-based cache clearing'
403
- ],
404
- drivers: ['redis', 'memcached', 'memory', 'custom']
405
- };
406
- }
407
- }