@onurege3467/zerohelper 9.0.0 → 9.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.
Files changed (45) hide show
  1. package/README.md +152 -254
  2. package/dist/bin/zero.d.ts +2 -0
  3. package/dist/bin/zero.js +141 -0
  4. package/dist/database/IDatabase.d.ts +25 -31
  5. package/dist/database/IDatabase.js +38 -0
  6. package/dist/database/cacheWrapper.d.ts +5 -2
  7. package/dist/database/cacheWrapper.js +36 -50
  8. package/dist/database/index.d.ts +3 -2
  9. package/dist/database/index.js +13 -9
  10. package/dist/database/json.d.ts +4 -4
  11. package/dist/database/json.js +85 -87
  12. package/dist/database/mongodb.d.ts +12 -12
  13. package/dist/database/mongodb.js +49 -82
  14. package/dist/database/mysql.d.ts +7 -9
  15. package/dist/database/mysql.js +149 -270
  16. package/dist/database/pg.d.ts +12 -14
  17. package/dist/database/pg.js +113 -222
  18. package/dist/database/redis.d.ts +5 -3
  19. package/dist/database/redis.js +81 -107
  20. package/dist/database/seeder.d.ts +20 -0
  21. package/dist/database/seeder.js +37 -0
  22. package/dist/database/sqlite.d.ts +12 -15
  23. package/dist/database/sqlite.js +108 -223
  24. package/dist/database/telemetry.d.ts +35 -0
  25. package/dist/database/telemetry.js +41 -0
  26. package/dist/database/toon.d.ts +32 -0
  27. package/dist/database/toon.js +209 -0
  28. package/dist/database/types.d.ts +28 -34
  29. package/dist/database/zpack.d.ts +10 -4
  30. package/dist/database/zpack.js +151 -71
  31. package/dist/functions/index.d.ts +16 -0
  32. package/dist/functions/index.js +49 -3
  33. package/dist/functions/security.d.ts +15 -0
  34. package/dist/functions/security.js +46 -0
  35. package/dist/functions/toon.d.ts +7 -0
  36. package/dist/functions/toon.js +118 -0
  37. package/dist/functions/worker.d.ts +5 -0
  38. package/dist/functions/worker.js +35 -0
  39. package/dist/test_v91_advanced.d.ts +1 -0
  40. package/dist/test_v91_advanced.js +48 -0
  41. package/dist/test_v91_basics.d.ts +1 -0
  42. package/dist/test_v91_basics.js +54 -0
  43. package/dist/test_v91_performance.d.ts +1 -0
  44. package/dist/test_v91_performance.js +54 -0
  45. package/package.json +16 -3
