@onurege3467/zerohelper 5.0.3 → 6.0.1
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/data/test_db.json +3 -0
- package/data/test_db.sqlite +0 -0
- package/data/test_db_cached.sqlite +0 -0
- package/database/cacheWrapper.js +121 -0
- package/database/index.js +24 -6
- package/database/{adapters/json.js → json.js} +9 -9
- package/database/{adapters/mongodb.js → mongodb.js} +1 -0
- package/database/{adapters/mysql.js → mysql.js} +12 -12
- package/database/{adapters/sqlite.js → sqlite.js} +86 -77
- package/functions/index.js +14 -4
- package/package.json +4 -3
- package/readme.md +111 -324
- package/test.js +244 -0
- package/database/csvdb/index.js +0 -90
- package/database/jsondatabase/index.js +0 -132
- package/database/migrate/index.js +0 -68
- package/database/mongodb/index.js +0 -49
- package/database/mongodb/src/client/Client.js +0 -37
- package/database/mongodb/src/structers/Collection.js +0 -136
- package/database/mongodb/src/structers/Data.js +0 -282
- package/database/mongodb/src/structers/Database.js +0 -53
- package/database/mongodb/src/tools/FormatTool.js +0 -5
- package/database/mysql/examples/example.js +0 -301
- package/database/mysql/index.js +0 -1
- package/database/mysql/structures/classes/MySQL.js +0 -41
- package/database/mysql/structures/errors/strings.js +0 -23
- package/database/mysql/structures/methods/add.js +0 -19
- package/database/mysql/structures/methods/all.js +0 -25
- package/database/mysql/structures/methods/auto_increment.js +0 -16
- package/database/mysql/structures/methods/base_get.js +0 -14
- package/database/mysql/structures/methods/base_set.js +0 -21
- package/database/mysql/structures/methods/clear.js +0 -16
- package/database/mysql/structures/methods/connect.js +0 -15
- package/database/mysql/structures/methods/create.js +0 -11
- package/database/mysql/structures/methods/create_db.js +0 -10
- package/database/mysql/structures/methods/delete.js +0 -31
- package/database/mysql/structures/methods/drop.js +0 -13
- package/database/mysql/structures/methods/end.js +0 -7
- package/database/mysql/structures/methods/exists.js +0 -15
- package/database/mysql/structures/methods/get.js +0 -40
- package/database/mysql/structures/methods/getAllData.js +0 -35
- package/database/mysql/structures/methods/has.js +0 -42
- package/database/mysql/structures/methods/includes.js +0 -17
- package/database/mysql/structures/methods/ping.js +0 -11
- package/database/mysql/structures/methods/process.js +0 -7
- package/database/mysql/structures/methods/pull.js +0 -23
- package/database/mysql/structures/methods/push.js +0 -23
- package/database/mysql/structures/methods/query.js +0 -9
- package/database/mysql/structures/methods/rename.js +0 -16
- package/database/mysql/structures/methods/set.js +0 -60
- package/database/mysql/structures/methods/stats.js +0 -13
- package/database/mysql/structures/methods/sub.js +0 -19
- package/database/mysql/structures/methods/tables.js +0 -8
- package/database/mysql/structures/methods/variables.js +0 -20
- package/database/newMongoDB/index.js +0 -94
- package/database/newMySQL/index.js +0 -205
- package/database/newSQLite/index.js +0 -240
- package/database/postgresql/index.js +0 -150
- package/database/redis/index.js +0 -125
- package/database/sqldb/index.js +0 -243
- package/database/yamldatabase/index.js +0 -76
- /package/database/{adapters/IDatabase.js → IDatabase.js} +0 -0
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
const { LRUCache } = require('lru-cache');
|
|
2
|
+
|
|
3
|
+
class CacheWrapper {
|
|
4
|
+
constructor(databaseInstance, options = {}) {
|
|
5
|
+
this.db = databaseInstance;
|
|
6
|
+
this.cache = new LRUCache({
|
|
7
|
+
max: options.max || 500, // Maximum number of items in cache
|
|
8
|
+
ttl: options.ttl || 1000 * 60 * 5, // Time to live in ms (5 minutes)
|
|
9
|
+
updateAgeOnGet: options.updateAgeOnGet !== undefined ? options.updateAgeOnGet : false, // Update item age on get
|
|
10
|
+
});
|
|
11
|
+
this.tableCaches = {}; // Cache for each table
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
_getCache(table) {
|
|
15
|
+
if (!this.tableCaches[table]) {
|
|
16
|
+
this.tableCaches[table] = new LRUCache({
|
|
17
|
+
max: this.cache.max,
|
|
18
|
+
ttl: this.cache.ttl,
|
|
19
|
+
updateAgeOnGet: this.cache.updateAgeOnGet,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
return this.tableCaches[table];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
_generateKey(table, where) {
|
|
26
|
+
return `${table}:${JSON.stringify(where || {})}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Read operations
|
|
30
|
+
async select(table, where) {
|
|
31
|
+
const cache = this._getCache(table);
|
|
32
|
+
const key = this._generateKey(table, where);
|
|
33
|
+
let data = cache.get(key);
|
|
34
|
+
|
|
35
|
+
if (data) {
|
|
36
|
+
// console.log(`Cache hit for select: ${key}`);
|
|
37
|
+
return data;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// console.log(`Cache miss for select: ${key}`);
|
|
41
|
+
data = await this.db.select(table, where);
|
|
42
|
+
cache.set(key, data);
|
|
43
|
+
return data;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async selectOne(table, where) {
|
|
47
|
+
const cache = this._getCache(table);
|
|
48
|
+
const key = this._generateKey(table, where);
|
|
49
|
+
let data = cache.get(key);
|
|
50
|
+
|
|
51
|
+
if (data) {
|
|
52
|
+
// console.log(`Cache hit for selectOne: ${key}`);
|
|
53
|
+
return data;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// console.log(`Cache miss for selectOne: ${key}`);
|
|
57
|
+
data = await this.db.selectOne(table, where);
|
|
58
|
+
cache.set(key, data);
|
|
59
|
+
return data;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Write operations (invalidate cache)
|
|
63
|
+
async insert(table, data) {
|
|
64
|
+
this._getCache(table).clear();
|
|
65
|
+
return this.db.insert(table, data);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async update(table, data, where) {
|
|
69
|
+
this._getCache(table).clear();
|
|
70
|
+
return this.db.update(table, data, where);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async set(table, data, where) {
|
|
74
|
+
this._getCache(table).clear();
|
|
75
|
+
return this.db.set(table, data, where);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async delete(table, where) {
|
|
79
|
+
this._getCache(table).clear();
|
|
80
|
+
return this.db.delete(table, where);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async bulkInsert(table, dataArray) {
|
|
84
|
+
this._getCache(table).clear();
|
|
85
|
+
return this.db.bulkInsert(table, dataArray);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async deleteOne(table, where) {
|
|
89
|
+
this._getCache(table).clear();
|
|
90
|
+
return this.db.deleteOne(table, where);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async updateOne(table, data, where) {
|
|
94
|
+
this._getCache(table).clear();
|
|
95
|
+
return this.db.updateOne(table, data, where);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Pass-through for other methods (e.g., close, ensureTable, query for MySQL/SQLite)
|
|
99
|
+
async close() {
|
|
100
|
+
// Clear all caches before closing
|
|
101
|
+
Object.values(this.tableCaches).forEach(cache => cache.clear());
|
|
102
|
+
this.cache.clear();
|
|
103
|
+
return this.db.close();
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Dynamically pass through any other methods not explicitly defined here
|
|
107
|
+
// This ensures compatibility with specific adapter methods (e.g., MySQL's connect, ping)
|
|
108
|
+
// Note: This is a simplified approach. A more robust solution might involve checking
|
|
109
|
+
// if the underlying db instance has the method before calling.
|
|
110
|
+
get(target, prop) {
|
|
111
|
+
if (typeof this[prop] !== 'undefined') {
|
|
112
|
+
return this[prop];
|
|
113
|
+
} else if (typeof this.db[prop] === 'function') {
|
|
114
|
+
return this.db[prop].bind(this.db);
|
|
115
|
+
} else {
|
|
116
|
+
return this.db[prop];
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
module.exports = CacheWrapper;
|
package/database/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
const IDatabase = require('./
|
|
2
|
-
const MySQLDatabase = require('./
|
|
3
|
-
const SQLiteDatabase = require('./
|
|
4
|
-
const MongoDBDatabase = require('./
|
|
5
|
-
const JsonDatabase = require('./
|
|
1
|
+
const IDatabase = require('./IDatabase');
|
|
2
|
+
const MySQLDatabase = require('./mysql');
|
|
3
|
+
const SQLiteDatabase = require('./sqlite');
|
|
4
|
+
const MongoDBDatabase = require('./mongodb');
|
|
5
|
+
const JsonDatabase = require('./json');
|
|
6
|
+
const CacheWrapper = require('./cacheWrapper');
|
|
6
7
|
|
|
7
8
|
const adapters = {
|
|
8
9
|
mysql: MySQLDatabase,
|
|
@@ -35,7 +36,24 @@ function createDatabase(options) {
|
|
|
35
36
|
const DatabaseClass = adapters[adapter];
|
|
36
37
|
|
|
37
38
|
// Sınıfın bir örneğini oluştur ve doğrudan döndür
|
|
38
|
-
|
|
39
|
+
const dbInstance = new DatabaseClass(config);
|
|
40
|
+
|
|
41
|
+
// Eğer cache etkinse, veritabanı örneğini CacheWrapper ile sarmala
|
|
42
|
+
if (config.cache) {
|
|
43
|
+
return new Proxy(new CacheWrapper(dbInstance, config.cache), {
|
|
44
|
+
get: (target, prop) => {
|
|
45
|
+
if (typeof target[prop] !== 'undefined') {
|
|
46
|
+
return target[prop];
|
|
47
|
+
} else if (typeof target.db[prop] === 'function') {
|
|
48
|
+
return target.db[prop].bind(target.db);
|
|
49
|
+
} else {
|
|
50
|
+
return target.db[prop];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return dbInstance;
|
|
39
57
|
}
|
|
40
58
|
|
|
41
59
|
// Artık varsayılan olarak bu fonksiyonu export ediyoruz.
|
|
@@ -111,7 +111,7 @@ class JsonDatabase extends IDatabase{
|
|
|
111
111
|
async ensureTable(table) {
|
|
112
112
|
await this.initPromise;
|
|
113
113
|
if (!this.db[table]) {
|
|
114
|
-
return this.
|
|
114
|
+
return this._queueRequest(() => {
|
|
115
115
|
this.db[table] = [];
|
|
116
116
|
});
|
|
117
117
|
}
|
|
@@ -119,7 +119,7 @@ class JsonDatabase extends IDatabase{
|
|
|
119
119
|
|
|
120
120
|
async insert(table, data) {
|
|
121
121
|
await this.ensureTable(table);
|
|
122
|
-
return this.
|
|
122
|
+
return this._queueRequest(() => {
|
|
123
123
|
const maxId = this.db[table].reduce((max, row) => (row._id > max ? row._id : max), 0);
|
|
124
124
|
const newId = maxId + 1;
|
|
125
125
|
const newRow = { _id: newId, ...data };
|
|
@@ -130,7 +130,7 @@ class JsonDatabase extends IDatabase{
|
|
|
130
130
|
|
|
131
131
|
async update(table, data, where) {
|
|
132
132
|
await this.ensureTable(table);
|
|
133
|
-
return this.
|
|
133
|
+
return this._queueRequest(() => {
|
|
134
134
|
let affectedRows = 0;
|
|
135
135
|
this.db[table].forEach(row => {
|
|
136
136
|
if (this._matches(row, where)) {
|
|
@@ -144,7 +144,7 @@ class JsonDatabase extends IDatabase{
|
|
|
144
144
|
|
|
145
145
|
async delete(table, where) {
|
|
146
146
|
await this.ensureTable(table);
|
|
147
|
-
return this.
|
|
147
|
+
return this._queueRequest(() => {
|
|
148
148
|
const initialLength = this.db[table].length;
|
|
149
149
|
this.db[table] = this.db[table].filter(row => !this._matches(row, where));
|
|
150
150
|
return initialLength - this.db[table].length;
|
|
@@ -179,32 +179,32 @@ class JsonDatabase extends IDatabase{
|
|
|
179
179
|
|
|
180
180
|
async deleteOne(table, where) {
|
|
181
181
|
await this.ensureTable(table);
|
|
182
|
-
return this.
|
|
182
|
+
return this._queueRequest(() => {
|
|
183
183
|
const index = this.db[table].findIndex(row => this._matches(row, where));
|
|
184
184
|
if (index > -1) {
|
|
185
185
|
this.db[table].splice(index, 1);
|
|
186
186
|
return 1; // 1 satır etkilendi
|
|
187
187
|
}
|
|
188
|
-
return 0; // Hiçbir satır
|
|
188
|
+
return 0; // Hiçbir satır etkilendi
|
|
189
189
|
});
|
|
190
190
|
}
|
|
191
191
|
|
|
192
192
|
async updateOne(table, data, where) {
|
|
193
193
|
await this.ensureTable(table);
|
|
194
|
-
return this.
|
|
194
|
+
return this._queueRequest(() => {
|
|
195
195
|
const row = this.db[table].find(row => this._matches(row, where));
|
|
196
196
|
if (row) {
|
|
197
197
|
Object.assign(row, data);
|
|
198
198
|
return 1; // 1 satır etkilendi
|
|
199
199
|
}
|
|
200
|
-
return 0; // Hiçbir satır
|
|
200
|
+
return 0; // Hiçbir satır etkilendi
|
|
201
201
|
});
|
|
202
202
|
}
|
|
203
203
|
|
|
204
204
|
async bulkInsert(table, dataArray) {
|
|
205
205
|
if (!Array.isArray(dataArray) || dataArray.length === 0) return 0;
|
|
206
206
|
await this.ensureTable(table);
|
|
207
|
-
return this.
|
|
207
|
+
return this._queueRequest(() => {
|
|
208
208
|
let maxId = this.db[table].reduce((max, row) => (row._id > max ? row._id : max), 0);
|
|
209
209
|
dataArray.forEach(data => {
|
|
210
210
|
maxId++;
|
|
@@ -80,7 +80,7 @@ class MySQLDatabase extends IDatabase{
|
|
|
80
80
|
|
|
81
81
|
async ensureTable(table, data = {}) {
|
|
82
82
|
return this._queueRequest(async () => {
|
|
83
|
-
|
|
83
|
+
|
|
84
84
|
|
|
85
85
|
const escapedTable = mysql.escape(table);
|
|
86
86
|
const tables = await this.query(`SHOW TABLES LIKE ${escapedTable}`);
|
|
@@ -124,20 +124,20 @@ class MySQLDatabase extends IDatabase{
|
|
|
124
124
|
async update(table, data, where) {
|
|
125
125
|
return this._queueRequest(async () => {
|
|
126
126
|
await this.ensureTable(table, { ...data, ...where });
|
|
127
|
-
const existingColumns = await this.query(`DESCRIBE
|
|
127
|
+
const existingColumns = await this.query(`DESCRIBE \`${table}\``).catch(() => null);
|
|
128
128
|
if (!existingColumns) throw new Error(`Table ${table} does not exist.`);
|
|
129
129
|
|
|
130
130
|
const existingColumnNames = existingColumns.map(col => col.Field);
|
|
131
131
|
for (const key of Object.keys(data)) {
|
|
132
132
|
if (!existingColumnNames.includes(key)) {
|
|
133
|
-
const alterSQL = `ALTER TABLE
|
|
133
|
+
const alterSQL = `ALTER TABLE \`${table}\` ADD COLUMN \`${key}\` VARCHAR(255)`;
|
|
134
134
|
await this.query(alterSQL);
|
|
135
135
|
console.log(`Added missing column '${key}' to table '${table}'`);
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
|
-
const setString = Object.keys(data).map(k =>
|
|
139
|
-
const whereString = Object.keys(where).map(k =>
|
|
140
|
-
const sql = `UPDATE
|
|
138
|
+
const setString = Object.keys(data).map(k => `\`${k}\` = ?`).join(", ");
|
|
139
|
+
const whereString = Object.keys(where).map(k => `\`${k}\` = ?`).join(" AND ");
|
|
140
|
+
const sql = `UPDATE \`${table}\` SET ${setString} WHERE ${whereString}`;
|
|
141
141
|
const result = await this.query(sql, [...Object.values(data), ...Object.values(where)]);
|
|
142
142
|
return result.affectedRows;
|
|
143
143
|
});
|
|
@@ -157,11 +157,11 @@ class MySQLDatabase extends IDatabase{
|
|
|
157
157
|
async select(table, where = null) {
|
|
158
158
|
return this._queueRequest(async () => {
|
|
159
159
|
await this.ensureTable(table, where || {});
|
|
160
|
-
let sql = `SELECT * FROM
|
|
160
|
+
let sql = `SELECT * FROM \`${table}\``;
|
|
161
161
|
let params = [];
|
|
162
162
|
|
|
163
163
|
if (where && Object.keys(where).length > 0) {
|
|
164
|
-
const whereString = Object.keys(where).map(k =>
|
|
164
|
+
const whereString = Object.keys(where).map(k => `\`${k}\` = ?`).join(" AND ");
|
|
165
165
|
sql += ` WHERE ${whereString}`;
|
|
166
166
|
params = Object.values(where);
|
|
167
167
|
}
|
|
@@ -238,20 +238,20 @@ class MySQLDatabase extends IDatabase{
|
|
|
238
238
|
if (!Array.isArray(dataArray) || dataArray.length === 0) return 0;
|
|
239
239
|
await this.ensureTable(table, dataArray[0]);
|
|
240
240
|
|
|
241
|
-
const existingColumns = await this.query(`DESCRIBE
|
|
241
|
+
const existingColumns = await this.query(`DESCRIBE \`${table}\``);
|
|
242
242
|
const existingColumnNames = existingColumns.map(col => col.Field);
|
|
243
243
|
const keys = Object.keys(dataArray[0]);
|
|
244
244
|
|
|
245
245
|
// Eksik kolonları sadece ilk elemana göre kontrol et
|
|
246
246
|
for (const key of keys) {
|
|
247
247
|
if (!existingColumnNames.includes(key)) {
|
|
248
|
-
await this.query(`ALTER TABLE
|
|
248
|
+
await this.query(`ALTER TABLE \`${table}\` ADD COLUMN \`${key}\` VARCHAR(255)`);
|
|
249
249
|
}
|
|
250
250
|
}
|
|
251
251
|
|
|
252
252
|
const placeholders = dataArray.map(() => `(${keys.map(() => '?').join(',')})`).join(',');
|
|
253
253
|
const values = dataArray.flatMap(obj => keys.map(k => obj[k]));
|
|
254
|
-
const sql = `INSERT INTO
|
|
254
|
+
const sql = `INSERT INTO \`${table}\` (${keys.map(k => `\`${k}\``).join(",")}) VALUES ${placeholders}`;
|
|
255
255
|
|
|
256
256
|
const result = await this.query(sql, values);
|
|
257
257
|
return result.affectedRows;
|
|
@@ -263,4 +263,4 @@ class MySQLDatabase extends IDatabase{
|
|
|
263
263
|
}
|
|
264
264
|
}
|
|
265
265
|
|
|
266
|
-
module.exports = MySQLDatabase;
|
|
266
|
+
module.exports = MySQLDatabase;
|
|
@@ -3,7 +3,7 @@ const IDatabase = require('./IDatabase'); // Arayüzü import et
|
|
|
3
3
|
/**
|
|
4
4
|
* @implements {IDatabase}
|
|
5
5
|
*/
|
|
6
|
-
const
|
|
6
|
+
const sqlite3 = require('sqlite3').verbose();
|
|
7
7
|
const fs = require('fs');
|
|
8
8
|
const path = require('path');
|
|
9
9
|
|
|
@@ -24,28 +24,36 @@ class SQLiteDatabase extends IDatabase{
|
|
|
24
24
|
fs.mkdirSync(dir, { recursive: true });
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
this.db = new sqlite3.Database(config.filePath, (err) => {
|
|
28
|
+
if (err) {
|
|
29
|
+
console.error("SQLite connection error:", err.message);
|
|
30
|
+
} else {
|
|
31
|
+
console.log('Connected to the SQLite database.');
|
|
32
|
+
}
|
|
33
|
+
});
|
|
29
34
|
}
|
|
30
35
|
|
|
31
36
|
/**
|
|
32
|
-
* SQL sorgusu çalıştırır.
|
|
37
|
+
* SQL sorgusu çalıştırır. Promise döndürür.
|
|
33
38
|
* @param {string} sql - Çalıştırılacak SQL sorgusu.
|
|
34
39
|
* @param {Array} params - Sorgu parametreleri.
|
|
35
40
|
*/
|
|
36
41
|
query(sql, params = []) {
|
|
37
|
-
|
|
38
|
-
// SELECT sorguları için .all() kullanılır
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
return new Promise((resolve, reject) => {
|
|
43
|
+
// SELECT sorguları için .all() kullanılır
|
|
44
|
+
if (sql.trim().toUpperCase().startsWith('SELECT') || sql.trim().toUpperCase().startsWith('PRAGMA')) {
|
|
45
|
+
this.db.all(sql, params, (err, rows) => {
|
|
46
|
+
if (err) reject(err);
|
|
47
|
+
else resolve(rows);
|
|
48
|
+
});
|
|
49
|
+
} else {
|
|
50
|
+
// INSERT, UPDATE, DELETE gibi sorgular için .run() kullanılır
|
|
51
|
+
this.db.run(sql, params, function (err) {
|
|
52
|
+
if (err) reject(err);
|
|
53
|
+
else resolve({ changes: this.changes, lastInsertRowid: this.lastID });
|
|
54
|
+
});
|
|
45
55
|
}
|
|
46
|
-
|
|
47
|
-
throw error;
|
|
48
|
-
}
|
|
56
|
+
});
|
|
49
57
|
}
|
|
50
58
|
|
|
51
59
|
/**
|
|
@@ -53,16 +61,13 @@ class SQLiteDatabase extends IDatabase{
|
|
|
53
61
|
* @param {string} table - Tablo adı.
|
|
54
62
|
* @param {object} data - Tablo oluşturulurken sütunları belirlemek için örnek veri.
|
|
55
63
|
*/
|
|
56
|
-
ensureTable(table, data = {}) {
|
|
57
|
-
|
|
64
|
+
async ensureTable(table, data = {}) {
|
|
65
|
+
|
|
58
66
|
|
|
59
67
|
try {
|
|
60
|
-
|
|
61
|
-
this.db.prepare(`SELECT 1 FROM \`${table}\` LIMIT 1`).get();
|
|
68
|
+
await this.query(`SELECT 1 FROM \`${table}\` LIMIT 1`);
|
|
62
69
|
} catch (error) {
|
|
63
|
-
// "no such table" hatası alırsak, tabloyu oluştur.
|
|
64
70
|
if (error.message.includes('no such table')) {
|
|
65
|
-
// SQLite tipleri esnek olduğu için TEXT çoğu veri tipi için yeterlidir.
|
|
66
71
|
const columns = Object.keys(data).map(col => `\`${col}\` TEXT`).join(', ');
|
|
67
72
|
const createTableSQL = `
|
|
68
73
|
CREATE TABLE \`${table}\` (
|
|
@@ -70,7 +75,7 @@ class SQLiteDatabase extends IDatabase{
|
|
|
70
75
|
${columns}
|
|
71
76
|
)
|
|
72
77
|
`;
|
|
73
|
-
this.query(createTableSQL);
|
|
78
|
+
await this.query(createTableSQL);
|
|
74
79
|
} else {
|
|
75
80
|
throw error;
|
|
76
81
|
}
|
|
@@ -81,69 +86,69 @@ class SQLiteDatabase extends IDatabase{
|
|
|
81
86
|
* Verilen verideki anahtarların tabloda sütun olarak var olduğundan emin olur.
|
|
82
87
|
* @private
|
|
83
88
|
*/
|
|
84
|
-
_ensureColumns(table, data) {
|
|
85
|
-
const columnsInfo = this.
|
|
89
|
+
async _ensureColumns(table, data) {
|
|
90
|
+
const columnsInfo = await this.query(`PRAGMA table_info(\`${table}\`)`);
|
|
86
91
|
const existingNames = columnsInfo.map(col => col.name);
|
|
87
92
|
|
|
88
93
|
for (const key of Object.keys(data)) {
|
|
89
94
|
if (!existingNames.includes(key)) {
|
|
90
|
-
this.query(`ALTER TABLE \`${table}\` ADD COLUMN \`${key}\` TEXT`);
|
|
95
|
+
await this.query(`ALTER TABLE \`${table}\` ADD COLUMN \`${key}\` TEXT`);
|
|
91
96
|
}
|
|
92
97
|
}
|
|
93
98
|
}
|
|
94
99
|
|
|
95
100
|
/**
|
|
96
101
|
* Bir tabloya yeni veri ekler.
|
|
97
|
-
* @returns {number} Eklenen satırın ID'si.
|
|
102
|
+
* @returns {Promise<number>} Eklenen satırın ID'si.
|
|
98
103
|
*/
|
|
99
|
-
insert(table, data) {
|
|
104
|
+
async insert(table, data) {
|
|
100
105
|
const copy = { ...data };
|
|
101
|
-
this.ensureTable(table, copy);
|
|
102
|
-
this._ensureColumns(table, copy);
|
|
106
|
+
await this.ensureTable(table, copy);
|
|
107
|
+
await this._ensureColumns(table, copy);
|
|
103
108
|
|
|
104
109
|
const keys = Object.keys(copy);
|
|
105
110
|
const placeholders = keys.map(() => '?').join(',');
|
|
106
111
|
const values = Object.values(copy);
|
|
107
112
|
const sql = `INSERT INTO \`${table}\` (${keys.map(k => `\`${k}\``).join(',')}) VALUES (${placeholders})`;
|
|
108
113
|
|
|
109
|
-
const result = this.query(sql, values);
|
|
110
|
-
return result.lastInsertRowid;
|
|
114
|
+
const result = await this.query(sql, values);
|
|
115
|
+
return result.lastInsertRowid;
|
|
111
116
|
}
|
|
112
117
|
|
|
113
118
|
/**
|
|
114
119
|
* Tablodaki verileri günceller.
|
|
115
|
-
* @returns {number} Etkilenen satır sayısı.
|
|
120
|
+
* @returns {Promise<number>} Etkilenen satır sayısı.
|
|
116
121
|
*/
|
|
117
|
-
update(table, data, where) {
|
|
118
|
-
this.ensureTable(table, { ...data, ...where });
|
|
119
|
-
this._ensureColumns(table, data);
|
|
122
|
+
async update(table, data, where) {
|
|
123
|
+
await this.ensureTable(table, { ...data, ...where });
|
|
124
|
+
await this._ensureColumns(table, data);
|
|
120
125
|
|
|
121
126
|
const setString = Object.keys(data).map(k => `\`${k}\` = ?`).join(', ');
|
|
122
127
|
const whereString = Object.keys(where).map(k => `\`${k}\` = ?`).join(' AND ');
|
|
123
128
|
const sql = `UPDATE \`${table}\` SET ${setString} WHERE ${whereString}`;
|
|
124
|
-
const result = this.query(sql, [...Object.values(data), ...Object.values(where)]);
|
|
125
|
-
return result.changes;
|
|
129
|
+
const result = await this.query(sql, [...Object.values(data), ...Object.values(where)]);
|
|
130
|
+
return result.changes;
|
|
126
131
|
}
|
|
127
132
|
|
|
128
133
|
/**
|
|
129
134
|
* Tablodan veri siler.
|
|
130
|
-
* @returns {number} Etkilenen satır sayısı.
|
|
135
|
+
* @returns {Promise<number>} Etkilenen satır sayısı.
|
|
131
136
|
*/
|
|
132
|
-
delete(table, where) {
|
|
137
|
+
async delete(table, where) {
|
|
133
138
|
if (!where || Object.keys(where).length === 0) return 0;
|
|
134
|
-
this.ensureTable(table, { ...where });
|
|
139
|
+
await this.ensureTable(table, { ...where });
|
|
135
140
|
const whereString = Object.keys(where).map(k => `\`${k}\` = ?`).join(' AND ');
|
|
136
141
|
const sql = `DELETE FROM \`${table}\` WHERE ${whereString}`;
|
|
137
|
-
const result = this.query(sql, Object.values(where));
|
|
142
|
+
const result = await this.query(sql, Object.values(where));
|
|
138
143
|
return result.changes;
|
|
139
144
|
}
|
|
140
145
|
|
|
141
146
|
/**
|
|
142
147
|
* Tablodan veri seçer.
|
|
143
|
-
* @returns {Array<object
|
|
148
|
+
* @returns {Promise<Array<object>>} Sonuç satırları.
|
|
144
149
|
*/
|
|
145
|
-
select(table, where = null) {
|
|
146
|
-
this.ensureTable(table, where || {});
|
|
150
|
+
async select(table, where = null) {
|
|
151
|
+
await this.ensureTable(table, where || {});
|
|
147
152
|
let sql = `SELECT * FROM \`${table}\``;
|
|
148
153
|
let params = [];
|
|
149
154
|
|
|
@@ -153,92 +158,96 @@ class SQLiteDatabase extends IDatabase{
|
|
|
153
158
|
params = Object.values(where);
|
|
154
159
|
}
|
|
155
160
|
|
|
156
|
-
return this.query(sql, params);
|
|
161
|
+
return await this.query(sql, params);
|
|
157
162
|
}
|
|
158
163
|
|
|
159
164
|
/**
|
|
160
165
|
* Veri varsa günceller, yoksa ekler (upsert).
|
|
161
166
|
*/
|
|
162
|
-
set(table, data, where) {
|
|
163
|
-
this.ensureTable(table, { ...data, ...where });
|
|
164
|
-
this._ensureColumns(table, data);
|
|
165
|
-
const existing = this.select(table, where);
|
|
167
|
+
async set(table, data, where) {
|
|
168
|
+
await this.ensureTable(table, { ...data, ...where });
|
|
169
|
+
await this._ensureColumns(table, data);
|
|
170
|
+
const existing = await this.select(table, where);
|
|
166
171
|
if (existing.length === 0) {
|
|
167
|
-
return this.insert(table, { ...where, ...data });
|
|
172
|
+
return await this.insert(table, { ...where, ...data });
|
|
168
173
|
} else {
|
|
169
|
-
return this.update(table, data, where);
|
|
174
|
+
return await this.update(table, data, where);
|
|
170
175
|
}
|
|
171
176
|
}
|
|
172
177
|
|
|
173
178
|
/**
|
|
174
179
|
* Koşula uyan ilk veriyi seçer.
|
|
175
|
-
* @returns {object|null} Bulunan satır veya null.
|
|
180
|
+
* @returns {Promise<object|null>} Bulunan satır veya null.
|
|
176
181
|
*/
|
|
177
|
-
selectOne(table, where = null) {
|
|
178
|
-
const results = this.select(table, where);
|
|
182
|
+
async selectOne(table, where = null) {
|
|
183
|
+
const results = await this.select(table, where);
|
|
179
184
|
return results[0] || null;
|
|
180
185
|
}
|
|
181
186
|
|
|
182
187
|
/**
|
|
183
188
|
* Koşula uyan ilk veriyi siler.
|
|
184
|
-
* @returns {number} Etkilenen satır sayısı (0 veya 1).
|
|
189
|
+
* @returns {Promise<number>} Etkilenen satır sayısı (0 veya 1).
|
|
185
190
|
*/
|
|
186
|
-
deleteOne(table, where) {
|
|
191
|
+
async deleteOne(table, where) {
|
|
187
192
|
if (!where || Object.keys(where).length === 0) return 0;
|
|
188
|
-
this.ensureTable(table, where);
|
|
193
|
+
await this.ensureTable(table, where);
|
|
189
194
|
const whereString = Object.keys(where).map(k => `\`${k}\` = ?`).join(' AND ');
|
|
190
195
|
const sql = `DELETE FROM \`${table}\` WHERE rowid IN (SELECT rowid FROM \`${table}\` WHERE ${whereString} LIMIT 1)`;
|
|
191
|
-
const result = this.query(sql, Object.values(where));
|
|
196
|
+
const result = await this.query(sql, Object.values(where));
|
|
192
197
|
return result.changes;
|
|
193
198
|
}
|
|
194
199
|
|
|
195
200
|
/**
|
|
196
201
|
* Koşula uyan ilk veriyi günceller.
|
|
197
|
-
* @returns {number} Etkilenen satır sayısı (0 veya 1).
|
|
202
|
+
* @returns {Promise<number>} Etkilenen satır sayısı (0 veya 1).
|
|
198
203
|
*/
|
|
199
|
-
updateOne(table, data, where) {
|
|
200
|
-
this.ensureTable(table, { ...data, ...where });
|
|
201
|
-
this._ensureColumns(table, data);
|
|
204
|
+
async updateOne(table, data, where) {
|
|
205
|
+
await this.ensureTable(table, { ...data, ...where });
|
|
206
|
+
await this._ensureColumns(table, data);
|
|
202
207
|
const setString = Object.keys(data).map(k => `\`${k}\` = ?`).join(', ');
|
|
203
208
|
const whereString = Object.keys(where).map(k => `\`${k}\` = ?`).join(' AND ');
|
|
204
209
|
const sql = `UPDATE \`${table}\` SET ${setString} WHERE rowid IN (SELECT rowid FROM \`${table}\` WHERE ${whereString} LIMIT 1)`;
|
|
205
|
-
const result = this.query(sql, [...Object.values(data), ...Object.values(where)]);
|
|
210
|
+
const result = await this.query(sql, [...Object.values(data), ...Object.values(where)]);
|
|
206
211
|
return result.changes;
|
|
207
212
|
}
|
|
208
213
|
|
|
209
214
|
/**
|
|
210
215
|
* Toplu veri ekleme.
|
|
211
|
-
* @returns {number} Eklenen satır sayısı.
|
|
216
|
+
* @returns {Promise<number>} Eklenen satır sayısı.
|
|
212
217
|
*/
|
|
213
|
-
bulkInsert(table, dataArray) {
|
|
218
|
+
async bulkInsert(table, dataArray) {
|
|
214
219
|
if (!Array.isArray(dataArray) || dataArray.length === 0) return 0;
|
|
215
|
-
this.ensureTable(table, dataArray[0]);
|
|
216
|
-
this._ensureColumns(table, dataArray[0]);
|
|
220
|
+
await this.ensureTable(table, dataArray[0]);
|
|
221
|
+
await this._ensureColumns(table, dataArray[0]);
|
|
217
222
|
|
|
218
223
|
const keys = Object.keys(dataArray[0]);
|
|
219
224
|
const placeholders = keys.map(() => '?').join(',');
|
|
220
225
|
const sql = `INSERT INTO \`${table}\` (${keys.map(k => `\`${k}\``).join(',')}) VALUES (${placeholders})`;
|
|
221
226
|
|
|
222
|
-
//
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
227
|
+
// sqlite3'te toplu ekleme için transaction kullanabiliriz
|
|
228
|
+
const stmt = this.db.prepare(sql);
|
|
229
|
+
this.db.serialize(() => {
|
|
230
|
+
this.db.run("BEGIN TRANSACTION;");
|
|
231
|
+
for (const item of dataArray) {
|
|
226
232
|
stmt.run(Object.values(item));
|
|
227
233
|
}
|
|
234
|
+
this.db.run("COMMIT;");
|
|
228
235
|
});
|
|
229
236
|
|
|
230
|
-
insertMany(dataArray);
|
|
231
237
|
return dataArray.length;
|
|
232
238
|
}
|
|
233
239
|
|
|
234
240
|
/**
|
|
235
241
|
* Veritabanı bağlantısını kapatır.
|
|
236
242
|
*/
|
|
237
|
-
close() {
|
|
238
|
-
|
|
239
|
-
this.db.close()
|
|
240
|
-
|
|
243
|
+
async close() {
|
|
244
|
+
return new Promise((resolve, reject) => {
|
|
245
|
+
this.db.close((err) => {
|
|
246
|
+
if (err) reject(err);
|
|
247
|
+
else resolve();
|
|
248
|
+
});
|
|
249
|
+
});
|
|
241
250
|
}
|
|
242
251
|
}
|
|
243
252
|
|
|
244
|
-
module.exports = SQLiteDatabase;
|
|
253
|
+
module.exports = SQLiteDatabase;
|
package/functions/index.js
CHANGED
|
@@ -124,15 +124,25 @@ function deepMerge(obj1, obj2) {
|
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
// Şifreleme ve Güvenlik
|
|
127
|
+
function getKeyFromSecret(secret) {
|
|
128
|
+
// Use a fixed salt for simplicity in testing. In production, use a unique salt per encryption.
|
|
129
|
+
const salt = Buffer.from('some_fixed_salt_for_testing_only', 'utf8');
|
|
130
|
+
return crypto.pbkdf2Sync(secret, salt, 100000, 32, 'sha512'); // 32 bytes for AES-256
|
|
131
|
+
}
|
|
132
|
+
|
|
127
133
|
function encryptText(text, secret) {
|
|
128
|
-
const
|
|
134
|
+
const key = getKeyFromSecret(secret);
|
|
135
|
+
const iv = crypto.randomBytes(16); // Initialization vector
|
|
136
|
+
const cipher = crypto.createCipheriv("aes-256-cbc", key, iv);
|
|
129
137
|
let encrypted = cipher.update(text, "utf8", "hex");
|
|
130
138
|
encrypted += cipher.final("hex");
|
|
131
|
-
return encrypted;
|
|
139
|
+
return { encryptedText: encrypted, iv: iv.toString('hex') };
|
|
132
140
|
}
|
|
133
141
|
|
|
134
|
-
function decryptText(encryptedText, secret) {
|
|
135
|
-
const
|
|
142
|
+
function decryptText(encryptedText, secret, ivHex) {
|
|
143
|
+
const key = getKeyFromSecret(secret);
|
|
144
|
+
const iv = Buffer.from(ivHex, 'hex');
|
|
145
|
+
const decipher = crypto.createDecipheriv("aes-256-cbc", key, iv);
|
|
136
146
|
let decrypted = decipher.update(encryptedText, "hex", "utf8");
|
|
137
147
|
decrypted += decipher.final("utf8");
|
|
138
148
|
return decrypted;
|