@onurege3467/zerohelper 7.0.0 → 7.2.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.
@@ -92,6 +92,11 @@ class SQLiteDatabase extends IDatabase{
92
92
  }
93
93
  }
94
94
 
95
+ // Object ve Array kontrolü
96
+ if (typeof value === 'object') {
97
+ return 'TEXT'; // SQLite'da JSON olarak string halinde saklanacak
98
+ }
99
+
95
100
  // Varsayılan olarak TEXT
96
101
  return 'TEXT';
97
102
  }
@@ -120,6 +125,24 @@ class SQLiteDatabase extends IDatabase{
120
125
  return bestType || 'TEXT';
121
126
  }
122
127
 
128
+ /**
129
+ * Eksik kolonları kontrol eder ve ekler
130
+ * @param {string} table - Tablo adı
131
+ * @param {object} data - Kontrol edilecek veri
132
+ */
133
+ async _ensureMissingColumns(table, data) {
134
+ const columnsInfo = await this.query(`PRAGMA table_info(\`${table}\`)`);
135
+ const existingNames = columnsInfo.map(col => col.name);
136
+
137
+ for (const key of Object.keys(data)) {
138
+ if (!existingNames.includes(key)) {
139
+ const columnType = this._detectColumnType(data[key]);
140
+ await this.query(`ALTER TABLE \`${table}\` ADD COLUMN \`${key}\` ${columnType}`);
141
+ console.log(`Added missing column '${key}' to table '${table}' with type ${columnType}`);
142
+ }
143
+ }
144
+ }
145
+
123
146
  /**
124
147
  * SQL sorgusu çalıştırır. Promise döndürür.
125
148
  * @param {string} sql - Çalıştırılacak SQL sorgusu.
@@ -179,17 +202,43 @@ class SQLiteDatabase extends IDatabase{
179
202
  /**
180
203
  * Verilen verideki anahtarların tabloda sütun olarak var olduğundan emin olur.
181
204
  * @private
205
+ * @deprecated Bu fonksiyon yerine _ensureMissingColumns kullanılıyor
182
206
  */
183
207
  async _ensureColumns(table, data) {
184
- const columnsInfo = await this.query(`PRAGMA table_info(\`${table}\`)`);
185
- const existingNames = columnsInfo.map(col => col.name);
208
+ return this._ensureMissingColumns(table, data);
209
+ }
186
210
 