@@ -12,103 +12,32 @@ class PostgreSQLDatabase extends IDatabase_1.IDatabase {
12
12
  this.config = config;
13
13
  this._connectionPromise = new Promise(async (resolve, reject) => {
14
14
  try {
15
- const tempPool = new pg_1.Pool({
16
- host: config.host,
17
- port: config.port || 5432,
18
- user: config.user,
19
- password: config.password,
20
- database: 'postgres'
21
- });
15
+ const tempPool = new pg_1.Pool({ host: config.host || 'localhost', port: config.port || 5432, user: config.username, password: config.password, database: 'postgres' });
22
16
  try {
23
17
  await tempPool.query(`CREATE DATABASE "${config.database}"`);
24
18
  }
25
- catch (error) {
26
- if (!error.message.includes('already exists')) {
27
- console.warn('Database creation warning:', error.message);
28
- }
19
+ catch (e) {
20
+ if (!e.message.includes('already exists'))
21
+ console.warn(e.message);
29
22
  }
30
23
  await tempPool.end();
31
- this.pool = new pg_1.Pool({
32
- host: config.host,
33
- port: config.port || 5432,
34
- user: config.user,
35
- password: config.password,
36
- database: config.database,
37
- max: config.connectionLimit || 10,
38
- idleTimeoutMillis: 30000,
39
- connectionTimeoutMillis: 2000,
40
- });
24
+ this.pool = new pg_1.Pool({ host: config.host || 'localhost', port: config.port || 5432, user: config.username, password: config.password, database: config.database, max: config.poolSize || 10 });
41
25
  this._connected = true;
42
26
  resolve(this.pool);
43
27
  this._processQueue();
44
28
  }
45
29
  catch (error) {
46
- console.error("PostgreSQL connection error:", error);
47
30
  reject(error);
48
31
  }
49
32
  });
50
33
  }
51
- _getColumnType(value) {
52
- if (value === null || value === undefined)
53
- return 'TEXT';
54
- if (typeof value === 'boolean')
55
- return 'BOOLEAN';
56
- if (typeof value === 'number') {
57
- if (Number.isInteger(value)) {
58
- if (value >= -32768 && value <= 32767)
59
- return 'SMALLINT';
60
- if (value >= -2147483648 && value <= 2147483647)
61
- return 'INTEGER';
62
- return 'BIGINT';
63
- }
64
- return 'DOUBLE PRECISION';
65
- }
66
- if (typeof value === 'string') {
67
- return value.length <= 255 ? 'VARCHAR(255)' : 'TEXT';
68
- }
69
- if (typeof value === 'object')
70
- return 'JSONB';
71
- if (value instanceof Date)
72
- return 'TIMESTAMP';
73
- return 'TEXT';
74
- }
75
- _getBestColumnType(values) {
76
- const types = values.map(val => this._getColumnType(val));
77
- const uniqueTypes = [...new Set(types)];
78
- if (uniqueTypes.length === 1)
79
- return uniqueTypes[0];
80
- const typePriority = {
81
- 'TEXT': 10, 'JSONB': 9, 'VARCHAR(255)': 8, 'TIMESTAMP': 7,
82
- 'DOUBLE PRECISION': 6, 'BIGINT': 5, 'INTEGER': 4, 'SMALLINT': 3, 'BOOLEAN': 2
83
- };
84
- return uniqueTypes.sort((a, b) => (typePriority[b] || 0) - (typePriority[a] || 0))[0];
85
- }
86
- async _ensureMissingColumns(table, data) {
87
- const existingColumns = await this.query(`
88
- SELECT column_name
89
- FROM information_schema.columns
90
- WHERE table_name = $1 AND table_schema = 'public'
91
- `, [table]);
92
- if (!existingColumns || existingColumns.length === 0)
93
- throw new Error(`Table ${table} does not exist.`);
94
- const existingColumnNames = existingColumns.map(col => col.column_name);
95
- for (const key of Object.keys(data)) {
96
- if (!existingColumnNames.includes(key)) {
97
- const columnType = this._getColumnType(data[key]);
98
- await this.query(`ALTER TABLE "${table}" ADD COLUMN "${key}" ${columnType}`);
99
- }
100
- }
101
- }
102
- async _queueRequest(operation) {
103
- if (this._connected) {
104
- return operation();
105
- }
106
- else {
107
- return new Promise((resolve, reject) => {
108
- this._queue.push({ operation, resolve, reject });
109
- });
110
- }
34
+ async _execute(op, table, fn) {
35
+ const start = Date.now();
36
+ const res = await fn();
37
+ this.recordMetric(op, table, Date.now() - start);
38
+ return res;
111
39
  }
40
+ ;
112
41
  async _processQueue() {
113
42
  if (!this._connected)
114
43
  return;
@@ -116,8 +45,7 @@ class PostgreSQLDatabase extends IDatabase_1.IDatabase {
116
45
  const item = this._queue.shift();
117
46
  if (item) {
118
47
  try {
119
- const result = await item.operation();
120
- item.resolve(result);
48
+ item.resolve(await item.operation());
121
49
  }
122
50
  catch (error) {
123
51
  item.reject(error);
@@ -126,174 +54,137 @@ class PostgreSQLDatabase extends IDatabase_1.IDatabase {
126
54
  }
127
55
  }
128
56
  async query(sql, params = []) {
129
- return this._queueRequest(async () => {
130
- const pool = await this._connectionPromise;
131
- const result = await pool.query(sql, params);
132
- return result.rows;
133
- });
57
+ const pool = await this._connectionPromise;
58
+ const res = await pool.query(sql, params);
59
+ return res.rows;
134
60
  }
135
61
  async ensureTable(table, data = {}) {
136
- return this._queueRequest(async () => {
137
- const tables = await this.query(`
138
- SELECT table_name
139
- FROM information_schema.tables
140
- WHERE table_schema = 'public' AND table_name = $1
141
- `, [table]);
142
- if (tables.length === 0) {
143
- const columnDefinitions = Object.keys(data).map(col => {
144
- const columnType = this._getColumnType(data[col]);
145
- return `"${col}" ${columnType}`;
146
- });
147
- const columnsPart = columnDefinitions.length > 0 ? ', ' + columnDefinitions.join(", ") : '';
148
- const createTableSQL = `CREATE TABLE "${table}" ("_id" SERIAL PRIMARY KEY ${columnsPart})`;
149
- await this.query(createTableSQL);
62
+ const tables = await this.query(`SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' AND table_name = $1`, [table]);
63
+ if (tables.length === 0) {
64
+ const defs = Object.keys(data).map(k => `"${k}" TEXT`);
65
+ await this.query(`CREATE TABLE "${table}" ("_id" SERIAL PRIMARY KEY ${defs.length ? ', ' + defs.join(",") : ''})`);
66
+ }
67
+ else {
68
+ const existing = await this.query(`SELECT column_name FROM information_schema.columns WHERE table_name = $1 AND table_schema = 'public'`, [table]);
69
+ const names = existing.map((c) => c.column_name);
70
+ for (const key of Object.keys(data)) {
71
+ if (key !== '_id' && !names.includes(key)) {
72
+ await this.query(`ALTER TABLE "${table}" ADD COLUMN "${key}" TEXT`);
73
+ }
150
74
  }
151
- });
75
+ }
152
76
  }
153
77
  async insert(table, data) {
154
- return this._queueRequest(async () => {
155
- const copy = { ...data };
156
- await this.ensureTable(table, copy);
157
- await this._ensureMissingColumns(table, copy);
158
- const existingColumns = await this.query(`
159
- SELECT column_name, column_default
160
- FROM information_schema.columns
161
- WHERE table_name = $1 AND table_schema = 'public'
162
- `, [table]);
163
- const primaryKeyColumn = existingColumns.find(col => col.column_default && col.column_default.includes('nextval'));
164
- if (primaryKeyColumn && copy[primaryKeyColumn.column_name] !== undefined) {
165
- delete copy[primaryKeyColumn.column_name];
166
- }
167
- const keys = Object.keys(copy);
168
- const placeholders = keys.map((_, index) => `$${index + 1}`).join(",");
169
- const values = Object.values(copy).map(value => this._serializeValue(value));
170
- const sql = `INSERT INTO "${table}" (${keys.map(k => `"${k}"`).join(",")}) VALUES (${placeholders}) RETURNING "_id"`;
171
- const result = await this.query(sql, values);
172
- return result[0]._id;
78
+ await this.runHooks('beforeInsert', table, data);
79
+ return this._execute('insert', table, async () => {
80
+ await this.ensureTable(table, data);
81
+ const keys = Object.keys(data);
82
+ const sql = `INSERT INTO "${table}" (${keys.map(k => `"${k}"`).join(",")}) VALUES (${keys.map((_, i) => `$${i + 1}`).join(",")}) RETURNING "_id"`;
83
+ const res = await this.query(sql, Object.values(data).map(v => this._serializeValue(v)));
84
+ const finalData = { _id: res[0]._id, ...data };
85
+ await this.runHooks('afterInsert', table, finalData);
86
+ return res[0]._id;
173
87
  });
174
88
  }
175
89
  async update(table, data, where) {
176
- return this._queueRequest(async () => {
90
+ await this.runHooks('beforeUpdate', table, { data, where });
91
+ return this._execute('update', table, async () => {
177
92
  await this.ensureTable(table, { ...data, ...where });
178
- await this._ensureMissingColumns(table, { ...data, ...where });
179
- const setString = Object.keys(data).map((k, i) => `"${k}" = $${i + 1}`).join(", ");
180
- const whereString = Object.keys(where).map((k, i) => `"${k}" = $${Object.keys(data).length + i + 1}`).join(" AND ");
181
- const sql = `UPDATE "${table}" SET ${setString} WHERE ${whereString}`;
93
+ const set = Object.keys(data).map((k, i) => `"${k}" = $${i + 1}`).join(",");
94
+ const { whereClause, values: whereValues } = this._buildWhereClause(where);
95
+ const sql = `UPDATE "${table}" SET ${set} ${whereClause}`;
182
96
  const pool = await this._connectionPromise;
183
- const result = await pool.query(sql, [...Object.values(data).map(v => this._serializeValue(v)), ...Object.values(where).map(v => this._serializeValue(v))]);
184
- return result.rowCount ?? 0;
97
+ const res = await pool.query(sql, [...Object.values(data).map(v => this._serializeValue(v)), ...whereValues]);
98
+ return res.rowCount ?? 0;
185
99
  });
186
100
  }
187
101
  async delete(table, where) {
188
- return this._queueRequest(async () => {
189
- if (!where || Object.keys(where).length === 0)
190
- return 0;
191
- await this.ensureTable(table, { ...where });
192
- await this._ensureMissingColumns(table, where);
193
- const whereString = Object.keys(where).map((k, i) => `"${k}" = $${i + 1}`).join(" AND ");
194
- const sql = `DELETE FROM "${table}" WHERE ${whereString}`;
102
+ await this.runHooks('beforeDelete', table, where);
103
+ return this._execute('delete', table, async () => {
104
+ await this.ensureTable(table, where);
105
+ const { whereClause, values } = this._buildWhereClause(where);
106
+ const sql = `DELETE FROM "${table}" ${whereClause}`;
195
107
  const pool = await this._connectionPromise;
196
- const result = await pool.query(sql, Object.values(where).map(v => this._serializeValue(v)));
197
- return result.rowCount ?? 0;
108
+ const res = await pool.query(sql, values);
109
+ return res.rowCount ?? 0;
198
110
  });
199
111
  }
200
112
  async select(table, where = null) {
201
- return this._queueRequest(async () => {
113
+ return this._execute('select', table, async () => {
202
114
  await this.ensureTable(table, where || {});
203
- if (where && Object.keys(where).length > 0) {
204
- await this._ensureMissingColumns(table, where);
205
- }
206
- let sql = `SELECT * FROM "${table}"`;
207
- let params = [];
208
- if (where && Object.keys(where).length > 0) {
209
- const whereString = Object.keys(where).map((k, i) => `"${k}" = $${i + 1}`).join(" AND ");
210
- sql += ` WHERE ${whereString}`;
211
- params = Object.values(where).map(v => this._serializeValue(v));
212
- }
213
- const rows = await this.query(sql, params);
214
- return rows;
215
- });
216
- }
217
- async set(table, data, where) {
218
- return this._queueRequest(async () => {
219
- const existing = await this.select(table, where);
220
- if (existing.length === 0) {
221
- return await this.insert(table, { ...where, ...data });
222
- }
223
- else {
224
- return await this.update(table, data, where);
225
- }
115
+ const { whereClause, values } = this._buildWhereClause(where);
116
+ const rows = await this.query(`SELECT * FROM "${table}" ${whereClause}`, values);
117
+ return rows.map((r) => {
118
+ const nr = {};
119
+ for (const k in r)
120
+ nr[k] = r[k];
121
+ return nr;
122
+ });
226
123
  });
227
124
  }
228
125
  async selectOne(table, where = null) {
229
- const results = await this.select(table, where);
230
- return results[0] || null;
126
+ const res = await this.select(table, where);
127
+ return res[0] || null;
128
+ }
129
+ async set(table, data, where) {
130
+ const ex = await this.selectOne(table, where);
131
+ return ex ? this.update(table, data, where) : this.insert(table, { ...where, ...data });
231
132
  }
232
133
  async bulkInsert(table, dataArray) {
233
- return this._queueRequest(async () => {
234
- if (!Array.isArray(dataArray) || dataArray.length === 0)
235
- return 0;
236
- await this.ensureTable(table, dataArray[0]);
237
- const allKeys = new Set();
238
- dataArray.forEach(obj => Object.keys(obj).forEach(key => allKeys.add(key)));
239
- const existingColumns = await this.query(`
240
- SELECT column_name
241
- FROM information_schema.columns
242
- WHERE table_name = $1 AND table_schema = 'public'
243
- `, [table]);
244
- const existingColumnNames = existingColumns.map(col => col.column_name);
245
- for (const key of allKeys) {
246
- if (!existingColumnNames.includes(key)) {
247
- const columnValues = dataArray.map(obj => obj[key]).filter(val => val !== undefined && val !== null);
248
- const columnType = columnValues.length > 0 ? this._getBestColumnType(columnValues) : 'TEXT';
249
- await this.query(`ALTER TABLE "${table}" ADD COLUMN "${key}" ${columnType}`);
250
- }
251
- }
252
- const keys = Array.from(allKeys);
253
- const placeholders = dataArray.map((_, rowIndex) => `(${keys.map((_, colIndex) => `$${rowIndex * keys.length + colIndex + 1}`).join(',')})`).join(',');
254
- const values = dataArray.flatMap(obj => keys.map(k => this._serializeValue(obj[k])));
255
- const sql = `INSERT INTO "${table}" (${keys.map(k => `"${k}"`).join(",")}) VALUES ${placeholders}`;
134
+ if (!dataArray.length)
135
+ return 0;
136
+ for (const d of dataArray)
137
+ await this.insert(table, d);
138
+ return dataArray.length;
139
+ }
140
+ async increment(table, incs, where) {
141
+ return this._execute('increment', table, async () => {
142
+ await this.ensureTable(table, where);
143
+ const set = Object.keys(incs).map((f, i) => `"${f}" = "${f}" + $${i + 1}`).join(',');
144
+ const { whereClause, values } = this._buildWhereClause(where);
145
+ const sql = `UPDATE "${table}" SET ${set} ${whereClause}`;
256
146
  const pool = await this._connectionPromise;
257
- const result = await pool.query(sql, values);
258
- return result.rowCount ?? 0;
147
+ const res = await pool.query(sql, [...Object.values(incs), ...values]);
148
+ return res.rowCount ?? 0;
259
149
  });
260
150
  }
261
- async close() {
262
- if (this.pool)
263
- await this.pool.end();
264
- }
265
- _serializeValue(value) {
266
- if (value instanceof Date)
267
- return value.toISOString();
268
- if (Array.isArray(value) || (typeof value === 'object' && value !== null))
269
- return JSON.stringify(value);
270
- return value;
151
+ async decrement(table, decs, where) {
152
+ const incs = {};
153
+ for (const k in decs)
154
+ incs[k] = -decs[k];
155
+ return this.increment(table, incs, where);
271
156
  }
272
- async increment(table, increments, where = {}) {
273
- const incrementClauses = Object.keys(increments).map((field, index) => `"${field}" = "${field}" + $${index + 1}`).join(', ');
274
- const incrementValues = Object.values(increments);
275
- const { whereClause, values: whereValues } = this._buildWhereClause(where, incrementValues.length);
276
- const sql = `UPDATE "${table}" SET ${incrementClauses}${whereClause}`;
277
- const pool = await this._connectionPromise;
278
- const result = await pool.query(sql, [...incrementValues, ...whereValues]);
279
- return result.rowCount ?? 0;
157
+ async close() { if (this.pool)
158
+ await this.pool.end(); }
159
+ _getColumnType(v) {
160
+ if (v === null || v === undefined)
161
+ return 'TEXT';
162
+ if (typeof v === 'boolean')
163
+ return 'BOOLEAN';
164
+ if (typeof v === 'number')
165
+ return Number.isInteger(v) ? 'INTEGER' : 'DOUBLE PRECISION';
166
+ if (v instanceof Date)
167
+ return 'TIMESTAMP';
168
+ if (typeof v === 'object')
169
+ return 'JSONB';
170
+ return 'TEXT';
280
171
  }
281
- async decrement(table, decrements, where = {}) {
282
- const decrementClauses = Object.keys(decrements).map((field, index) => `"${field}" = "${field}" - $${index + 1}`).join(', ');
283
- const decrementValues = Object.values(decrements);
284
- const { whereClause, values: whereValues } = this._buildWhereClause(where, decrementValues.length);
285
- const sql = `UPDATE "${table}" SET ${decrementClauses}${whereClause}`;
286
- const pool = await this._connectionPromise;
287
- const result = await pool.query(sql, [...decrementValues, ...whereValues]);
288
- return result.rowCount ?? 0;
172
+ _serializeValue(v) {
173
+ if (v instanceof Date)
174
+ return v.toISOString();
175
+ return (typeof v === 'object' && v !== null) ? JSON.stringify(v) : v;
289
176
  }
290
- _buildWhereClause(where = {}, startIndex = 0) {
291
- const conditions = Object.keys(where);
292
- if (conditions.length === 0)
177
+ _buildWhereClause(where) {
178
+ if (!where)
179
+ return { whereClause: '', values: [] };
180
+ const safeWhere = where;
181
+ const keys = Object.keys(safeWhere);
182
+ if (!keys.length)
293
183
  return { whereClause: '', values: [] };
294
- const whereClause = ' WHERE ' + conditions.map((key, index) => `"${key}" = $${startIndex + index + 1}`).join(' AND ');
295
- const values = Object.values(where).map(v => this._serializeValue(v));
296
- return { whereClause, values };
184
+ return {
185
+ whereClause: 'WHERE ' + keys.map((k, i) => `"${k}" = $${i + 1}`).join(' AND '),
186
+ values: keys.map(k => this._serializeValue(safeWhere[k]))
187
+ };
297
188
  }
298
189
  }
299
190
  exports.PostgreSQLDatabase = PostgreSQLDatabase;
@@ -1,11 +1,13 @@
1
1
  import { IDatabase } from './IDatabase';
2
2
  import { RedisClientType } from 'redis';
3
+ import { RedisConfig } from './types';
3
4
  export declare class RedisDatabase extends IDatabase {
4
5
  private config;
5
6
  private client;
6
7
  private isConnecting;
7
8
  private keyPrefix;
8
- constructor(config?: any);
9
+ constructor(config: RedisConfig);
10
+ private _execute;
9
11
  connect(): Promise<RedisClientType>;
10
12
  private _getKey;
11
13
  private _getTableKey;
@@ -16,8 +18,8 @@ export declare class RedisDatabase extends IDatabase {
16
18
  delete(table: string, where: Record<string, any>): Promise<number>;
17
19
  set(table: string, data: Record<string, any>, where: Record<string, any>): Promise<any>;
18
20
  bulkInsert(table: string, dataArray: Record<string, any>[]): Promise<number>;
19
- increment(table: string, increments: Record<string, number>, where?: Record<string, any>): Promise<number>;
20
- decrement(table: string, decrements: Record<string, number>, where?: Record<string, any>): Promise<number>;
21
+ increment(table: string, incs: Record<string, number>, where?: Record<string, any>): Promise<number>;
22
+ decrement(table: string, decs: Record<string, number>, where?: Record<string, any>): Promise<number>;
21
23
  close(): Promise<void>;
22
24
  }
23
25
  export default RedisDatabase;