@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/json.js
DELETED
|
@@ -1,281 +0,0 @@
|
|
|
1
|
-
const IDatabase = require('./IDatabase'); // Arayüzü import et
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @implements {IDatabase}
|
|
5
|
-
*/
|
|
6
|
-
const fs = require('fs').promises; // Asenkron dosya işlemleri için
|
|
7
|
-
const path = require('path');
|
|
8
|
-
|
|
9
|
-
class JsonDatabase extends IDatabase{
|
|
10
|
-
/**
|
|
11
|
-
* @param {object} config - Yapılandırma nesnesi.
|
|
12
|
-
* @param {string} config.filePath - JSON veritabanı dosyasının yolu.
|
|
13
|
-
* @param {number} [config.saveInterval=500] - Değişiklikleri dosyaya yazma gecikmesi (ms).
|
|
14
|
-
*/
|
|
15
|
-
constructor(config) {
|
|
16
|
-
super()
|
|
17
|
-
if (!config || !config.filePath) {
|
|
18
|
-
throw new Error('Yapılandırma içinde "filePath" belirtilmelidir.');
|
|
19
|
-
}
|
|
20
|
-
this.filePath = config.filePath;
|
|
21
|
-
this.db = {};
|
|
22
|
-
this.isDirty = false;
|
|
23
|
-
this.isWriting = false;
|
|
24
|
-
this.writeQueue = [];
|
|
25
|
-
this.saveDebounceTimeout = null;
|
|
26
|
-
this.saveInterval = config.saveInterval || 500;
|
|
27
|
-
|
|
28
|
-
process.on('exit', () => this.flushSync());
|
|
29
|
-
this.initPromise = this._load();
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// --- ÖZEL (PRIVATE) METOTLAR ---
|
|
33
|
-
|
|
34
|
-
async _load() {
|
|
35
|
-
try {
|
|
36
|
-
const dir = path.dirname(this.filePath);
|
|
37
|
-
await fs.mkdir(dir, { recursive: true });
|
|
38
|
-
const fileContent = await fs.readFile(this.filePath, 'utf-8');
|
|
39
|
-
this.db = JSON.parse(fileContent);
|
|
40
|
-
} catch (error) {
|
|
41
|
-
if (error.code === 'ENOENT') {
|
|
42
|
-
this.db = {};
|
|
43
|
-
await this._saveNow();
|
|
44
|
-
} else {
|
|
45
|
-
console.error("Veritabanı dosyası okunurken hata:", error);
|
|
46
|
-
this.db = {};
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
_queueRequest(operation) {
|
|
52
|
-
return new Promise((resolve, reject) => {
|
|
53
|
-
this.writeQueue.push({ operation, resolve, reject });
|
|
54
|
-
this._processQueue();
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async _processQueue() {
|
|
59
|
-
if (this.isWriting || this.writeQueue.length === 0) return;
|
|
60
|
-
this.isWriting = true;
|
|
61
|
-
|
|
62
|
-
const { operation, resolve, reject } = this.writeQueue.shift();
|
|
63
|
-
try {
|
|
64
|
-
const result = operation();
|
|
65
|
-
this.isDirty = true;
|
|
66
|
-
this._scheduleSave();
|
|
67
|
-
resolve(result);
|
|
68
|
-
} catch (error) {
|
|
69
|
-
reject(error);
|
|
70
|
-
} finally {
|
|
71
|
-
this.isWriting = false;
|
|
72
|
-
this._processQueue();
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
_scheduleSave() {
|
|
77
|
-
if (this.saveDebounceTimeout) clearTimeout(this.saveDebounceTimeout);
|
|
78
|
-
this.saveDebounceTimeout = setTimeout(() => this._saveNow(), this.saveInterval);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
async _saveNow() {
|
|
82
|
-
if (!this.isDirty) return;
|
|
83
|
-
clearTimeout(this.saveDebounceTimeout);
|
|
84
|
-
this.saveDebounceTimeout = null;
|
|
85
|
-
try {
|
|
86
|
-
await fs.writeFile(this.filePath, JSON.stringify(this.db, null, 2));
|
|
87
|
-
this.isDirty = false;
|
|
88
|
-
} catch (error) {
|
|
89
|
-
console.error("Veritabanı dosyasına yazılırken hata:", error);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
flushSync() {
|
|
94
|
-
if (this.isDirty) {
|
|
95
|
-
console.log('Uygulama kapanıyor, bekleyen değişiklikler kaydediliyor...');
|
|
96
|
-
try {
|
|
97
|
-
require('fs').writeFileSync(this.filePath, JSON.stringify(this.db, null, 2));
|
|
98
|
-
this.isDirty = false;
|
|
99
|
-
} catch (error) {
|
|
100
|
-
console.error('Senkron kaydetme sırasında hata:', error);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
_matches(row, where) {
|
|
106
|
-
return Object.keys(where).every(key => row[key] === where[key]);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// Alias for consistency with cache wrapper
|
|
110
|
-
_matchesWhere(row, where) {
|
|
111
|
-
return this._matches(row, where);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// --- GENEL (PUBLIC) API ---
|
|
115
|
-
|
|
116
|
-
async ensureTable(table) {
|
|
117
|
-
await this.initPromise;
|
|
118
|
-
if (!this.db[table]) {
|
|
119
|
-
return this._queueRequest(() => {
|
|
120
|
-
this.db[table] = [];
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
async insert(table, data) {
|
|
126
|
-
await this.ensureTable(table);
|
|
127
|
-
return this._queueRequest(() => {
|
|
128
|
-
const maxId = this.db[table].reduce((max, row) => (row._id > max ? row._id : max), 0);
|
|
129
|
-
const newId = maxId + 1;
|
|
130
|
-
const newRow = { _id: newId, ...data };
|
|
131
|
-
this.db[table].push(newRow);
|
|
132
|
-
return newId;
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
async update(table, data, where) {
|
|
137
|
-
await this.ensureTable(table);
|
|
138
|
-
return this._queueRequest(() => {
|
|
139
|
-
let affectedRows = 0;
|
|
140
|
-
this.db[table].forEach(row => {
|
|
141
|
-
if (this._matches(row, where)) {
|
|
142
|
-
Object.assign(row, data);
|
|
143
|
-
affectedRows++;
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
return affectedRows;
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
async delete(table, where) {
|
|
151
|
-
await this.ensureTable(table);
|
|
152
|
-
return this._queueRequest(() => {
|
|
153
|
-
const initialLength = this.db[table].length;
|
|
154
|
-
this.db[table] = this.db[table].filter(row => !this._matches(row, where));
|
|
155
|
-
return initialLength - this.db[table].length;
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
async select(table, where = null) {
|
|
160
|
-
await this.initPromise;
|
|
161
|
-
const tableData = this.db[table] || [];
|
|
162
|
-
let results = tableData;
|
|
163
|
-
if (where && Object.keys(where).length > 0) {
|
|
164
|
-
results = results.filter(row => this._matches(row, where));
|
|
165
|
-
}
|
|
166
|
-
return JSON.parse(JSON.stringify(results));
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
async set(table, data, where) {
|
|
170
|
-
await this.ensureTable(table);
|
|
171
|
-
const existing = await this.select(table, where);
|
|
172
|
-
if (existing.length === 0) {
|
|
173
|
-
return this.insert(table, { ...where, ...data });
|
|
174
|
-
} else {
|
|
175
|
-
return this.update(table, data, where);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
async selectOne(table, where = null) {
|
|
180
|
-
// Bu metot sadece okuma yaptığı için kuyruğa girmesine gerek yok.
|
|
181
|
-
const results = await this.select(table, where);
|
|
182
|
-
return results[0] || null;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
async deleteOne(table, where) {
|
|
186
|
-
await this.ensureTable(table);
|
|
187
|
-
return this._queueRequest(() => {
|
|
188
|
-
const index = this.db[table].findIndex(row => this._matches(row, where));
|
|
189
|
-
if (index > -1) {
|
|
190
|
-
this.db[table].splice(index, 1);
|
|
191
|
-
return 1; // 1 satır etkilendi
|
|
192
|
-
}
|
|
193
|
-
return 0; // Hiçbir satır etkilendi
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
async updateOne(table, data, where) {
|
|
198
|
-
await this.ensureTable(table);
|
|
199
|
-
return this._queueRequest(() => {
|
|
200
|
-
const row = this.db[table].find(row => this._matches(row, where));
|
|
201
|
-
if (row) {
|
|
202
|
-
Object.assign(row, data);
|
|
203
|
-
return 1; // 1 satır etkilendi
|
|
204
|
-
}
|
|
205
|
-
return 0; // Hiçbir satır etkilendi
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
async bulkInsert(table, dataArray) {
|
|
210
|
-
if (!Array.isArray(dataArray) || dataArray.length === 0) return 0;
|
|
211
|
-
await this.ensureTable(table);
|
|
212
|
-
return this._queueRequest(() => {
|
|
213
|
-
let maxId = this.db[table].reduce((max, row) => (row._id > max ? row._id : max), 0);
|
|
214
|
-
dataArray.forEach(data => {
|
|
215
|
-
maxId++;
|
|
216
|
-
this.db[table].push({ _id: maxId, ...data });
|
|
217
|
-
});
|
|
218
|
-
return dataArray.length;
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* Numerik alanları artırır (increment).
|
|
224
|
-
* @param {string} table - Verinin güncelleneceği tablo adı.
|
|
225
|
-
* @param {object} increments - Artırılacak alanlar ve miktarları.
|
|
226
|
-
* @param {object} where - Güncelleme koşulları.
|
|
227
|
-
* @returns {Promise<number>} Etkilenen kayıt sayısı.
|
|
228
|
-
*/
|
|
229
|
-
async increment(table, increments, where = {}) {
|
|
230
|
-
await this.ensureTable(table);
|
|
231
|
-
return this._queueRequest(() => {
|
|
232
|
-
let affectedCount = 0;
|
|
233
|
-
this.db[table].forEach(row => {
|
|
234
|
-
if (this._matchesWhere(row, where)) {
|
|
235
|
-
for (const [field, value] of Object.entries(increments)) {
|
|
236
|
-
if (typeof row[field] === 'number') {
|
|
237
|
-
row[field] += value;
|
|
238
|
-
} else {
|
|
239
|
-
row[field] = value; // Eğer field sayı değilse, yeni değeri ata
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
affectedCount++;
|
|
243
|
-
}
|
|
244
|
-
});
|
|
245
|
-
return affectedCount;
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
/**
|
|
250
|
-
* Numerik alanları azaltır (decrement).
|
|
251
|
-
* @param {string} table - Verinin güncelleneceği tablo adı.
|
|
252
|
-
* @param {object} decrements - Azaltılacak alanlar ve miktarları.
|
|
253
|
-
* @param {object} where - Güncelleme koşulları.
|
|
254
|
-
* @returns {Promise<number>} Etkilenen kayıt sayısı.
|
|
255
|
-
*/
|
|
256
|
-
async decrement(table, decrements, where = {}) {
|
|
257
|
-
await this.ensureTable(table);
|
|
258
|
-
return this._queueRequest(() => {
|
|
259
|
-
let affectedCount = 0;
|
|
260
|
-
this.db[table].forEach(row => {
|
|
261
|
-
if (this._matchesWhere(row, where)) {
|
|
262
|
-
for (const [field, value] of Object.entries(decrements)) {
|
|
263
|
-
if (typeof row[field] === 'number') {
|
|
264
|
-
row[field] -= value;
|
|
265
|
-
} else {
|
|
266
|
-
row[field] = -value; // Eğer field sayı değilse, negatif değeri ata
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
affectedCount++;
|
|
270
|
-
}
|
|
271
|
-
});
|
|
272
|
-
return affectedCount;
|
|
273
|
-
});
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
async close() {
|
|
277
|
-
await this._saveNow();
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
module.exports = JsonDatabase;
|
package/database/migration.js
DELETED
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
|
|
4
|
-
class MigrationManager {
|
|
5
|
-
constructor(database, options = {}) {
|
|
6
|
-
this.db = database;
|
|
7
|
-
this.migrationsDir = options.migrationsDir || './migrations';
|
|
8
|
-
this.migrationsTable = options.migrationsTable || 'migrations';
|
|
9
|
-
this.ensureMigrationsDir();
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
ensureMigrationsDir() {
|
|
13
|
-
if (!fs.existsSync(this.migrationsDir)) {
|
|
14
|
-
fs.mkdirSync(this.migrationsDir, { recursive: true });
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
async ensureMigrationsTable() {
|
|
19
|
-
try {
|
|
20
|
-
// Migrations tablosu var mı kontrol et
|
|
21
|
-
await this.db.selectOne(this.migrationsTable, {});
|
|
22
|
-
} catch (error) {
|
|
23
|
-
// Tablo yoksa oluştur
|
|
24
|
-
const createTableSQL = `
|
|
25
|
-
CREATE TABLE IF NOT EXISTS ${this.migrationsTable} (
|
|
26
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
27
|
-
name VARCHAR(255) NOT NULL UNIQUE,
|
|
28
|
-
executed_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
29
|
-
)
|
|
30
|
-
`;
|
|
31
|
-
|
|
32
|
-
// SQLite, MySQL, PostgreSQL için farklı SQL'ler
|
|
33
|
-
if (this.db.constructor.name === 'MySQLDatabase') {
|
|
34
|
-
await this.db.query(createTableSQL.replace('AUTOINCREMENT', 'AUTO_INCREMENT'));
|
|
35
|
-
} else if (this.db.constructor.name === 'PostgreSQLDatabase') {
|
|
36
|
-
const pgSQL = `
|
|
37
|
-
CREATE TABLE IF NOT EXISTS ${this.migrationsTable} (
|
|
38
|
-
id SERIAL PRIMARY KEY,
|
|
39
|
-
name VARCHAR(255) NOT NULL UNIQUE,
|
|
40
|
-
executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
41
|
-
)
|
|
42
|
-
`;
|
|
43
|
-
await this.db.query(pgSQL);
|
|
44
|
-
} else {
|
|
45
|
-
// SQLite
|
|
46
|
-
await this.db.query(createTableSQL);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
createMigration(name, description = '') {
|
|
52
|
-
const timestamp = Date.now();
|
|
53
|
-
const filename = `${timestamp}_${name}.js`;
|
|
54
|
-
const filePath = path.join(this.migrationsDir, filename);
|
|
55
|
-
|
|
56
|
-
const template = `// Migration: ${name}
|
|
57
|
-
// Description: ${description}
|
|
58
|
-
// Created: ${new Date().toISOString()}
|
|
59
|
-
|
|
60
|
-
module.exports = {
|
|
61
|
-
async up(db) {
|
|
62
|
-
// Migration işlemlerini buraya yazın
|
|
63
|
-
// Örnek:
|
|
64
|
-
// await db.query(\`
|
|
65
|
-
// CREATE TABLE users (
|
|
66
|
-
// id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
67
|
-
// name VARCHAR(255) NOT NULL,
|
|
68
|
-
// email VARCHAR(255) UNIQUE NOT NULL
|
|
69
|
-
// )
|
|
70
|
-
// \`);
|
|
71
|
-
|
|
72
|
-
console.log('Migration ${name} executed (up)');
|
|
73
|
-
},
|
|
74
|
-
|
|
75
|
-
async down(db) {
|
|
76
|
-
// Rollback işlemlerini buraya yazın
|
|
77
|
-
// Örnek:
|
|
78
|
-
// await db.query('DROP TABLE IF EXISTS users');
|
|
79
|
-
|
|
80
|
-
console.log('Migration ${name} rolled back (down)');
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
`;
|
|
84
|
-
|
|
85
|
-
fs.writeFileSync(filePath, template);
|
|
86
|
-
console.log(`Migration oluşturuldu: ${filename}`);
|
|
87
|
-
return filename;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
getMigrationFiles() {
|
|
91
|
-
const files = fs.readdirSync(this.migrationsDir)
|
|
92
|
-
.filter(file => file.endsWith('.js'))
|
|
93
|
-
.sort();
|
|
94
|
-
|
|
95
|
-
return files.map(file => ({
|
|
96
|
-
name: file,
|
|
97
|
-
path: path.join(this.migrationsDir, file)
|
|
98
|
-
}));
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
async getExecutedMigrations() {
|
|
102
|
-
await this.ensureMigrationsTable();
|
|
103
|
-
|
|
104
|
-
try {
|
|
105
|
-
const executed = await this.db.select(this.migrationsTable, {});
|
|
106
|
-
return executed.map(row => row.name);
|
|
107
|
-
} catch (error) {
|
|
108
|
-
console.error('Executed migrations alınırken hata:', error);
|
|
109
|
-
return [];
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
async getPendingMigrations() {
|
|
114
|
-
const allMigrations = this.getMigrationFiles();
|
|
115
|
-
const executedMigrations = await this.getExecutedMigrations();
|
|
116
|
-
|
|
117
|
-
return allMigrations.filter(migration =>
|
|
118
|
-
!executedMigrations.includes(migration.name)
|
|
119
|
-
);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
async runMigration(migrationFile, direction = 'up') {
|
|
123
|
-
try {
|
|
124
|
-
delete require.cache[require.resolve(migrationFile.path)];
|
|
125
|
-
const migration = require(migrationFile.path);
|
|
126
|
-
|
|
127
|
-
if (typeof migration[direction] !== 'function') {
|
|
128
|
-
throw new Error(`Migration ${migrationFile.name} has no ${direction} method`);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
await migration[direction](this.db);
|
|
132
|
-
|
|
133
|
-
if (direction === 'up') {
|
|
134
|
-
await this.db.insert(this.migrationsTable, {
|
|
135
|
-
name: migrationFile.name
|
|
136
|
-
});
|
|
137
|
-
} else if (direction === 'down') {
|
|
138
|
-
await this.db.delete(this.migrationsTable, {
|
|
139
|
-
name: migrationFile.name
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
console.log(`✅ Migration ${migrationFile.name} (${direction}) başarılı`);
|
|
144
|
-
return true;
|
|
145
|
-
} catch (error) {
|
|
146
|
-
console.error(`❌ Migration ${migrationFile.name} (${direction}) hatası:`, error);
|
|
147
|
-
throw error;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
async migrate() {
|
|
152
|
-
const pending = await this.getPendingMigrations();
|
|
153
|
-
|
|
154
|
-
if (pending.length === 0) {
|
|
155
|
-
console.log('✅ Tüm migration\'lar güncel');
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
console.log(`🔄 ${pending.length} migration çalıştırılacak...`);
|
|
160
|
-
|
|
161
|
-
for (const migration of pending) {
|
|
162
|
-
await this.runMigration(migration, 'up');
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
console.log('✅ Tüm migration\'lar tamamlandı');
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
async rollback(steps = 1) {
|
|
169
|
-
const executed = await this.getExecutedMigrations();
|
|
170
|
-
|
|
171
|
-
if (executed.length === 0) {
|
|
172
|
-
console.log('❌ Rollback yapılacak migration yok');
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const allMigrations = this.getMigrationFiles();
|
|
177
|
-
const toRollback = executed
|
|
178
|
-
.slice(-steps)
|
|
179
|
-
.reverse()
|
|
180
|
-
.map(name => allMigrations.find(m => m.name === name))
|
|
181
|
-
.filter(Boolean);
|
|
182
|
-
|
|
183
|
-
console.log(`🔄 ${toRollback.length} migration rollback edilecek...`);
|
|
184
|
-
|
|
185
|
-
for (const migration of toRollback) {
|
|
186
|
-
await this.runMigration(migration, 'down');
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
console.log('✅ Rollback tamamlandı');
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
async status() {
|
|
193
|
-
const allMigrations = this.getMigrationFiles();
|
|
194
|
-
const executedMigrations = await this.getExecutedMigrations();
|
|
195
|
-
|
|
196
|
-
console.log('\n📋 Migration Durumu:');
|
|
197
|
-
console.log('==================');
|
|
198
|
-
|
|
199
|
-
if (allMigrations.length === 0) {
|
|
200
|
-
console.log('❌ Migration dosyası bulunamadı');
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
allMigrations.forEach(migration => {
|
|
205
|
-
const status = executedMigrations.includes(migration.name) ? '✅ Executed' : '⏳ Pending';
|
|
206
|
-
console.log(`${status} ${migration.name}`);
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
const pendingCount = allMigrations.length - executedMigrations.length;
|
|
210
|
-
console.log(`\n📊 Toplam: ${allMigrations.length}, Executed: ${executedMigrations.length}, Pending: ${pendingCount}`);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
async reset() {
|
|
214
|
-
const executed = await this.getExecutedMigrations();
|
|
215
|
-
|
|
216
|
-
if (executed.length === 0) {
|
|
217
|
-
console.log('❌ Reset edilecek migration yok');
|
|
218
|
-
return;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
console.log(`🔄 ${executed.length} migration reset edilecek...`);
|
|
222
|
-
await this.rollback(executed.length);
|
|
223
|
-
console.log('✅ Tüm migration\'lar reset edildi');
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
module.exports = MigrationManager;
|
package/database/mongodb.js
DELETED
|
@@ -1,203 +0,0 @@
|
|
|
1
|
-
const IDatabase = require('./IDatabase'); // Arayüzü import et
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @implements {IDatabase}
|
|
5
|
-
*/
|
|
6
|
-
const { MongoClient, ObjectId } = require("mongodb");
|
|
7
|
-
|
|
8
|
-
class MongoDBDatabase extends IDatabase{
|
|
9
|
-
constructor(config) {
|
|
10
|
-
super();
|
|
11
|
-
this.config = config;
|
|
12
|
-
this.client = new MongoClient(config.url, {
|
|
13
|
-
useNewUrlParser: true,
|
|
14
|
-
useUnifiedTopology: true,
|
|
15
|
-
});
|
|
16
|
-
this._queue = [];
|
|
17
|
-
this._connected = false;
|
|
18
|
-
|
|
19
|
-
this._connectionPromise = new Promise(async (resolve, reject) => {
|
|
20
|
-
try {
|
|
21
|
-
await this.client.connect();
|
|
22
|
-
this.db = this.client.db(config.database);
|
|
23
|
-
this._connected = true;
|
|
24
|
-
resolve(this.db);
|
|
25
|
-
this._processQueue(); // Process any queued requests
|
|
26
|
-
} catch (error) {
|
|
27
|
-
console.error("MongoDB connection error:", error);
|
|
28
|
-
reject(error);
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async _queueRequest(operation) {
|
|
34
|
-
if (this._connected) {
|
|
35
|
-
return operation();
|
|
36
|
-
} else {
|
|
37
|
-
return new Promise((resolve, reject) => {
|
|
38
|
-
this._queue.push({ operation, resolve, reject });
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async _processQueue() {
|
|
44
|
-
if (!this._connected) return;
|
|
45
|
-
|
|
46
|
-
while (this._queue.length > 0) {
|
|
47
|
-
const { operation, resolve, reject } = this._queue.shift();
|
|
48
|
-
try {
|
|
49
|
-
const result = await operation();
|
|
50
|
-
resolve(result);
|
|
51
|
-
} catch (error) {
|
|
52
|
-
reject(error);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
async ensureCollection(collection) {
|
|
58
|
-
return this._queueRequest(async () => {
|
|
59
|
-
const db = await this._connectionPromise;
|
|
60
|
-
const collections = await db.listCollections({ name: collection }).toArray();
|
|
61
|
-
if (collections.length === 0) {
|
|
62
|
-
await db.createCollection(collection);
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
async insert(collection, data) {
|
|
68
|
-
return this._queueRequest(async () => {
|
|
69
|
-
await this.ensureCollection(collection);
|
|
70
|
-
const db = await this._connectionPromise;
|
|
71
|
-
const result = await db.collection(collection).insertOne(data);
|
|
72
|
-
return result.insertedId;
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
async bulkInsert(collection, dataArray) {
|
|
77
|
-
return this._queueRequest(async () => {
|
|
78
|
-
if (!Array.isArray(dataArray) || dataArray.length === 0) return 0;
|
|
79
|
-
await this.ensureCollection(collection);
|
|
80
|
-
const db = await this._connectionPromise;
|
|
81
|
-
const result = await db.collection(collection).insertMany(dataArray);
|
|
82
|
-
return result.insertedCount;
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
async update(collection, data, where) {
|
|
87
|
-
return this._queueRequest(async () => {
|
|
88
|
-
await this.ensureCollection(collection);
|
|
89
|
-
const db = await this._connectionPromise;
|
|
90
|
-
const result = await db.collection(collection).updateMany(where, { $set: data });
|
|
91
|
-
return result.modifiedCount;
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
async updateOne(collection, data, where) {
|
|
96
|
-
return this._queueRequest(async () => {
|
|
97
|
-
await this.ensureCollection(collection);
|
|
98
|
-
const db = await this._connectionPromise;
|
|
99
|
-
const result = await db.collection(collection).updateOne(where, { $set: data });
|
|
100
|
-
return result.modifiedCount;
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
async delete(collection, where) {
|
|
105
|
-
return this._queueRequest(async () => {
|
|
106
|
-
await this.ensureCollection(collection);
|
|
107
|
-
const db = await this._connectionPromise;
|
|
108
|
-
const result = await db.collection(collection).deleteMany(where);
|
|
109
|
-
return result.deletedCount;
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
async deleteOne(collection, where) {
|
|
114
|
-
return this._queueRequest(async () => {
|
|
115
|
-
await this.ensureCollection(collection);
|
|
116
|
-
const db = await this._connectionPromise;
|
|
117
|
-
const result = await db.collection(collection).deleteOne(where);
|
|
118
|
-
return result.deletedCount;
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
async select(collection, where = {}) {
|
|
123
|
-
return this._queueRequest(async () => {
|
|
124
|
-
await this.ensureCollection(collection);
|
|
125
|
-
const db = await this._connectionPromise;
|
|
126
|
-
return await db.collection(collection).find(where).toArray();
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
async selectOne(collection, where = {}) {
|
|
131
|
-
return this._queueRequest(async () => {
|
|
132
|
-
await this.ensureCollection(collection);
|
|
133
|
-
const db = await this._connectionPromise;
|
|
134
|
-
return await db.collection(collection).findOne(where);
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
async set(collection, data, where) {
|
|
139
|
-
return this._queueRequest(async () => {
|
|
140
|
-
await this.ensureCollection(collection);
|
|
141
|
-
const db = await this._connectionPromise;
|
|
142
|
-
const existing = await db.collection(collection).findOne(where);
|
|
143
|
-
if (!existing) {
|
|
144
|
-
const result = await db.collection(collection).insertOne({ ...where, ...data });
|
|
145
|
-
return result.insertedId;
|
|
146
|
-
} else {
|
|
147
|
-
const result = await db.collection(collection).updateOne(where, { $set: data });
|
|
148
|
-
return result.modifiedCount;
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Numerik alanları artırır (increment).
|
|
155
|
-
* @param {string} collection - Verinin güncelleneceği koleksiyon adı.
|
|
156
|
-
* @param {object} increments - Artırılacak alanlar ve miktarları.
|
|
157
|
-
* @param {object} where - Güncelleme koşulları.
|
|
158
|
-
* @returns {Promise<number>} Etkilenen belge sayısı.
|
|
159
|
-
*/
|
|
160
|
-
async increment(collection, increments, where = {}) {
|
|
161
|
-
return this._queueRequest(async () => {
|
|
162
|
-
await this.ensureCollection(collection);
|
|
163
|
-
const db = await this._connectionPromise;
|
|
164
|
-
const incObject = {};
|
|
165
|
-
|
|
166
|
-
for (const [field, value] of Object.entries(increments)) {
|
|
167
|
-
incObject[field] = value;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const result = await db.collection(collection).updateMany(where, { $inc: incObject });
|
|
171
|
-
return result.modifiedCount;
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Numerik alanları azaltır (decrement).
|
|
177
|
-
* @param {string} collection - Verinin güncelleneceği koleksiyon adı.
|
|
178
|
-
* @param {object} decrements - Azaltılacak alanlar ve miktarları.
|
|
179
|
-
* @param {object} where - Güncelleme koşulları.
|
|
180
|
-
* @returns {Promise<number>} Etkilenen belge sayısı.
|
|
181
|
-
*/
|
|
182
|
-
async decrement(collection, decrements, where = {}) {
|
|
183
|
-
return this._queueRequest(async () => {
|
|
184
|
-
await this.ensureCollection(collection);
|
|
185
|
-
const db = await this._connectionPromise;
|
|
186
|
-
const incObject = {};
|
|
187
|
-
|
|
188
|
-
// Decrement için negatif değerler kullanıyoruz
|
|
189
|
-
for (const [field, value] of Object.entries(decrements)) {
|
|
190
|
-
incObject[field] = -value;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const result = await db.collection(collection).updateMany(where, { $inc: incObject });
|
|
194
|
-
return result.modifiedCount;
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
async close() {
|
|
199
|
-
await this.client.close();
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
module.exports = MongoDBDatabase;
|