187
- for (const key of Object.keys(data)) {
188
- if (!existingNames.includes(key)) {
189
- const columnType = this._detectColumnType(data[key]);
190
- await this.query(`ALTER TABLE \`${table}\` ADD COLUMN \`${key}\` ${columnType}`);
211
+ /**
212
+ * Değeri serileştir (JSON objeler için)
213
+ */
214
+ _serializeValue(value) {
215
+ if (value instanceof Date) {
216
+ return value.toISOString();
217
+ }
218
+ if (Array.isArray(value) || (typeof value === 'object' && value !== null)) {
219
+ return JSON.stringify(value);
220
+ }
221
+ return value;
222
+ }
223
+
224
+ /**
225
+ * Değeri deserileştir (JSON objeler için)
226
+ */
227
+ _deserializeValue(value) {
228
+ if (typeof value === 'string') {
229
+ try {
230
+ // JSON string olup olmadığını kontrol et
231
+ if (value.startsWith('[') || value.startsWith('{')) {
232
+ const parsed = JSON.parse(value);
233
+ if (typeof parsed === 'object' && parsed !== null) {
234
+ return parsed;
235
+ }
236
+ }
237
+ } catch (e) {
238
+ // JSON parse hatası, orijinal değeri döndür
191
239
  }
192
240
  }
241
+ return value;
193
242
  }
194
243
 
195
244
  /**
@@ -199,11 +248,13 @@ class SQLiteDatabase extends IDatabase{
199
248
  async insert(table, data) {
200
249
  const copy = { ...data };
201
250
  await this.ensureTable(table, copy);
202
- await this._ensureColumns(table, copy);
251
+
252
+ // Eksik kolonları ekle
253
+ await this._ensureMissingColumns(table, copy);
203
254
 
204
255
  const keys = Object.keys(copy);
205
256
  const placeholders = keys.map(() => '?').join(',');
206
- const values = Object.values(copy);
257
+ const values = Object.values(copy).map(v => this._serializeValue(v));
207
258
  const sql = `INSERT INTO \`${table}\` (${keys.map(k => `\`${k}\``).join(',')}) VALUES (${placeholders})`;
208
259
 
209
260
  const result = await this.query(sql, values);
@@ -216,12 +267,14 @@ class SQLiteDatabase extends IDatabase{
216
267
  */
217
268
  async update(table, data, where) {
218
269
  await this.ensureTable(table, { ...data, ...where });
219
- await this._ensureColumns(table, data);
270
+
271
+ // Eksik kolonları ekle
272
+ await this._ensureMissingColumns(table, { ...data, ...where });
220
273
 
221
274
  const setString = Object.keys(data).map(k => `\`${k}\` = ?`).join(', ');
222
275
  const whereString = Object.keys(where).map(k => `\`${k}\` = ?`).join(' AND ');
223
276
  const sql = `UPDATE \`${table}\` SET ${setString} WHERE ${whereString}`;
224
- const result = await this.query(sql, [...Object.values(data), ...Object.values(where)]);
277
+ const result = await this.query(sql, [...Object.values(data).map(v => this._serializeValue(v)), ...Object.values(where).map(v => this._serializeValue(v))]);
225
278
  return result.changes;
226
279
  }
227
280
 
@@ -232,9 +285,13 @@ class SQLiteDatabase extends IDatabase{
232
285
  async delete(table, where) {
233
286
  if (!where || Object.keys(where).length === 0) return 0;
234
287
  await this.ensureTable(table, { ...where });
288
+
289
+ // Eksik kolonları ekle (where koşulları için)
290
+ await this._ensureMissingColumns(table, where);
291
+
235
292
  const whereString = Object.keys(where).map(k => `\`${k}\` = ?`).join(' AND ');
236
293
  const sql = `DELETE FROM \`${table}\` WHERE ${whereString}`;
237
- const result = await this.query(sql, Object.values(where));
294
+ const result = await this.query(sql, Object.values(where).map(v => this._serializeValue(v)));
238
295
  return result.changes;
239
296
  }
240
297
 
@@ -244,16 +301,29 @@ class SQLiteDatabase extends IDatabase{
244
301
  */
245
302
  async select(table, where = null) {
246
303
  await this.ensureTable(table, where || {});
304
+
305
+ // Eğer where koşulu varsa, eksik kolonları ekle
306
+ if (where && Object.keys(where).length > 0) {
307
+ await this._ensureMissingColumns(table, where);
308
+ }
309
+
247
310
  let sql = `SELECT * FROM \`${table}\``;
248
311
  let params = [];
249
312
 
250
313
  if (where && Object.keys(where).length > 0) {
251
314
  const whereString = Object.keys(where).map(k => `\`${k}\` = ?`).join(' AND ');
252
315
  sql += ` WHERE ${whereString}`;
253
- params = Object.values(where);
316
+ params = Object.values(where).map(v => this._serializeValue(v));
254
317
  }
255
318
 
256
- return await this.query(sql, params);
319
+ const rows = await this.query(sql, params);
320
+ return rows.map(row => {
321
+ const newRow = {};
322
+ for (const key in row) {
323
+ newRow[key] = this._deserializeValue(row[key]);
324
+ }
325
+ return newRow;
326
+ });
257
327
  }
258
328
 
259
329
  /**
@@ -261,7 +331,10 @@ class SQLiteDatabase extends IDatabase{
261
331
  */
262
332
  async set(table, data, where) {
263
333
  await this.ensureTable(table, { ...data, ...where });
264
- await this._ensureColumns(table, data);
334
+
335
+ // Eksik kolonları ekle
336
+ await this._ensureMissingColumns(table, { ...data, ...where });
337
+
265
338
  const existing = await this.select(table, where);
266
339
  if (existing.length === 0) {
267
340
  return await this.insert(table, { ...where, ...data });
@@ -286,9 +359,13 @@ class SQLiteDatabase extends IDatabase{
286
359
  async deleteOne(table, where) {
287
360
  if (!where || Object.keys(where).length === 0) return 0;
288
361
  await this.ensureTable(table, where);
362
+
363
+ // Eksik kolonları ekle (where koşulları için)
364
+ await this._ensureMissingColumns(table, where);
365
+
289
366
  const whereString = Object.keys(where).map(k => `\`${k}\` = ?`).join(' AND ');
290
367
  const sql = `DELETE FROM \`${table}\` WHERE rowid IN (SELECT rowid FROM \`${table}\` WHERE ${whereString} LIMIT 1)`;
291
- const result = await this.query(sql, Object.values(where));
368
+ const result = await this.query(sql, Object.values(where).map(v => this._serializeValue(v)));
292
369
  return result.changes;
293
370
  }
294
371
 
@@ -298,11 +375,14 @@ class SQLiteDatabase extends IDatabase{
298
375
  */
299
376
  async updateOne(table, data, where) {
300
377
  await this.ensureTable(table, { ...data, ...where });
301
- await this._ensureColumns(table, data);
378
+
379
+ // Eksik kolonları ekle
380
+ await this._ensureMissingColumns(table, { ...data, ...where });
381
+
302
382
  const setString = Object.keys(data).map(k => `\`${k}\` = ?`).join(', ');
303
383
  const whereString = Object.keys(where).map(k => `\`${k}\` = ?`).join(' AND ');
304
384
  const sql = `UPDATE \`${table}\` SET ${setString} WHERE rowid IN (SELECT rowid FROM \`${table}\` WHERE ${whereString} LIMIT 1)`;
305
- const result = await this.query(sql, [...Object.values(data), ...Object.values(where)]);
385
+ const result = await this.query(sql, [...Object.values(data).map(v => this._serializeValue(v)), ...Object.values(where).map(v => this._serializeValue(v))]);
306
386
  return result.changes;
307
387
  }
308
388
 
@@ -316,26 +396,74 @@ class SQLiteDatabase extends IDatabase{
316
396
  // İlk elemanı tablo oluşturmak için kullan
317
397
  await this.ensureTable(table, dataArray[0]);
318
398
 
319
- // Tüm elemanların sütunlarını kontrol et
320
- for (const item of dataArray) {
321
- await this._ensureColumns(table, item);
399
+ // Tüm datalardan gelen tüm anahtarları topla
400
+ const allKeys = new Set();
401
+ dataArray.forEach(obj => {
402
+ Object.keys(obj).forEach(key => allKeys.add(key));
403
+ });
404
+
405
+ // Tüm eksik kolonları ekle
406
+ for (const key of allKeys) {
407
+ const columnsInfo = await this.query(`PRAGMA table_info(\`${table}\`)`);
408
+ const existingNames = columnsInfo.map(col => col.name);
409
+
410
+ if (!existingNames.includes(key)) {
411
+ // Tüm değerleri kontrol ederek en uygun türü belirle
412
+ const columnValues = dataArray
413
+ .map(obj => obj[key])
414
+ .filter(val => val !== undefined && val !== null);
415
+ const columnType = columnValues.length > 0 ? this._determineBestColumnType(columnValues) : 'TEXT';
416
+ await this.query(`ALTER TABLE \`${table}\` ADD COLUMN \`${key}\` ${columnType}`);
417
+ console.log(`Added missing column '${key}' to table '${table}' with type ${columnType}`);
418
+ }
322
419
  }
323
420
 
324
- const keys = Object.keys(dataArray[0]);
421
+ const keys = Array.from(allKeys);
325
422
  const placeholders = keys.map(() => '?').join(',');
326
423
  const sql = `INSERT INTO \`${table}\` (${keys.map(k => `\`${k}\``).join(',')}) VALUES (${placeholders})`;
327
424
 
328
- // sqlite3'te toplu ekleme için transaction kullanabiliriz
329
- const stmt = this.db.prepare(sql);
330
- this.db.serialize(() => {
331
- this.db.run("BEGIN TRANSACTION;");
332
- for (const item of dataArray) {
333
- stmt.run(Object.values(item));
334
- }
335
- this.db.run("COMMIT;");
425
+ // sqlite3'te toplu ekleme için transaction kullan
426
+ return new Promise((resolve, reject) => {
427
+ const stmt = this.db.prepare(sql, (err) => {
428
+ if (err) {
429
+ reject(err);
430
+ return;
431
+ }
432
+ });
433
+
434
+ this.db.serialize(() => {
435
+ this.db.run("BEGIN TRANSACTION;");
436
+
437
+ let completed = 0;
438
+ let hasError = false;
439
+
440
+ for (const item of dataArray) {
441
+ if (hasError) break;
442
+
443
+ const values = keys.map(k => this._serializeValue(item[k]));
444
+ stmt.run(values, (err) => {
445
+ if (err && !hasError) {
446
+ hasError = true;
447
+ this.db.run("ROLLBACK;");
448
+ reject(err);
449
+ return;
450
+ }
451
+
452
+ completed++;
453
+ if (completed === dataArray.length && !hasError) {
454
+ this.db.run("COMMIT;", (err) => {
455
+ if (err) {
456
+ reject(err);
457
+ } else {
458
+ stmt.finalize();
459
+ resolve(dataArray.length);
460
+ }
461
+ });
462
+ }
463
+ });
464
+ }
465
+ });
336
466
  });
337
-
338
- return dataArray.length;
339
467
  }
340
468
 
341
469
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onurege3467/zerohelper",
3
- "version": "7.0.0",
3
+ "version": "7.2.0",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "node test.js"
@@ -16,7 +16,6 @@
16
16
  "sqlite3",
17
17
  "quick.db",
18
18
  "postgresql",
19
- "redis",
20
19
  "utility",
21
20
  "functions",
22
21
  "nodejs"
@@ -26,7 +25,6 @@
26
25
  "description": "ZeroHelper is a versatile JavaScript library offering helper functions and database utilities for developers. It supports MongoDB, MySQL, SQLite, Redis, and PostgreSQL.",
27
26
  "dependencies": {
28
27
  "bcrypt": "^5.1.1",
29
-
30
28
  "crypto": "^1.0.1",
31
29
  "csv": "^6.3.11",
32
30
  "dotenv": "^16.4.7",
@@ -34,13 +32,13 @@
34
32
  "js-yaml": "^4.1.0",
35
33
  "jsonwebtoken": "^9.0.2",
36
34
  "lodash": "^4.17.21",
35
+ "lru-cache": "^10.0.0",
37
36
  "mongodb": "^6.12.0",
38
37
  "mysql2": "^3.14.1",
39
38
  "path": "^0.12.7",
40
39
  "pg": "^8.14.1",
41
40
  "promise-mysql": "^5.2.0",
42
- "redis": "^4.7.0",
43
- "sqlite3": "^5.1.7",
44
- "lru-cache": "^10.0.0"
41
+ "redis": "^5.8.2",
42
+ "sqlite3": "^5.1.7"
45
43
  }
46
44
  }
package/readme.md CHANGED
@@ -187,6 +187,7 @@ const cachedSqliteDb = createDatabase({
187
187
  config: {
188
188
  filePath: path.join(__dirname, 'data', 'cached_development.sqlite'),
189
189
  cache: {
190
+ type:'memory'
190
191
  max: 1000, // Cache up to 1000 items
191
192
  ttl: 1000 * 60 * 10, // Cache items for 10 minutes
192
193
  updateAgeOnGet: true // Refresh TTL on access
@@ -196,6 +197,29 @@ const cachedSqliteDb = createDatabase({
196
197
 
197
198
  // Subsequent `select` or `selectOne` calls for the same query will hit the cache
198
199
  // Write operations (insert, update, delete, set, bulkInsert) will automatically invalidate the cache for the affected table.
200
+
201
+ const postgresWithRedisCache = createDatabase({
202
+ adapter: 'postgres',
203
+ config: {
204
+ host: 'localhost',
205
+ user: 'postgres',
206
+ password: 'password',
207
+ database: 'myapp',
208
+ cache: {
209
+ type: 'redis',
210
+ host: 'localhost',
211
+ port: 6379,
212
+ password: 'redis_password',
213
+ db: 0,
214
+ ttl: 600, //seconds
215
+ keyPrefix: 'myapp_cache:',
216
+ redis: {
217
+ connectTimeout: 10000,
218
+ lazyConnect: true
219
+ }
220
+ }
221
+ }
222
+ });
199
223
  ```
200
224
 
201
225
  **Basic Usage (without cache configuration shown):**
@@ -250,6 +274,17 @@ const mongoDb = createDatabase({
250
274
  database: 'my_app_prod'
251
275
  }
252
276
  });
277
+ // --- Using Redis ---
278
+ const redisDatabase = createDatabase({
279
+ adapter: 'redis',
280
+ config: {
281
+ host: 'localhost',
282
+ port: 6379,
283
+ password: 'redis_password',
284
+ db: 1,
285
+ keyPrefix: 'myapp_data:'
286
+ }
287
+ });
253
288
  ```
254
289
 
255
290
  ### Basic Operations (CRUD)
package/data/test_db.json DELETED
@@ -1,3 +0,0 @@
1
- {
2
- "users": []
3
- }
Binary file
Binary file
package/test copy.js DELETED
@@ -1,144 +0,0 @@
1
- const path = require('path');
2
- const createDatabase = require('./database');
3
- const helpers = require('./functions');
4
- const { setInterval } = require('timers');
5
-
6
- const mysqlConfig = {
7
- adapter: 'mysql',
8
- config: {
9
- host: process.env.MYSQL_HOST || 'localhost',
10
- user: process.env.MYSQL_USER || 'root',
11
- password: process.env.MYSQL_PASSWORD || '',
12
- database: process.env.MYSQL_DATABASE || 'test_db_zerohelper',
13
- cache: {
14
- max: 100,
15
- ttl: 1000 * 10,
16
- updateAgeOnGet: true,
17
- },
18
- },
19
- };
20
- // Absurd configurations for testing edge cases
21
- async function runDatabaseTests() {
22
- console.log('Starting database tests...');
23
-
24
- const databases = [
25
- { name: 'MySQL', config: mysqlConfig },
26
- ];
27
-
28
- for (const dbInfo of databases) {
29
- const { name, config } = dbInfo;
30
- console.log(`\n--- Testing ${name} Database ---`);
31
- let db;
32
- try {
33
- db = createDatabase(config);
34
- console.log(`${name} database connected.`);
35
-
36
- // Test Insert
37
- const insertResult = await db.insert('users', { name: 'Test User', email: `test_${name.toLowerCase()}@example.com`, int_age: 30, bool_active: true,city: 'Test City' });
38
- console.log(`${name} Insert:`, insertResult);
39
- const selectResult = await db.selectOne('users', { _id: insertResult});
40
- console.log(`${name} Select One:`, selectResult);
41
- await db.set('users', {city:'Amkara'}, {_id: insertResult });
42
-
43
- setInterval(async () => {
44
- const updatedSelectResult = await db.selectOne('users', { _id: insertResult });
45
- console.log(`${name} Select One after update:`, updatedSelectResult);
46
- }, 1000);
47
-
48
-
49
-
50
- } catch (error) {
51
- console.error(`Error testing ${name} database:`, error);
52
- } finally {
53
- if (db) {
54
- try {
55
- } catch (closeError) {
56
- console.error(`Error closing ${name} database connection:`, closeError);
57
- }
58
- }
59
- }
60
-
61
-
62
- console.log('\nAll database tests completed.');
63
- }
64
- }
65
- function runHelperFunctionTests() {
66
- console.log('\nStarting helper function tests...');
67
-
68
- // Random Functions
69
- console.log('\n--- Testing Random Functions ---');
70
- console.log('makeUniqueId:', helpers.random.makeUniqueId());
71
- console.log('randomArray:', helpers.random.randomArray([1, 2, 3]));
72
- console.log('randomText (5 chars):', helpers.random.randomText(5));
73
- console.log('randomNumber (1-10):', helpers.random.randomNumber(1, 10));
74
- console.log('randomEmoji:', helpers.random.randomEmoji());
75
- console.log('randomHex:', helpers.random.randomHex());
76
- console.log('randomFloat (1.0-2.0):', helpers.random.randomFloat(1.0, 2.0));
77
-
78
- // String Functions
79
- console.log('\n--- Testing String Functions ---');
80
- console.log('titleCase:', helpers.string.titleCase('hello world'));
81
- console.log('generateRandomString (8 chars):', helpers.string.generateRandomString(8));
82
-
83
- // Array Functions
84
- console.log('\n--- Testing Array Functions ---');
85
- console.log('shuffleArray:', helpers.array.shuffleArray([1, 2, 3, 4, 5]));
86
- console.log('flattenArray:', helpers.array.flattenArray([1, [2, [3]], 4]));
87
- console.log('removeFalsyValues:', helpers.array.removeFalsyValues([0, 1, false, '', null, undefined, 2]));
88
- const groupByData = [
89
- { type: 'A', value: 1 },
90
- { type: 'B', value: 2 },
91
- { type: 'A', value: 3 },
92
- ];
93
- console.log('groupBy:', helpers.array.groupBy(groupByData, 'type'));
94
- const pluckData = [
95
- { name: 'Alice', age: 30 },
96
- { name: 'Bob', age: 24 },
97
- ];
98
- console.log('pluck (name):', helpers.array.pluck(pluckData, 'name'));
99
- const sortByData = [
100
- { age: 30 },
101
- { age: 20 },
102
- { age: 40 },
103
- ];
104
- console.log('sortBy (age):', helpers.array.sortBy(sortByData, 'age'));
105
-
106
- // Object Functions
107
- console.log('\n--- Testing Object Functions ---');
108
- const filterObjectData = { a: 1, b: 2, c: 3 };
109
- console.log('filterObjectByKey:', helpers.object.filterObjectByKey(filterObjectData, ['a', 'c']));
110
- const deepMergeData1 = { a: 1, b: { c: 2 } };
111
- const deepMergeData2 = { b: { d: 3 }, e: 4 };
112
- console.log('deepMerge:', helpers.object.deepMerge(deepMergeData1, deepMergeData2));
113
-
114
- // Crypto Functions
115
- console.log('\n--- Testing Crypto Functions ---');
116
- const secret = 'mySuperSecretKey';
117
- const textToEncrypt = 'Hello Crypto!';
118
- const encryptedResult = helpers.crypto.encryptText(textToEncrypt, secret);
119
- const encryptedText = encryptedResult.encryptedText;
120
- const iv = encryptedResult.iv;
121
- console.log('encryptText:', encryptedText);
122
- console.log('decryptText:', helpers.crypto.decryptText(encryptedText, secret, iv));
123
- const password = 'mySecurePassword';
124
- const hashedPassword = helpers.crypto.hashPassword(password);
125
- console.log('hashPassword:', hashedPassword);
126
- console.log('verifyPassword (true):', helpers.crypto.verifyPassword(password, hashedPassword));
127
- console.log('verifyPassword (false):', helpers.crypto.verifyPassword('wrongPassword', hashedPassword));
128
- const jwtPayload = { userId: 123, username: 'testuser' };
129
- const jwtToken = helpers.crypto.generateJWT(jwtPayload, secret);
130
- console.log('generateJWT:', jwtToken);
131
- console.log('verifyJWT:', helpers.crypto.verifyJWT(jwtToken, secret));
132
-
133
- // Math Functions
134
- console.log('\n--- Testing Math Functions ---');
135
- console.log('mean:', helpers.math.mean([1, 2, 3, 4, 5]));
136
- console.log('isPrime (7):', helpers.math.isPrime(7));
137
- console.log('isPrime (10):', helpers.math.isPrime(10));
138
- }
139
-
140
- async function main() {
141
- await runDatabaseTests();
142
- }
143
-
144
- main();