@onurege3467/zerohelper 8.0.0 → 9.0.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/README.md +292 -612
- package/dist/database/IDatabase.d.ts +77 -0
- package/dist/database/IDatabase.js +10 -0
- package/dist/database/cacheWrapper.d.ts +31 -0
- package/dist/database/cacheWrapper.js +228 -0
- package/dist/database/index.d.ts +11 -0
- package/dist/database/index.js +94 -0
- package/dist/database/json.d.ts +32 -0
- package/dist/database/json.js +210 -0
- package/dist/database/migration.d.ts +21 -0
- package/dist/database/migration.js +97 -0
- package/dist/database/mongodb.d.ts +24 -0
- package/dist/database/mongodb.js +153 -0
- package/dist/database/mysql.d.ts +31 -0
- package/dist/database/mysql.js +385 -0
- package/dist/database/pg.d.ts +30 -0
- package/dist/database/pg.js +300 -0
- package/dist/database/redis.d.ts +23 -0
- package/dist/database/redis.js +157 -0
- package/dist/database/sqlite.d.ts +25 -0
- package/dist/database/sqlite.js +273 -0
- package/dist/database/types.d.ts +76 -0
- package/dist/database/types.js +2 -0
- package/dist/database/zpack.d.ts +59 -0
- package/dist/database/zpack.js +462 -0
- package/dist/functions/index.d.ts +183 -0
- package/dist/functions/index.js +636 -0
- package/dist/functions/temp_isphone.d.ts +1 -0
- package/dist/functions/temp_isphone.js +7 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +45 -0
- package/dist/test.d.ts +1 -0
- package/dist/test.js +55 -0
- package/dist/test_zpack.d.ts +1 -0
- package/dist/test_zpack.js +64 -0
- package/package.json +23 -6
- package/database/IDatabase.js +0 -92
- package/database/cacheWrapper.js +0 -585
- package/database/index.js +0 -72
- package/database/json.js +0 -281
- package/database/migration.js +0 -227
- package/database/mongodb.js +0 -203
- package/database/mysql.js +0 -526
- package/database/pg.js +0 -527
- package/database/redis.js +0 -342
- package/database/sqlite.js +0 -551
- package/functions/index.js +0 -705
- package/index.js +0 -7
package/database/cacheWrapper.js
DELETED
|
@@ -1,585 +0,0 @@
|
|
|
1
|
-
// cacheWrapper.js - Redis@4 ve Memory Cache Uyumlu (Düzeltilmiş)
|
|
2
|
-
const { LRUCache } = require('lru-cache');
|
|
3
|
-
const { createClient } = require('redis');
|
|
4
|
-
|
|
5
|
-
class CacheWrapper {
|
|
6
|
-
constructor(databaseInstance, options = {}) {
|
|
7
|
-
this.db = databaseInstance;
|
|
8
|
-
this.cacheType = options.type || 'memory'; // 'memory' or 'redis'
|
|
9
|
-
this.tableCaches = {};
|
|
10
|
-
|
|
11
|
-
// Redis client için başlangıç değerleri
|
|
12
|
-
this.redisClient = null;
|
|
13
|
-
this.redisAvailable = false;
|
|
14
|
-
|
|
15
|
-
if (this.cacheType === 'redis') {
|
|
16
|
-
this._initRedisCache(options);
|
|
17
|
-
} else {
|
|
18
|
-
this._initMemoryCache(options);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
_initMemoryCache(options) {
|
|
23
|
-
this.cache = new LRUCache({
|
|
24
|
-
max: options.max || 500,
|
|
25
|
-
ttl: options.ttl || 1000 * 60 * 5, // milliseconds
|
|
26
|
-
updateAgeOnGet: options.updateAgeOnGet || false,
|
|
27
|
-
});
|
|
28
|
-
this.redisAvailable = false;
|
|
29
|
-
this.redisClient = null;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async _initRedisCache(options) {
|
|
33
|
-
const redisConfig = {
|
|
34
|
-
socket: {
|
|
35
|
-
host: options.host || '127.0.0.1',
|
|
36
|
-
port: options.port || 6379,
|
|
37
|
-
connectTimeout: options.connectTimeout || 5000,
|
|
38
|
-
},
|
|
39
|
-
password: options.password,
|
|
40
|
-
database: options.db || 0,
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
this.redisClient = createClient(redisConfig);
|
|
44
|
-
this.ttl = options.ttl || 300; // 5 dakika (saniye cinsinden)
|
|
45
|
-
this.keyPrefix = options.keyPrefix || 'db_cache:';
|
|
46
|
-
this.redisAvailable = false;
|
|
47
|
-
|
|
48
|
-
this.redisClient.on('error', (err) => {
|
|
49
|
-
console.warn('Redis Cache Error, memory cache fallback:', err.message);
|
|
50
|
-
this.redisAvailable = false;
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
this.redisClient.on('connect', () => {
|
|
54
|
-
console.log('Redis Cache Connected');
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
this.redisClient.on('ready', () => {
|
|
58
|
-
console.log('Redis Cache Ready');
|
|
59
|
-
this.redisAvailable = true;
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
this.redisClient.on('end', () => {
|
|
63
|
-
console.log('Redis Cache Disconnected');
|
|
64
|
-
this.redisAvailable = false;
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
try {
|
|
68
|
-
await Promise.race([
|
|
69
|
-
this.redisClient.connect(),
|
|
70
|
-
new Promise((_, reject) =>
|
|
71
|
-
setTimeout(() => reject(new Error('Redis connection timeout')), 5000)
|
|
72
|
-
),
|
|
73
|
-
]);
|
|
74
|
-
this.redisAvailable = true;
|
|
75
|
-
} catch (error) {
|
|
76
|
-
console.warn('Redis bağlantısı başarısız, memory cache kullanılacak:', error.message);
|
|
77
|
-
this._initMemoryCache(options);
|
|
78
|
-
if (this.redisClient) {
|
|
79
|
-
this.redisClient.removeAllListeners();
|
|
80
|
-
this.redisClient = null;
|
|
81
|
-
}
|
|
82
|
-
this.redisAvailable = false;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
_getCache(table) {
|
|
87
|
-
if (this.cacheType === 'redis' && this.redisAvailable && this.redisClient) {
|
|
88
|
-
return this.redisClient;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Memory fallback - tablo bazlı cache oluştur
|
|
92
|
-
if (!this.tableCaches[table]) {
|
|
93
|
-
this.tableCaches[table] = new LRUCache({
|
|
94
|
-
max: this.cache ? this.cache.max : 500,
|
|
95
|
-
ttl: this.cache ? this.cache.ttl : 300000,
|
|
96
|
-
updateAgeOnGet: this.cache ? this.cache.updateAgeOnGet : false,
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
return this.tableCaches[table];
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
_generateKey(table, where) {
|
|
103
|
-
const sortedWhere = where ? this._sortObject(where) : {};
|
|
104
|
-
const key = `${table}:${JSON.stringify(sortedWhere)}`;
|
|
105
|
-
return this.cacheType === 'redis' ? `${this.keyPrefix}${key}` : key;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Where objelerini sıralama (tutarlı key oluşturma için)
|
|
109
|
-
_sortObject(obj) {
|
|
110
|
-
if (!obj || typeof obj !== 'object') return obj;
|
|
111
|
-
return Object.keys(obj)
|
|
112
|
-
.sort()
|
|
113
|
-
.reduce((sorted, key) => {
|
|
114
|
-
sorted[key] = obj[key];
|
|
115
|
-
return sorted;
|
|
116
|
-
}, {});
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
async _getCacheValue(cache, key, table) {
|
|
120
|
-
if (this.cacheType === 'redis' && this.redisAvailable && this.redisClient) {
|
|
121
|
-
try {
|
|
122
|
-
const value = await cache.get(key);
|
|
123
|
-
return value ? JSON.parse(value) : null;
|
|
124
|
-
} catch (err) {
|
|
125
|
-
console.warn('Redis get error, memory fallback:', err.message);
|
|
126
|
-
this.redisAvailable = false;
|
|
127
|
-
// Memory cache'e geçiş yap
|
|
128
|
-
const memoryCache = this._getCache(table);
|
|
129
|
-
return memoryCache.get(key);
|
|
130
|
-
}
|
|
131
|
-
} else {
|
|
132
|
-
return cache.get(key);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
async _setCacheValue(cache, key, value, table) {
|
|
137
|
-
if (this.cacheType === 'redis' && this.redisAvailable && this.redisClient) {
|
|
138
|
-
try {
|
|
139
|
-
await cache.setEx(key, this.ttl, JSON.stringify(value));
|
|
140
|
-
} catch (err) {
|
|
141
|
-
console.warn('Redis set error, memory fallback:', err.message);
|
|
142
|
-
this.redisAvailable = false;
|
|
143
|
-
// Memory cache'e geçiş yap
|
|
144
|
-
const memoryCache = this._getCache(table);
|
|
145
|
-
memoryCache.set(key, value);
|
|
146
|
-
}
|
|
147
|
-
} else {
|
|
148
|
-
cache.set(key, value);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
async _clearCache(table) {
|
|
153
|
-
if (this.cacheType === 'redis' && this.redisAvailable && this.redisClient) {
|
|
154
|
-
try {
|
|
155
|
-
const keys = await this.redisClient.keys(`${this.keyPrefix}${table}:*`);
|
|
156
|
-
if (keys.length) await this.redisClient.del(keys);
|
|
157
|
-
} catch (err) {
|
|
158
|
-
console.warn('Redis clear error, memory fallback:', err.message);
|
|
159
|
-
this.redisAvailable = false;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// Memory cache'i de temizle
|
|
164
|
-
if (this.tableCaches[table]) {
|
|
165
|
-
this.tableCaches[table].clear();
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Belirli bir cache key'i sil
|
|
170
|
-
async _deleteCacheKey(table, key) {
|
|
171
|
-
if (this.cacheType === 'redis' && this.redisAvailable && this.redisClient) {
|
|
172
|
-
try {
|
|
173
|
-
await this.redisClient.del(`${this.keyPrefix}${table}:${key}`);
|
|
174
|
-
} catch (err) {
|
|
175
|
-
console.warn('Redis delete key error:', err.message);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// Memory cache'ten de sil
|
|
180
|
-
const cache = this._getCache(table);
|
|
181
|
-
if (cache && cache.delete) {
|
|
182
|
-
cache.delete(key);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// Cache'teki veriyi güncelle
|
|
187
|
-
async _updateCacheValue(table, key, newData) {
|
|
188
|
-
const cache = this._getCache(table);
|
|
189
|
-
if (newData !== null && newData !== undefined) {
|
|
190
|
-
await this._setCacheValue(cache, key, newData, table);
|
|
191
|
-
} else {
|
|
192
|
-
await this._deleteCacheKey(table, key);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// Where koşuluna uyan tüm cache key'lerini bul ve güncelle/sil
|
|
197
|
-
async _updateCacheByWhere(table, where, newData = null) {
|
|
198
|
-
// Eğer where boşsa veya çok karmaşıksa, cache'i tamamen temizle
|
|
199
|
-
if (!where || Object.keys(where).length === 0) {
|
|
200
|
-
await this._clearCache(table);
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// Redis için
|
|
205
|
-
if (this.cacheType === 'redis' && this.redisAvailable && this.redisClient) {
|
|
206
|
-
try {
|
|
207
|
-
const keys = await this.redisClient.keys(`${this.keyPrefix}${table}:*`);
|
|
208
|
-
for (const fullKey of keys) {
|
|
209
|
-
const cacheData = await this.redisClient.get(fullKey);
|
|
210
|
-
if (cacheData) {
|
|
211
|
-
try {
|
|
212
|
-
const parsedData = JSON.parse(cacheData);
|
|
213
|
-
// Eğer cached data where koşuluna uyuyorsa güncelle/sil
|
|
214
|
-
if (this._matchesWhere(parsedData, where)) {
|
|
215
|
-
if (newData) {
|
|
216
|
-
await this.redisClient.setEx(fullKey, this.ttl, JSON.stringify(newData));
|
|
217
|
-
} else {
|
|
218
|
-
await this.redisClient.del(fullKey);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
} catch (parseErr) {
|
|
222
|
-
// Parse edilemeyen veriyi sil
|
|
223
|
-
await this.redisClient.del(fullKey);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
} catch (err) {
|
|
228
|
-
console.warn('Redis update by where error:', err.message);
|
|
229
|
-
// Hata durumunda cache'i temizle
|
|
230
|
-
await this._clearCache(table);
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// Memory cache için
|
|
235
|
-
const cache = this._getCache(table);
|
|
236
|
-
if (cache && cache.forEach) {
|
|
237
|
-
const keysToUpdate = [];
|
|
238
|
-
const keysToDelete = [];
|
|
239
|
-
|
|
240
|
-
cache.forEach((value, key) => {
|
|
241
|
-
try {
|
|
242
|
-
if (this._matchesWhere(value, where)) {
|
|
243
|
-
if (newData) {
|
|
244
|
-
keysToUpdate.push({ key, data: newData });
|
|
245
|
-
} else {
|
|
246
|
-
keysToDelete.push(key);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
} catch (err) {
|
|
250
|
-
// Hatalı veriyi sil
|
|
251
|
-
keysToDelete.push(key);
|
|
252
|
-
}
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
// Güncellemeleri uygula
|
|
256
|
-
keysToUpdate.forEach(({ key, data }) => {
|
|
257
|
-
cache.set(key, data);
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
keysToDelete.forEach(key => {
|
|
261
|
-
cache.delete(key);
|
|
262
|
-
});
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
// Basit where matching (nested object desteği ile)
|
|
267
|
-
_matchesWhere(data, where) {
|
|
268
|
-
if (!data || !where) return false;
|
|
269
|
-
|
|
270
|
-
for (const [key, value] of Object.entries(where)) {
|
|
271
|
-
if (data[key] !== value) {
|
|
272
|
-
return false;
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
return true;
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
// Read Operations
|
|
279
|
-
async select(table, where) {
|
|
280
|
-
const cache = this._getCache(table);
|
|
281
|
-
const key = this._generateKey(table, where);
|
|
282
|
-
let data = await this._getCacheValue(cache, key, table);
|
|
283
|
-
if (data !== null && data !== undefined) return data;
|
|
284
|
-
|
|
285
|
-
data = await this.db.select(table, where);
|
|
286
|
-
if (data !== null && data !== undefined) {
|
|
287
|
-
await this._setCacheValue(cache, key, data, table);
|
|
288
|
-
}
|
|
289
|
-
return data;
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
async selectOne(table, where) {
|
|
293
|
-
const cache = this._getCache(table);
|
|
294
|
-
const key = this._generateKey(table + '_one', where); // selectOne için farklı key
|
|
295
|
-
let data = await this._getCacheValue(cache, key, table);
|
|
296
|
-
if (data !== null && data !== undefined) return data;
|
|
297
|
-
|
|
298
|
-
data = await this.db.selectOne(table, where);
|
|
299
|
-
if (data !== null && data !== undefined) {
|
|
300
|
-
await this._setCacheValue(cache, key, data, table);
|
|
301
|
-
}
|
|
302
|
-
return data;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
// Write Operations (smart cache management)
|
|
306
|
-
async insert(table, data) {
|
|
307
|
-
const result = await this.db.insert(table, data);
|
|
308
|
-
|
|
309
|
-
// Insert için cache'i tamamen temizlemek yerine, sadece genel sorguları temizle
|
|
310
|
-
// Çünkü yeni veri eklendiğinde select() sonuçları değişebilir
|
|
311
|
-
await this._clearCache(table);
|
|
312
|
-
|
|
313
|
-
return result;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
async update(table, data, where) {
|
|
317
|
-
const result = await this.db.update(table, data, where);
|
|
318
|
-
|
|
319
|
-
if (result > 0) {
|
|
320
|
-
// Güncellenen verileri cache'te de güncelle
|
|
321
|
-
await this._updateCacheByWhere(table, where, null); // Önce sil
|
|
322
|
-
|
|
323
|
-
// Güncellenen veriyi cache'e eklemek için fresh data'yı al
|
|
324
|
-
try {
|
|
325
|
-
const updatedData = await this.db.selectOne(table, where);
|
|
326
|
-
if (updatedData) {
|
|
327
|
-
// selectOne cache'ine ekle
|
|
328
|
-
const cache = this._getCache(table);
|
|
329
|
-
const key = this._generateKey(table + '_one', where);
|
|
330
|
-
await this._setCacheValue(cache, key, updatedData, table);
|
|
331
|
-
}
|
|
332
|
-
} catch (err) {
|
|
333
|
-
// Hata durumunda cache'i temizle
|
|
334
|
-
await this._clearCache(table);
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
return result;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
async set(table, data, where) {
|
|
342
|
-
const result = await this.db.set(table, data, where);
|
|
343
|
-
|
|
344
|
-
// Set operasyonu için güncellenmiş/eklenen veriyi cache'e al
|
|
345
|
-
try {
|
|
346
|
-
const newData = await this.db.selectOne(table, where);
|
|
347
|
-
if (newData) {
|
|
348
|
-
// Cache'teki eski veriyi güncelle
|
|
349
|
-
const cache = this._getCache(table);
|
|
350
|
-
const key = this._generateKey(table + '_one', where);
|
|
351
|
-
await this._setCacheValue(cache, key, newData, table);
|
|
352
|
-
|
|
353
|
-
// Select cache'lerini de güncelle (where koşuluna uyarsa)
|
|
354
|
-
await this._updateCacheByWhere(table, where, null); // Eski cache'leri temizle
|
|
355
|
-
}
|
|
356
|
-
} catch (err) {
|
|
357
|
-
// Hata durumunda cache'i temizle
|
|
358
|
-
await this._clearCache(table);
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
return result;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
async delete(table, where) {
|
|
365
|
-
const result = await this.db.delete(table, where);
|
|
366
|
-
|
|
367
|
-
if (result > 0) {
|
|
368
|
-
// Silinen verileri cache'ten de sil
|
|
369
|
-
await this._updateCacheByWhere(table, where, null);
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
return result;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
async deleteOne(table, where) {
|
|
376
|
-
const result = await this.db.deleteOne(table, where);
|
|
377
|
-
|
|
378
|
-
if (result > 0) {
|
|
379
|
-
// Silinen veriyi cache'ten de sil
|
|
380
|
-
await this._updateCacheByWhere(table, where, null);
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
return result;
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
async updateOne(table, data, where) {
|
|
387
|
-
const result = await this.db.updateOne(table, data, where);
|
|
388
|
-
|
|
389
|
-
if (result > 0) {
|
|
390
|
-
// Güncellenen veriyi cache'te de güncelle
|
|
391
|
-
try {
|
|
392
|
-
const updatedData = await this.db.selectOne(table, where);
|
|
393
|
-
if (updatedData) {
|
|
394
|
-
const cache = this._getCache(table);
|
|
395
|
-
const key = this._generateKey(table + '_one', where);
|
|
396
|
-
await this._setCacheValue(cache, key, updatedData, table);
|
|
397
|
-
}
|
|
398
|
-
} catch (err) {
|
|
399
|
-
// Hata durumunda ilgili cache'leri temizle
|
|
400
|
-
await this._updateCacheByWhere(table, where, null);
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
return result;
|
|
405
|
-
}
|
|
406
|
-
|
|
407
|
-
async bulkInsert(table, dataArray) {
|
|
408
|
-
const result = await this.db.bulkInsert(table, dataArray);
|
|
409
|
-
|
|
410
|
-
// Bulk insert için cache'i tamamen temizle
|
|
411
|
-
// Çünkü çok sayıda yeni veri eklendiğinde select sonuçları değişir
|
|
412
|
-
await this._clearCache(table);
|
|
413
|
-
|
|
414
|
-
return result;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
async clearAllCache() {
|
|
418
|
-
if (this.cacheType === 'redis' && this.redisAvailable && this.redisClient) {
|
|
419
|
-
try {
|
|
420
|
-
const keys = await this.redisClient.keys(`${this.keyPrefix}*`);
|
|
421
|
-
if (keys.length) await this.redisClient.del(keys);
|
|
422
|
-
} catch (err) {
|
|
423
|
-
console.warn('Redis clearAll error:', err.message);
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
// Tüm memory cache'leri temizle
|
|
428
|
-
Object.values(this.tableCaches).forEach(c => c.clear());
|
|
429
|
-
if (this.cache) this.cache.clear();
|
|
430
|
-
this.tableCaches = {}; // Referansları da temizle
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
async close() {
|
|
434
|
-
await this.clearAllCache();
|
|
435
|
-
if (this.redisClient) {
|
|
436
|
-
try {
|
|
437
|
-
this.redisClient.removeAllListeners();
|
|
438
|
-
if (this.redisAvailable && this.redisClient.isOpen) {
|
|
439
|
-
await this.redisClient.quit();
|
|
440
|
-
} else if (this.redisClient.isOpen) {
|
|
441
|
-
await this.redisClient.disconnect();
|
|
442
|
-
}
|
|
443
|
-
} catch (err) {
|
|
444
|
-
console.warn('Redis close error:', err.message);
|
|
445
|
-
}
|
|
446
|
-
this.redisClient = null;
|
|
447
|
-
this.redisAvailable = false;
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
// Database bağlantısını kapat
|
|
451
|
-
if (this.db && typeof this.db.close === 'function') {
|
|
452
|
-
return this.db.close();
|
|
453
|
-
}
|
|
454
|
-
return Promise.resolve();
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
/**
|
|
458
|
-
* Numerik alanları artırır (increment) ve cache'i akıllıca günceller.
|
|
459
|
-
* @param {string} table - Verinin güncelleneceği tablo adı.
|
|
460
|
-
* @param {object} increments - Artırılacak alanlar ve miktarları.
|
|
461
|
-
* @param {object} where - Güncelleme koşulları.
|
|
462
|
-
* @returns {Promise<number>} Etkilenen kayıt sayısı.
|
|
463
|
-
*/
|
|
464
|
-
async increment(table, increments, where = {}) {
|
|
465
|
-
const result = await this.db.increment(table, increments, where);
|
|
466
|
-
|
|
467
|
-
if (result > 0) {
|
|
468
|
-
// Cache'teki değerleri de increment et
|
|
469
|
-
await this._incrementCacheValues(table, increments, where);
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
return result;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
/**
|
|
476
|
-
* Numerik alanları azaltır (decrement) ve cache'i akıllıca günceller.
|
|
477
|
-
* @param {string} table - Verinin güncelleneceği tablo adı.
|
|
478
|
-
* @param {object} decrements - Azaltılacak alanlar ve miktarları.
|
|
479
|
-
* @param {object} where - Güncelleme koşulları.
|
|
480
|
-
* @returns {Promise<number>} Etkilenen kayıt sayısı.
|
|
481
|
-
*/
|
|
482
|
-
async decrement(table, decrements, where = {}) {
|
|
483
|
-
const result = await this.db.decrement(table, decrements, where);
|
|
484
|
-
|
|
485
|
-
if (result > 0) {
|
|
486
|
-
// Cache'teki değerleri de decrement et
|
|
487
|
-
const negativeIncrements = {};
|
|
488
|
-
for (const [key, value] of Object.entries(decrements)) {
|
|
489
|
-
negativeIncrements[key] = -value;
|
|
490
|
-
}
|
|
491
|
-
await this._incrementCacheValues(table, negativeIncrements, where);
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
return result;
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
// Cache'teki numerik değerleri increment/decrement et
|
|
498
|
-
async _incrementCacheValues(table, increments, where) {
|
|
499
|
-
// Redis için
|
|
500
|
-
if (this.cacheType === 'redis' && this.redisAvailable && this.redisClient) {
|
|
501
|
-
try {
|
|
502
|
-
const keys = await this.redisClient.keys(`${this.keyPrefix}${table}:*`);
|
|
503
|
-
for (const fullKey of keys) {
|
|
504
|
-
const cacheData = await this.redisClient.get(fullKey);
|
|
505
|
-
if (cacheData) {
|
|
506
|
-
try {
|
|
507
|
-
const parsedData = JSON.parse(cacheData);
|
|
508
|
-
if (this._matchesWhere(parsedData, where)) {
|
|
509
|
-
// Cache'teki değerleri increment et
|
|
510
|
-
const updatedData = { ...parsedData };
|
|
511
|
-
for (const [field, increment] of Object.entries(increments)) {
|
|
512
|
-
if (typeof updatedData[field] === 'number') {
|
|
513
|
-
updatedData[field] += increment;
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
await this.redisClient.setEx(fullKey, this.ttl, JSON.stringify(updatedData));
|
|
517
|
-
}
|
|
518
|
-
} catch (parseErr) {
|
|
519
|
-
// Parse edilemeyen veriyi sil
|
|
520
|
-
await this.redisClient.del(fullKey);
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
} catch (err) {
|
|
525
|
-
console.warn('Redis increment cache error:', err.message);
|
|
526
|
-
// Hata durumunda cache'i temizle
|
|
527
|
-
await this._clearCache(table);
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
// Memory cache için
|
|
532
|
-
const cache = this._getCache(table);
|
|
533
|
-
if (cache && cache.forEach) {
|
|
534
|
-
const keysToUpdate = [];
|
|
535
|
-
|
|
536
|
-
cache.forEach((value, key) => {
|
|
537
|
-
try {
|
|
538
|
-
if (this._matchesWhere(value, where)) {
|
|
539
|
-
const updatedData = { ...value };
|
|
540
|
-
for (const [field, increment] of Object.entries(increments)) {
|
|
541
|
-
if (typeof updatedData[field] === 'number') {
|
|
542
|
-
updatedData[field] += increment;
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
keysToUpdate.push({ key, data: updatedData });
|
|
546
|
-
}
|
|
547
|
-
} catch (err) {
|
|
548
|
-
// Hatalı veriyi sil
|
|
549
|
-
cache.delete(key);
|
|
550
|
-
}
|
|
551
|
-
});
|
|
552
|
-
|
|
553
|
-
// Güncellemeleri uygula
|
|
554
|
-
keysToUpdate.forEach(({ key, data }) => {
|
|
555
|
-
cache.set(key, data);
|
|
556
|
-
});
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
// Utility methods
|
|
561
|
-
getCacheStats() {
|
|
562
|
-
const stats = {
|
|
563
|
-
type: this.cacheType,
|
|
564
|
-
redisAvailable: this.redisAvailable,
|
|
565
|
-
memoryTables: Object.keys(this.tableCaches),
|
|
566
|
-
};
|
|
567
|
-
|
|
568
|
-
if (this.cacheType === 'memory') {
|
|
569
|
-
stats.mainCache = {
|
|
570
|
-
size: this.cache ? this.cache.size : 0,
|
|
571
|
-
max: this.cache ? this.cache.max : 0,
|
|
572
|
-
};
|
|
573
|
-
stats.tableCaches = Object.fromEntries(
|
|
574
|
-
Object.entries(this.tableCaches).map(([table, cache]) => [
|
|
575
|
-
table,
|
|
576
|
-
{ size: cache.size, max: cache.max }
|
|
577
|
-
])
|
|
578
|
-
);
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
return stats;
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
module.exports = CacheWrapper;
|
package/database/index.js
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
// database-factory.js
|
|
2
|
-
const IDatabase = require('./IDatabase');
|
|
3
|
-
const MySQLDatabase = require('./mysql');
|
|
4
|
-
const SQLiteDatabase = require('./sqlite');
|
|
5
|
-
const MongoDBDatabase = require('./mongodb');
|
|
6
|
-
const JsonDatabase = require('./json');
|
|
7
|
-
const PostgreSQLDatabase = require('./pg');
|
|
8
|
-
const RedisDatabase = require('./redis'); // Yeni Redis adapter
|
|
9
|
-
const CacheWrapper = require('./cacheWrapper');
|
|
10
|
-
const MigrationManager = require('./migration');
|
|
11
|
-
|
|
12
|
-
const adapters = {
|
|
13
|
-
mysql: MySQLDatabase,
|
|
14
|
-
sqlite: SQLiteDatabase,
|
|
15
|
-
mongodb: MongoDBDatabase,
|
|
16
|
-
postgres: PostgreSQLDatabase,
|
|
17
|
-
json: JsonDatabase,
|
|
18
|
-
redis: RedisDatabase, // Redis adapter eklendi
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Belirtilen adaptör tipine göre bir veritabanı örneği oluşturur ve döndürür.
|
|
23
|
-
* Bu bir "Fabrika Fonksiyonu"dur.
|
|
24
|
-
*
|
|
25
|
-
* @param {object} options - Yapılandırma seçenekleri.
|
|
26
|
-
* @param {keyof adapters} options.adapter - Kullanılacak adaptör ('mysql', 'sqlite', 'redis', vb.).
|
|
27
|
-
* @param {object} options.config - Seçilen adaptöre özel yapılandırma.
|
|
28
|
-
* @returns {IDatabase} - IDatabase arayüzünü uygulayan bir örnek döndürür.
|
|
29
|
-
*/
|
|
30
|
-
function createDatabase(options) {
|
|
31
|
-
const { adapter, config } = options;
|
|
32
|
-
|
|
33
|
-
if (!adapter || !adapters[adapter]) {
|
|
34
|
-
throw new Error(`Geçersiz veya desteklenmeyen adaptör: ${adapter}. Desteklenenler: ${Object.keys(adapters).join(', ')}`);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
if (!config) {
|
|
38
|
-
throw new Error(`'${adapter}' adaptörü için yapılandırma (config) gereklidir.`);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// İlgili adaptör sınıfını al
|
|
42
|
-
const DatabaseClass = adapters[adapter];
|
|
43
|
-
|
|
44
|
-
// Sınıfın bir örneğini oluştur ve doğrudan döndür
|
|
45
|
-
const dbInstance = new DatabaseClass(config);
|
|
46
|
-
|
|
47
|
-
// Eğer cache etkinse, veritabanı örneğini CacheWrapper ile sarmala
|
|
48
|
-
if (config.cache) {
|
|
49
|
-
return new Proxy(new CacheWrapper(dbInstance, config.cache), {
|
|
50
|
-
get: (target, prop) => {
|
|
51
|
-
if (typeof target[prop] !== 'undefined') {
|
|
52
|
-
return target[prop];
|
|
53
|
-
} else if (typeof target.db[prop] === 'function') {
|
|
54
|
-
return target.db[prop].bind(target.db);
|
|
55
|
-
} else {
|
|
56
|
-
return target.db[prop];
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return dbInstance;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Artık varsayılan olarak bu fonksiyonu export ediyoruz.
|
|
66
|
-
module.exports = createDatabase;
|
|
67
|
-
|
|
68
|
-
// Migration manager'ı da export ediyoruz
|
|
69
|
-
module.exports.MigrationManager = MigrationManager;
|
|
70
|
-
|
|
71
|
-
// Eğer hem fonksiyonu hem de tipleri export etmek isterseniz:
|
|
72
|
-
// module.exports = { createDatabase, MigrationManager };
|