@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.
- package/README.md +152 -254
- package/dist/bin/zero.d.ts +2 -0
- package/dist/bin/zero.js +141 -0
- package/dist/database/IDatabase.d.ts +25 -31
- package/dist/database/IDatabase.js +38 -0
- package/dist/database/cacheWrapper.d.ts +5 -2
- package/dist/database/cacheWrapper.js +36 -50
- package/dist/database/index.d.ts +3 -2
- package/dist/database/index.js +13 -9
- package/dist/database/json.d.ts +4 -4
- package/dist/database/json.js +85 -87
- package/dist/database/mongodb.d.ts +12 -12
- package/dist/database/mongodb.js +49 -82
- package/dist/database/mysql.d.ts +7 -9
- package/dist/database/mysql.js +149 -270
- package/dist/database/pg.d.ts +12 -14
- package/dist/database/pg.js +113 -222
- package/dist/database/redis.d.ts +5 -3
- package/dist/database/redis.js +81 -107
- package/dist/database/seeder.d.ts +20 -0
- package/dist/database/seeder.js +37 -0
- package/dist/database/sqlite.d.ts +12 -15
- package/dist/database/sqlite.js +108 -223
- package/dist/database/telemetry.d.ts +35 -0
- package/dist/database/telemetry.js +41 -0
- package/dist/database/toon.d.ts +32 -0
- package/dist/database/toon.js +209 -0
- package/dist/database/types.d.ts +28 -34
- package/dist/database/zpack.d.ts +10 -4
- package/dist/database/zpack.js +151 -71
- package/dist/functions/index.d.ts +16 -0
- package/dist/functions/index.js +49 -3
- package/dist/functions/security.d.ts +15 -0
- package/dist/functions/security.js +46 -0
- package/dist/functions/toon.d.ts +7 -0
- package/dist/functions/toon.js +118 -0
- package/dist/functions/worker.d.ts +5 -0
- package/dist/functions/worker.js +35 -0
- package/dist/test_v91_advanced.d.ts +1 -0
- package/dist/test_v91_advanced.js +48 -0
- package/dist/test_v91_basics.d.ts +1 -0
- package/dist/test_v91_basics.js +54 -0
- package/dist/test_v91_performance.d.ts +1 -0
- package/dist/test_v91_performance.js +54 -0
- package/package.json +16 -3
package/dist/database/zpack.js
CHANGED
|
@@ -7,6 +7,7 @@ exports.ZPackAdapter = exports.ZPackDatabase = void 0;
|
|
|
7
7
|
const IDatabase_1 = require("./IDatabase");
|
|
8
8
|
const fs_1 = __importDefault(require("fs"));
|
|
9
9
|
const fsp = fs_1.default.promises;
|
|
10
|
+
const zlib_1 = __importDefault(require("zlib"));
|
|
10
11
|
class ZPackDatabase {
|
|
11
12
|
constructor(filePath, options = {}) {
|
|
12
13
|
this.fd = null;
|
|
@@ -22,6 +23,7 @@ class ZPackDatabase {
|
|
|
22
23
|
throw new Error("ZPackDatabase: 'filePath' zorunludur.");
|
|
23
24
|
this.filePath = filePath;
|
|
24
25
|
this._autoFlush = options.autoFlush === true;
|
|
26
|
+
this._compression = options.compression === true;
|
|
25
27
|
}
|
|
26
28
|
async open() {
|
|
27
29
|
if (this.fd)
|
|
@@ -56,6 +58,26 @@ class ZPackDatabase {
|
|
|
56
58
|
await this.fd.close();
|
|
57
59
|
this._closed = true;
|
|
58
60
|
}
|
|
61
|
+
async vacuum() {
|
|
62
|
+
this._ensureOpen();
|
|
63
|
+
return this._enqueue(async () => {
|
|
64
|
+
const tempPath = this.filePath + ".tmp";
|
|
65
|
+
const tempDb = new ZPackDatabase(tempPath, { autoFlush: false, compression: this._compression });
|
|
66
|
+
await tempDb.open();
|
|
67
|
+
for (const docId of this.index.keys()) {
|
|
68
|
+
const doc = await this.get(docId);
|
|
69
|
+
if (doc)
|
|
70
|
+
await tempDb.insert(doc, docId);
|
|
71
|
+
}
|
|
72
|
+
await tempDb.close();
|
|
73
|
+
await this.fd.close();
|
|
74
|
+
await fsp.rename(tempPath, this.filePath);
|
|
75
|
+
this.fd = null;
|
|
76
|
+
this.index.clear();
|
|
77
|
+
this.deleted.clear();
|
|
78
|
+
await this.open();
|
|
79
|
+
});
|
|
80
|
+
}
|
|
59
81
|
async insert(document, docId) {
|
|
60
82
|
this._ensureOpen();
|
|
61
83
|
const payload = this._encodeDocument(document, docId);
|
|
@@ -111,7 +133,7 @@ class ZPackDatabase {
|
|
|
111
133
|
}
|
|
112
134
|
else {
|
|
113
135
|
this.index.set(meta.docId, cur);
|
|
114
|
-
this.deleted.
|
|
136
|
+
this.deleted.add(meta.docId); // Bugfix: added to deleted, should be removed
|
|
115
137
|
if (meta.docId >= this._nextId)
|
|
116
138
|
this._nextId = meta.docId + 1;
|
|
117
139
|
}
|
|
@@ -126,8 +148,6 @@ class ZPackDatabase {
|
|
|
126
148
|
});
|
|
127
149
|
}
|
|
128
150
|
async delete(docId) {
|
|
129
|
-
if (!Number.isInteger(docId) || docId <= 0)
|
|
130
|
-
throw new Error("delete: 'docId' pozitif bir tamsayı olmalıdır.");
|
|
131
151
|
const tomb = this._encodeTombstone(docId);
|
|
132
152
|
await this._enqueue(async () => {
|
|
133
153
|
const writeOffset = this.fileSize;
|
|
@@ -146,21 +166,16 @@ class ZPackDatabase {
|
|
|
146
166
|
if (offset === undefined)
|
|
147
167
|
return null;
|
|
148
168
|
const header = Buffer.alloc(6);
|
|
149
|
-
if (offset + BigInt(header.length) > this._contentEnd)
|
|
150
|
-
return null;
|
|
151
169
|
const { bytesRead: hread } = await this.fd.read(header, 0, header.length, offset);
|
|
152
170
|
if (hread !== header.length)
|
|
153
171
|
return null;
|
|
154
172
|
const docLength = header.readUInt16LE(0);
|
|
155
173
|
const totalSize = 2 + docLength;
|
|
156
|
-
if (docLength < 4 || offset + BigInt(totalSize) > this._contentEnd)
|
|
157
|
-
return null;
|
|
158
174
|
const buf = Buffer.alloc(totalSize);
|
|
159
175
|
const { bytesRead } = await this.fd.read(buf, 0, totalSize, offset);
|
|
160
176
|
if (bytesRead !== totalSize)
|
|
161
177
|
return null;
|
|
162
|
-
|
|
163
|
-
return parsed.fieldCount === 0 ? null : parsed.document;
|
|
178
|
+
return this._decodeDocument(buf).document;
|
|
164
179
|
}
|
|
165
180
|
keys() { return Array.from(this.index.keys()); }
|
|
166
181
|
_ensureOpen() {
|
|
@@ -200,6 +215,15 @@ class ZPackDatabase {
|
|
|
200
215
|
}
|
|
201
216
|
_encodeDocument(document, docId) {
|
|
202
217
|
let id = docId ?? this._nextId++;
|
|
218
|
+
if (this._compression) {
|
|
219
|
+
const dataStr = JSON.stringify(document);
|
|
220
|
+
const compressed = zlib_1.default.deflateSync(dataStr);
|
|
221
|
+
const buf = Buffer.alloc(6 + compressed.length);
|
|
222
|
+
buf.writeUInt16LE(4 + compressed.length, 0);
|
|
223
|
+
buf.writeUInt32LE(id, 2);
|
|
224
|
+
compressed.copy(buf, 6);
|
|
225
|
+
return buf;
|
|
226
|
+
}
|
|
203
227
|
const fieldBuffers = [];
|
|
204
228
|
for (const [key, value] of Object.entries(document)) {
|
|
205
229
|
const keyBuf = Buffer.from(String(key), "utf8");
|
|
@@ -222,46 +246,35 @@ class ZPackDatabase {
|
|
|
222
246
|
}
|
|
223
247
|
return buf;
|
|
224
248
|
}
|
|
225
|
-
_encodeTombstone(docId) {
|
|
226
|
-
const buf = Buffer.alloc(6);
|
|
227
|
-
buf.writeUInt16LE(4, 0);
|
|
228
|
-
buf.writeUInt32LE(docId, 2);
|
|
229
|
-
return buf;
|
|
230
|
-
}
|
|
231
|
-
_peekDocMeta(encodedBuf) {
|
|
232
|
-
const payloadSize = encodedBuf.readUInt16LE(0);
|
|
233
|
-
const docId = encodedBuf.readUInt32LE(2);
|
|
234
|
-
const fieldBytes = payloadSize - 4;
|
|
235
|
-
let p = 6, consumed = 0, fields = 0;
|
|
236
|
-
while (consumed < fieldBytes) {
|
|
237
|
-
const klen = encodedBuf.readUInt8(p);
|
|
238
|
-
p += 1 + klen;
|
|
239
|
-
consumed += 1 + klen;
|
|
240
|
-
if (consumed >= fieldBytes)
|
|
241
|
-
break;
|
|
242
|
-
const vlen = encodedBuf.readUInt8(p);
|
|
243
|
-
p += 1 + vlen;
|
|
244
|
-
consumed += 1 + vlen;
|
|
245
|
-
fields += 1;
|
|
246
|
-
}
|
|
247
|
-
return { docId, fieldCount: fields };
|
|
248
|
-
}
|
|
249
249
|
_decodeDocument(buf) {
|
|
250
250
|
const payloadSize = buf.readUInt16LE(0);
|
|
251
251
|
const docId = buf.readUInt32LE(2);
|
|
252
|
+
if (this._compression && payloadSize > 4) {
|
|
253
|
+
try {
|
|
254
|
+
const decompressed = zlib_1.default.inflateSync(buf.subarray(6));
|
|
255
|
+
return { docId, fieldCount: 1, document: JSON.parse(decompressed.toString()) };
|
|
256
|
+
}
|
|
257
|
+
catch (e) { }
|
|
258
|
+
}
|
|
252
259
|
let p = 6;
|
|
253
260
|
const end = 2 + payloadSize;
|
|
254
261
|
const obj = {};
|
|
255
262
|
let fields = 0;
|
|
256
263
|
while (p < end) {
|
|
264
|
+
if (p + 1 > end)
|
|
265
|
+
break;
|
|
257
266
|
const klen = buf.readUInt8(p);
|
|
258
267
|
p += 1;
|
|
268
|
+
if (p + klen > end)
|
|
269
|
+
break;
|
|
259
270
|
const key = buf.toString("utf8", p, p + klen);
|
|
260
271
|
p += klen;
|
|
261
|
-
if (p
|
|
272
|
+
if (p + 1 > end)
|
|
262
273
|
break;
|
|
263
274
|
const vlen = buf.readUInt8(p);
|
|
264
275
|
p += 1;
|
|
276
|
+
if (p + vlen > end)
|
|
277
|
+
break;
|
|
265
278
|
const val = buf.toString("utf8", p, p + vlen);
|
|
266
279
|
p += vlen;
|
|
267
280
|
obj[key] = val;
|
|
@@ -269,6 +282,17 @@ class ZPackDatabase {
|
|
|
269
282
|
}
|
|
270
283
|
return { docId, fieldCount: fields, document: obj };
|
|
271
284
|
}
|
|
285
|
+
_encodeTombstone(docId) {
|
|
286
|
+
const buf = Buffer.alloc(6);
|
|
287
|
+
buf.writeUInt16LE(4, 0);
|
|
288
|
+
buf.writeUInt32LE(docId, 2);
|
|
289
|
+
return buf;
|
|
290
|
+
}
|
|
291
|
+
_peekDocMeta(encodedBuf) {
|
|
292
|
+
const payloadSize = encodedBuf.readUInt16LE(0);
|
|
293
|
+
const docId = encodedBuf.readUInt32LE(2);
|
|
294
|
+
return { docId, fieldCount: payloadSize > 4 ? 1 : 0 };
|
|
295
|
+
}
|
|
272
296
|
async _tryLoadIndexFromFooter() {
|
|
273
297
|
if (this.fileSize < 13n)
|
|
274
298
|
return false;
|
|
@@ -326,7 +350,13 @@ class ZPackAdapter extends IDatabase_1.IDatabase {
|
|
|
326
350
|
this.keyIndex = new Map();
|
|
327
351
|
this.rowCache = new Map();
|
|
328
352
|
this.secondary = new Map();
|
|
329
|
-
this.
|
|
353
|
+
this.indexedFields = new Map();
|
|
354
|
+
this.db = new ZPackDatabase(config.path, { autoFlush: !!config.autoFlush, compression: !!config.cache });
|
|
355
|
+
if (config.indexFields) {
|
|
356
|
+
for (const [table, fields] of Object.entries(config.indexFields)) {
|
|
357
|
+
this.indexedFields.set(table, new Set(fields));
|
|
358
|
+
}
|
|
359
|
+
}
|
|
330
360
|
this.initPromise = this._init();
|
|
331
361
|
}
|
|
332
362
|
async _init() {
|
|
@@ -336,19 +366,14 @@ class ZPackAdapter extends IDatabase_1.IDatabase {
|
|
|
336
366
|
if (!doc || !doc.t || !Number.isFinite(Number(doc._id)))
|
|
337
367
|
continue;
|
|
338
368
|
const table = String(doc.t), idNum = Number(doc._id);
|
|
339
|
-
|
|
340
|
-
this.keyIndex.set(table, new Map());
|
|
341
|
-
this.tableMaxId.set(table, 0);
|
|
342
|
-
this.rowCache.set(table, new Map());
|
|
343
|
-
this.secondary.set(table, new Map());
|
|
344
|
-
}
|
|
369
|
+
await this.ensureTable(table);
|
|
345
370
|
this.keyIndex.get(table).set(idNum, physicalDocId);
|
|
346
371
|
if (idNum > (this.tableMaxId.get(table) || 0))
|
|
347
372
|
this.tableMaxId.set(table, idNum);
|
|
373
|
+
this._updateSecondaryIndex(table, idNum, doc);
|
|
348
374
|
}
|
|
349
375
|
}
|
|
350
376
|
async ensureTable(table) {
|
|
351
|
-
await this.initPromise;
|
|
352
377
|
if (!this.tableMaxId.has(table)) {
|
|
353
378
|
this.tableMaxId.set(table, 0);
|
|
354
379
|
this.keyIndex.set(table, new Map());
|
|
@@ -356,6 +381,25 @@ class ZPackAdapter extends IDatabase_1.IDatabase {
|
|
|
356
381
|
this.secondary.set(table, new Map());
|
|
357
382
|
}
|
|
358
383
|
}
|
|
384
|
+
_updateSecondaryIndex(table, logicalId, data, oldData = null) {
|
|
385
|
+
const fields = this.indexedFields.get(table);
|
|
386
|
+
if (!fields)
|
|
387
|
+
return;
|
|
388
|
+
const tableIndex = this.secondary.get(table);
|
|
389
|
+
for (const field of fields) {
|
|
390
|
+
if (!tableIndex.has(field))
|
|
391
|
+
tableIndex.set(field, new Map());
|
|
392
|
+
const fieldMap = tableIndex.get(field);
|
|
393
|
+
if (oldData && oldData[field] !== undefined)
|
|
394
|
+
fieldMap.get(String(oldData[field]))?.delete(logicalId);
|
|
395
|
+
if (data[field] !== undefined) {
|
|
396
|
+
const newVal = String(data[field]);
|
|
397
|
+
if (!fieldMap.has(newVal))
|
|
398
|
+
fieldMap.set(newVal, new Set());
|
|
399
|
+
fieldMap.get(newVal).add(logicalId);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
359
403
|
_coerce(table, data, id) {
|
|
360
404
|
const out = { t: table, _id: String(id) };
|
|
361
405
|
for (const [k, v] of Object.entries(data || {})) {
|
|
@@ -370,7 +414,30 @@ class ZPackAdapter extends IDatabase_1.IDatabase {
|
|
|
370
414
|
return Object.entries(where).every(([k, v]) => String(row[k]) === String(v));
|
|
371
415
|
}
|
|
372
416
|
async select(table, where = null) {
|
|
417
|
+
const start = Date.now();
|
|
418
|
+
await this.initPromise;
|
|
373
419
|
await this.ensureTable(table);
|
|
420
|
+
if (where && Object.keys(where).length === 1) {
|
|
421
|
+
const [field, value] = Object.entries(where)[0];
|
|
422
|
+
const index = this.secondary.get(table)?.get(field);
|
|
423
|
+
if (index) {
|
|
424
|
+
const matches = index.get(String(value));
|
|
425
|
+
if (matches) {
|
|
426
|
+
const results = [];
|
|
427
|
+
for (const logicalId of matches) {
|
|
428
|
+
const physicalId = this.keyIndex.get(table).get(logicalId);
|
|
429
|
+
if (physicalId !== undefined) {
|
|
430
|
+
const doc = await this.db.get(physicalId);
|
|
431
|
+
if (doc)
|
|
432
|
+
results.push(doc);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
this.recordMetric('select', table, Date.now() - start);
|
|
436
|
+
return results;
|
|
437
|
+
}
|
|
438
|
+
return [];
|
|
439
|
+
}
|
|
440
|
+
}
|
|
374
441
|
const results = [];
|
|
375
442
|
for (const [logicalId, physicalId] of this.keyIndex.get(table).entries()) {
|
|
376
443
|
let row = this.rowCache.get(table).get(logicalId);
|
|
@@ -378,15 +445,13 @@ class ZPackAdapter extends IDatabase_1.IDatabase {
|
|
|
378
445
|
const doc = await this.db.get(physicalId);
|
|
379
446
|
if (!doc)
|
|
380
447
|
continue;
|
|
381
|
-
row =
|
|
382
|
-
for (const [k, v] of Object.entries(doc))
|
|
383
|
-
if (k !== 't' && k !== '_id')
|
|
384
|
-
row[k] = v;
|
|
448
|
+
row = doc;
|
|
385
449
|
this.rowCache.get(table).set(logicalId, row);
|
|
386
450
|
}
|
|
387
451
|
if (this._matches(row, where))
|
|
388
452
|
results.push({ ...row });
|
|
389
453
|
}
|
|
454
|
+
this.recordMetric('select', table, Date.now() - start);
|
|
390
455
|
return results;
|
|
391
456
|
}
|
|
392
457
|
async selectOne(table, where = null) {
|
|
@@ -394,68 +459,83 @@ class ZPackAdapter extends IDatabase_1.IDatabase {
|
|
|
394
459
|
return res[0] || null;
|
|
395
460
|
}
|
|
396
461
|
async insert(table, data) {
|
|
462
|
+
const start = Date.now();
|
|
463
|
+
await this.initPromise;
|
|
397
464
|
await this.ensureTable(table);
|
|
465
|
+
await this.runHooks('beforeInsert', table, data);
|
|
398
466
|
const nextId = (this.tableMaxId.get(table) || 0) + 1;
|
|
399
467
|
const record = this._coerce(table, data, nextId);
|
|
400
468
|
const physicalId = await this.db.insert(record);
|
|
401
469
|
this.tableMaxId.set(table, nextId);
|
|
402
470
|
this.keyIndex.get(table).set(nextId, physicalId);
|
|
403
|
-
const
|
|
404
|
-
this.rowCache.get(table).set(nextId,
|
|
471
|
+
const fullRow = { _id: nextId, ...data };
|
|
472
|
+
this.rowCache.get(table).set(nextId, fullRow);
|
|
473
|
+
this._updateSecondaryIndex(table, nextId, fullRow);
|
|
474
|
+
await this.runHooks('afterInsert', table, fullRow);
|
|
475
|
+
this.recordMetric('insert', table, Date.now() - start);
|
|
405
476
|
return nextId;
|
|
406
477
|
}
|
|
407
478
|
async update(table, data, where) {
|
|
479
|
+
const start = Date.now();
|
|
408
480
|
const rows = await this.select(table, where);
|
|
409
481
|
for (const row of rows) {
|
|
482
|
+
const logicalId = row._id;
|
|
483
|
+
await this.runHooks('beforeUpdate', table, { old: row, new: data });
|
|
410
484
|
const merged = { ...row, ...data };
|
|
411
|
-
const record = this._coerce(table, merged,
|
|
485
|
+
const record = this._coerce(table, merged, logicalId);
|
|
412
486
|
const physicalId = await this.db.insert(record);
|
|
413
|
-
this.keyIndex.get(table).set(
|
|
414
|
-
this.rowCache.get(table).set(
|
|
487
|
+
this.keyIndex.get(table).set(logicalId, physicalId);
|
|
488
|
+
this.rowCache.get(table).set(logicalId, merged);
|
|
489
|
+
this._updateSecondaryIndex(table, logicalId, merged, row);
|
|
490
|
+
await this.runHooks('afterUpdate', table, merged);
|
|
415
491
|
}
|
|
492
|
+
this.recordMetric('update', table, Date.now() - start);
|
|
416
493
|
return rows.length;
|
|
417
494
|
}
|
|
418
|
-
async set(table, data, where) {
|
|
419
|
-
const existing = await this.selectOne(table, where);
|
|
420
|
-
return existing ? this.update(table, data, where) : this.insert(table, { ...where, ...data });
|
|
421
|
-
}
|
|
422
495
|
async delete(table, where) {
|
|
496
|
+
const start = Date.now();
|
|
423
497
|
const rows = await this.select(table, where);
|
|
424
498
|
for (const row of rows) {
|
|
425
|
-
const
|
|
499
|
+
const logicalId = row._id;
|
|
500
|
+
await this.runHooks('beforeDelete', table, row);
|
|
501
|
+
const physicalId = this.keyIndex.get(table).get(logicalId);
|
|
426
502
|
if (physicalId !== undefined) {
|
|
427
503
|
await this.db.delete(physicalId);
|
|
428
|
-
this.keyIndex.get(table).delete(
|
|
429
|
-
this.rowCache.get(table).delete(
|
|
504
|
+
this.keyIndex.get(table).delete(logicalId);
|
|
505
|
+
this.rowCache.get(table).delete(logicalId);
|
|
506
|
+
this._updateSecondaryIndex(table, logicalId, {}, row);
|
|
430
507
|
}
|
|
508
|
+
await this.runHooks('afterDelete', table, row);
|
|
431
509
|
}
|
|
510
|
+
this.recordMetric('delete', table, Date.now() - start);
|
|
432
511
|
return rows.length;
|
|
433
512
|
}
|
|
513
|
+
async set(table, data, where) {
|
|
514
|
+
const ex = await this.selectOne(table, where);
|
|
515
|
+
return ex ? this.update(table, data, where) : this.insert(table, { ...where, ...data });
|
|
516
|
+
}
|
|
434
517
|
async bulkInsert(table, dataArray) {
|
|
435
|
-
for (const
|
|
436
|
-
await this.insert(table,
|
|
518
|
+
for (const d of dataArray)
|
|
519
|
+
await this.insert(table, d);
|
|
437
520
|
return dataArray.length;
|
|
438
521
|
}
|
|
439
|
-
async increment(table,
|
|
522
|
+
async increment(table, incs, where = {}) {
|
|
440
523
|
const rows = await this.select(table, where);
|
|
441
524
|
for (const row of rows) {
|
|
442
525
|
const updated = { ...row };
|
|
443
|
-
for (const [f, v] of Object.entries(
|
|
526
|
+
for (const [f, v] of Object.entries(incs))
|
|
444
527
|
updated[f] = (Number(updated[f]) || 0) + v;
|
|
445
528
|
await this.update(table, updated, { _id: row._id });
|
|
446
529
|
}
|
|
447
530
|
return rows.length;
|
|
448
531
|
}
|
|
449
|
-
async decrement(table,
|
|
450
|
-
const
|
|
451
|
-
for (const
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
updated[f] = (Number(updated[f]) || 0) - v;
|
|
455
|
-
await this.update(table, updated, { _id: row._id });
|
|
456
|
-
}
|
|
457
|
-
return rows.length;
|
|
532
|
+
async decrement(table, decs, where = {}) {
|
|
533
|
+
const incs = {};
|
|
534
|
+
for (const k in decs)
|
|
535
|
+
incs[k] = -decs[k];
|
|
536
|
+
return this.increment(table, incs, where);
|
|
458
537
|
}
|
|
538
|
+
async vacuum() { await this.db.vacuum(); }
|
|
459
539
|
async close() { await this.db.close(); }
|
|
460
540
|
}
|
|
461
541
|
exports.ZPackAdapter = ZPackAdapter;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import * as security from './security';
|
|
2
|
+
import * as toon from './toon';
|
|
1
3
|
export declare function makeUniqueId(): string;
|
|
2
4
|
export declare function randomArray<T>(arr: T[]): T;
|
|
3
5
|
export declare function randomText(length?: number): string;
|
|
@@ -181,3 +183,17 @@ export declare const logger_module: {
|
|
|
181
183
|
warn: typeof logWarn;
|
|
182
184
|
debug: typeof logDebug;
|
|
183
185
|
};
|
|
186
|
+
export declare const security_module: {
|
|
187
|
+
checkRateLimit(key: string, options: security.RateLimiterOptions): Promise<{
|
|
188
|
+
allowed: boolean;
|
|
189
|
+
remaining: number;
|
|
190
|
+
reset: number;
|
|
191
|
+
}>;
|
|
192
|
+
};
|
|
193
|
+
export declare const worker_module: {
|
|
194
|
+
runAsyncTask<T>(taskFn: string, data: any): Promise<T>;
|
|
195
|
+
};
|
|
196
|
+
export declare const toon_module: {
|
|
197
|
+
stringify: typeof toon.stringify;
|
|
198
|
+
parse: typeof toon.parse;
|
|
199
|
+
};
|
package/dist/functions/index.js
CHANGED
|
@@ -1,9 +1,42 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
37
|
};
|
|
5
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.logger_module = exports.validation_module = exports.math_module = exports.crypto_module = exports.object_module = exports.array_module = exports.string_module = exports.random_module = exports.date_module = exports.http_module = exports.Logger = void 0;
|
|
39
|
+
exports.toon_module = exports.worker_module = exports.security_module = exports.logger_module = exports.validation_module = exports.math_module = exports.crypto_module = exports.object_module = exports.array_module = exports.string_module = exports.random_module = exports.date_module = exports.http_module = exports.Logger = void 0;
|
|
7
40
|
exports.makeUniqueId = makeUniqueId;
|
|
8
41
|
exports.randomArray = randomArray;
|
|
9
42
|
exports.randomText = randomText;
|
|
@@ -68,6 +101,9 @@ const bcrypt_1 = __importDefault(require("bcrypt"));
|
|
|
68
101
|
const https_1 = __importDefault(require("https"));
|
|
69
102
|
const http_1 = __importDefault(require("http"));
|
|
70
103
|
const url_1 = require("url");
|
|
104
|
+
const security = __importStar(require("./security"));
|
|
105
|
+
const worker = __importStar(require("./worker"));
|
|
106
|
+
const toon = __importStar(require("./toon"));
|
|
71
107
|
// Random İşlemler
|
|
72
108
|
function makeUniqueId() {
|
|
73
109
|
return Date.now().toString(36) + Math.random().toString(36).substr(2);
|
|
@@ -373,8 +409,8 @@ function isEmail(email) {
|
|
|
373
409
|
return emailRegex.test(email);
|
|
374
410
|
}
|
|
375
411
|
function isPhone(phone) {
|
|
376
|
-
const phoneRegex = /^[
|
|
377
|
-
return phoneRegex.test(phone.replace(/[
|
|
412
|
+
const phoneRegex = /^[\\+]?[1-9][\\d]{0,15}$/;
|
|
413
|
+
return phoneRegex.test(phone.replace(/[\\s\-\(\)]/g, ''));
|
|
378
414
|
}
|
|
379
415
|
function isURL(url) {
|
|
380
416
|
try {
|
|
@@ -634,3 +670,13 @@ exports.logger_module = {
|
|
|
634
670
|
warn: logWarn,
|
|
635
671
|
debug: logDebug,
|
|
636
672
|
};
|
|
673
|
+
exports.security_module = {
|
|
674
|
+
...security
|
|
675
|
+
};
|
|
676
|
+
exports.worker_module = {
|
|
677
|
+
...worker
|
|
678
|
+
};
|
|
679
|
+
exports.toon_module = {
|
|
680
|
+
stringify: toon.stringify,
|
|
681
|
+
parse: toon.parse
|
|
682
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface RateLimiterOptions {
|
|
2
|
+
limit: number;
|
|
3
|
+
window: number;
|
|
4
|
+
storage?: 'memory' | 'redis';
|
|
5
|
+
redisClient?: any;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Advanced Rate Limiter for API protection.
|
|
9
|
+
* Returns true if allowed, false if rate limited.
|
|
10
|
+
*/
|
|
11
|
+
export declare function checkRateLimit(key: string, options: RateLimiterOptions): Promise<{
|
|
12
|
+
allowed: boolean;
|
|
13
|
+
remaining: number;
|
|
14
|
+
reset: number;
|
|
15
|
+
}>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkRateLimit = checkRateLimit;
|
|
4
|
+
const localStore = new Map();
|
|
5
|
+
/**
|
|
6
|
+
* Advanced Rate Limiter for API protection.
|
|
7
|
+
* Returns true if allowed, false if rate limited.
|
|
8
|
+
*/
|
|
9
|
+
async function checkRateLimit(key, options) {
|
|
10
|
+
const { limit, window, storage = 'memory', redisClient } = options;
|
|
11
|
+
const now = Date.now();
|
|
12
|
+
if (storage === 'redis' && redisClient) {
|
|
13
|
+
const redisKey = `rate_limit:${key}`;
|
|
14
|
+
const multi = redisClient.multi();
|
|
15
|
+
multi.incr(redisKey);
|
|
16
|
+
multi.ttl(redisKey);
|
|
17
|
+
const [count, ttl] = await multi.exec();
|
|
18
|
+
if (count === 1) {
|
|
19
|
+
await redisClient.expire(redisKey, window);
|
|
20
|
+
}
|
|
21
|
+
const isAllowed = count <= limit;
|
|
22
|
+
return {
|
|
23
|
+
allowed: isAllowed,
|
|
24
|
+
remaining: Math.max(0, limit - Number(count)),
|
|
25
|
+
reset: ttl > 0 ? now + (ttl * 1000) : now + (window * 1000)
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
// Memory Storage
|
|
30
|
+
let data = localStore.get(key);
|
|
31
|
+
if (!data || now > data.resetTime) {
|
|
32
|
+
data = {
|
|
33
|
+
count: 0,
|
|
34
|
+
resetTime: now + (window * 1000)
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
data.count++;
|
|
38
|
+
localStore.set(key, data);
|
|
39
|
+
const isAllowed = data.count <= limit;
|
|
40
|
+
return {
|
|
41
|
+
allowed: isAllowed,
|
|
42
|
+
remaining: Math.max(0, limit - data.count),
|
|
43
|
+
reset: data.resetTime
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TOON (Token-Oriented Object Notation) Support for ZeroHelper
|
|
3
|
+
* Optimized for LLM token efficiency and now supports Native Storage.
|
|
4
|
+
* API matches standard JSON object (stringify/parse).
|
|
5
|
+
*/
|
|
6
|
+
export declare function stringify(data: any, indent?: number): string;
|
|
7
|
+
export declare function parse(toonStr: string): any;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* TOON (Token-Oriented Object Notation) Support for ZeroHelper
|
|
4
|
+
* Optimized for LLM token efficiency and now supports Native Storage.
|
|
5
|
+
* API matches standard JSON object (stringify/parse).
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.stringify = stringify;
|
|
9
|
+
exports.parse = parse;
|
|
10
|
+
function stringify(data, indent = 0) {
|
|
11
|
+
const space = ' '.repeat(indent);
|
|
12
|
+
if (data === null)
|
|
13
|
+
return 'null';
|
|
14
|
+
if (typeof data === 'boolean' || typeof data === 'number')
|
|
15
|
+
return String(data);
|
|
16
|
+
if (typeof data === 'string') {
|
|
17
|
+
const hasSpecial = new RegExp('[\,\n:]').test(data);
|
|
18
|
+
if (hasSpecial)
|
|
19
|
+
return '"' + data.replace(/"/g, '\\"') + '"';
|
|
20
|
+
return data;
|
|
21
|
+
}
|
|
22
|
+
if (Array.isArray(data)) {
|
|
23
|
+
if (data.length === 0)
|
|
24
|
+
return '[]';
|
|
25
|
+
const first = data[0];
|
|
26
|
+
if (typeof first === 'object' && first !== null && !Array.isArray(first)) {
|
|
27
|
+
const keys = Object.keys(first);
|
|
28
|
+
const isUniform = data.every(item => item && typeof item === 'object' &&
|
|
29
|
+
Object.keys(item).length === keys.length &&
|
|
30
|
+
Object.keys(item).every(k => keys.includes(k)));
|
|
31
|
+
if (isUniform && data.length > 1) {
|
|
32
|
+
const header = '[' + data.length + ']{' + keys.join(',') + '}:';
|
|
33
|
+
const rows = data.map(item => {
|
|
34
|
+
const rowValues = keys.map(k => {
|
|
35
|
+
const val = item[k];
|
|
36
|
+
if (val === null)
|
|
37
|
+
return 'null';
|
|
38
|
+
const valStr = String(val);
|
|
39
|
+
const hasSpecialRow = new RegExp('[\,\n:]').test(valStr);
|
|
40
|
+
return (typeof val === 'string' && hasSpecialRow) ? '"' + valStr + '"' : valStr;
|
|
41
|
+
}).join(',');
|
|
42
|
+
return space + ' ' + rowValues;
|
|
43
|
+
});
|
|
44
|
+
return header + '\n' + rows.join('\n');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return '[' + data.length + ']: ' + data.map(v => stringify(v)).join(',');
|
|
48
|
+
}
|
|
49
|
+
if (typeof data === 'object') {
|
|
50
|
+
const entries = Object.entries(data);
|
|
51
|
+
if (entries.length === 0)
|
|
52
|
+
return '{}';
|
|
53
|
+
return entries.map(([key, value]) => {
|
|
54
|
+
const valStr = stringify(value, indent + 2);
|
|
55
|
+
const isComplex = typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
56
|
+
const separator = isComplex ? '\n' : ' ';
|
|
57
|
+
return space + key + ':' + separator + valStr;
|
|
58
|
+
}).join('\n');
|
|
59
|
+
}
|
|
60
|
+
return '';
|
|
61
|
+
}
|
|
62
|
+
function parse(toonStr) {
|
|
63
|
+
if (!toonStr || toonStr.trim() === '')
|
|
64
|
+
return {};
|
|
65
|
+
const lines = toonStr.split('\n').filter(l => l.trim() !== '');
|
|
66
|
+
const result = {};
|
|
67
|
+
let i = 0;
|
|
68
|
+
while (i < lines.length) {
|
|
69
|
+
const line = lines[i].trim();
|
|
70
|
+
const tabularMatch = line.match(/^(\w+)\[(\d+)\]\{(.*)\}:$/);
|
|
71
|
+
if (tabularMatch) {
|
|
72
|
+
const tableName = tabularMatch[1];
|
|
73
|
+
const rowCount = parseInt(tabularMatch[2]);
|
|
74
|
+
const fields = tabularMatch[3].split(',');
|
|
75
|
+
const rows = [];
|
|
76
|
+
for (let j = 0; j < rowCount; j++) {
|
|
77
|
+
i++;
|
|
78
|
+
if (!lines[i])
|
|
79
|
+
break;
|
|
80
|
+
const values = lines[i].trim().split(',').map(v => {
|
|
81
|
+
const trimmed = v.trim();
|
|
82
|
+
if (trimmed === 'true')
|
|
83
|
+
return true;
|
|
84
|
+
if (trimmed === 'false')
|
|
85
|
+
return false;
|
|
86
|
+
if (trimmed === 'null')
|
|
87
|
+
return null;
|
|
88
|
+
if (!isNaN(Number(trimmed)) && trimmed !== '')
|
|
89
|
+
return Number(trimmed);
|
|
90
|
+
return trimmed.replace(/^"|"$/g, '');
|
|
91
|
+
});
|
|
92
|
+
const row = {};
|
|
93
|
+
fields.forEach((f, idx) => row[f] = values[idx]);
|
|
94
|
+
rows.push(row);
|
|
95
|
+
}
|
|
96
|
+
result[tableName] = rows;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
const kvMatch = line.match(/^(\w+):\s*(.*)$/);
|
|
100
|
+
if (kvMatch) {
|
|
101
|
+
const key = kvMatch[1];
|
|
102
|
+
const value = kvMatch[2];
|
|
103
|
+
let parsedVal = value.trim();
|
|
104
|
+
if (parsedVal === 'true')
|
|
105
|
+
parsedVal = true;
|
|
106
|
+
else if (parsedVal === 'false')
|
|
107
|
+
parsedVal = false;
|
|
108
|
+
else if (parsedVal === 'null')
|
|
109
|
+
parsedVal = null;
|
|
110
|
+
else if (!isNaN(Number(parsedVal)) && parsedVal !== '')
|
|
111
|
+
parsedVal = Number(parsedVal);
|
|
112
|
+
result[key] = parsedVal;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
i++;
|
|
116
|
+
}
|
|
117
|
+
return result;
|
|
118
|
+
}
|