@onurege3467/zerohelper 9.2.0 → 10.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/bin/zero.js +0 -0
- package/dist/database/IDatabase.d.ts +12 -12
- package/dist/database/IDatabase.js +2 -2
- package/dist/database/index.d.ts +1 -1
- package/dist/database/index.js +3 -1
- package/dist/database/mongodb.d.ts +7 -5
- package/dist/database/mongodb.js +87 -62
- package/dist/database/mysql.js +24 -6
- package/dist/database/pg.js +18 -9
- package/dist/database/redis.d.ts +9 -3
- package/dist/database/redis.js +89 -44
- package/dist/database/sqlite.d.ts +4 -0
- package/dist/database/sqlite.js +63 -10
- package/dist/database/toon.d.ts +1 -0
- package/dist/database/toon.js +43 -12
- package/dist/database/types.d.ts +1 -0
- package/dist/database/zpack.d.ts +10 -0
- package/dist/database/zpack.js +187 -113
- package/dist/functions/toon.d.ts +3 -0
- package/dist/functions/toon.js +74 -48
- package/dist/tests/test.js +22 -0
- package/package.json +1 -1
- package/dist/functions/temp_isphone.d.ts +0 -1
- package/dist/functions/temp_isphone.js +0 -7
- package/dist/test.js +0 -55
- package/dist/test_v91_advanced.d.ts +0 -1
- package/dist/test_v91_advanced.js +0 -48
- package/dist/test_v91_basics.d.ts +0 -1
- package/dist/test_v91_basics.js +0 -54
- package/dist/test_v91_performance.d.ts +0 -1
- package/dist/test_v91_performance.js +0 -54
- package/dist/test_zpack.d.ts +0 -1
- package/dist/test_zpack.js +0 -64
- /package/dist/{test.d.ts → tests/test.d.ts} +0 -0
package/dist/database/zpack.js
CHANGED
|
@@ -8,6 +8,9 @@ const IDatabase_1 = require("./IDatabase");
|
|
|
8
8
|
const fs_1 = __importDefault(require("fs"));
|
|
9
9
|
const fsp = fs_1.default.promises;
|
|
10
10
|
const zlib_1 = __importDefault(require("zlib"));
|
|
11
|
+
/**
|
|
12
|
+
* ZPackDatabase: Low-level Binary Storage
|
|
13
|
+
*/
|
|
11
14
|
class ZPackDatabase {
|
|
12
15
|
constructor(filePath, options = {}) {
|
|
13
16
|
this.fd = null;
|
|
@@ -56,6 +59,7 @@ class ZPackDatabase {
|
|
|
56
59
|
return;
|
|
57
60
|
await this._writeFooter();
|
|
58
61
|
await this.fd.close();
|
|
62
|
+
this.fd = null;
|
|
59
63
|
this._closed = true;
|
|
60
64
|
}
|
|
61
65
|
async vacuum() {
|
|
@@ -83,7 +87,7 @@ class ZPackDatabase {
|
|
|
83
87
|
const payload = this._encodeDocument(document, docId);
|
|
84
88
|
return this._enqueue(async () => {
|
|
85
89
|
const writeOffset = this.fileSize;
|
|
86
|
-
await this.fd.write(payload, 0, payload.length, writeOffset);
|
|
90
|
+
await this.fd.write(payload, 0, payload.length, Number(writeOffset));
|
|
87
91
|
this.fileSize = writeOffset + BigInt(payload.length);
|
|
88
92
|
this._contentEnd = this.fileSize;
|
|
89
93
|
const parsed = this._peekDocMeta(payload);
|
|
@@ -122,7 +126,7 @@ class ZPackDatabase {
|
|
|
122
126
|
}
|
|
123
127
|
return this._enqueue(async () => {
|
|
124
128
|
const writeOffset = this.fileSize;
|
|
125
|
-
await this.fd.write(buffer, 0, buffer.length, writeOffset);
|
|
129
|
+
await this.fd.write(buffer, 0, buffer.length, Number(writeOffset));
|
|
126
130
|
let cur = writeOffset;
|
|
127
131
|
const ids = [];
|
|
128
132
|
for (let i = 0; i < payloads.length; i++) {
|
|
@@ -133,7 +137,7 @@ class ZPackDatabase {
|
|
|
133
137
|
}
|
|
134
138
|
else {
|
|
135
139
|
this.index.set(meta.docId, cur);
|
|
136
|
-
this.deleted.
|
|
140
|
+
this.deleted.delete(meta.docId);
|
|
137
141
|
if (meta.docId >= this._nextId)
|
|
138
142
|
this._nextId = meta.docId + 1;
|
|
139
143
|
}
|
|
@@ -151,7 +155,7 @@ class ZPackDatabase {
|
|
|
151
155
|
const tomb = this._encodeTombstone(docId);
|
|
152
156
|
await this._enqueue(async () => {
|
|
153
157
|
const writeOffset = this.fileSize;
|
|
154
|
-
await this.fd.write(tomb, 0, tomb.length, writeOffset);
|
|
158
|
+
await this.fd.write(tomb, 0, tomb.length, Number(writeOffset));
|
|
155
159
|
this.fileSize = writeOffset + BigInt(tomb.length);
|
|
156
160
|
this._contentEnd = this.fileSize;
|
|
157
161
|
this.index.delete(docId);
|
|
@@ -166,13 +170,13 @@ class ZPackDatabase {
|
|
|
166
170
|
if (offset === undefined)
|
|
167
171
|
return null;
|
|
168
172
|
const header = Buffer.alloc(6);
|
|
169
|
-
const { bytesRead: hread } = await this.fd.read(header, 0, header.length, offset);
|
|
173
|
+
const { bytesRead: hread } = await this.fd.read(header, 0, header.length, Number(offset));
|
|
170
174
|
if (hread !== header.length)
|
|
171
175
|
return null;
|
|
172
176
|
const docLength = header.readUInt16LE(0);
|
|
173
177
|
const totalSize = 2 + docLength;
|
|
174
178
|
const buf = Buffer.alloc(totalSize);
|
|
175
|
-
const { bytesRead } = await this.fd.read(buf, 0, totalSize, offset);
|
|
179
|
+
const { bytesRead } = await this.fd.read(buf, 0, totalSize, Number(offset));
|
|
176
180
|
if (bytesRead !== totalSize)
|
|
177
181
|
return null;
|
|
178
182
|
return this._decodeDocument(buf).document;
|
|
@@ -206,7 +210,7 @@ class ZPackDatabase {
|
|
|
206
210
|
}
|
|
207
211
|
footer.writeUInt32LE(footerSize, p);
|
|
208
212
|
const writeOffset = this.fileSize;
|
|
209
|
-
await this.fd.write(footer, 0, footer.length, writeOffset);
|
|
213
|
+
await this.fd.write(footer, 0, footer.length, Number(writeOffset));
|
|
210
214
|
this._contentEnd = writeOffset;
|
|
211
215
|
this.fileSize = writeOffset + BigInt(footer.length);
|
|
212
216
|
}
|
|
@@ -297,13 +301,13 @@ class ZPackDatabase {
|
|
|
297
301
|
if (this.fileSize < 13n)
|
|
298
302
|
return false;
|
|
299
303
|
const sizeBuf = Buffer.alloc(4);
|
|
300
|
-
await this.fd.read(sizeBuf, 0, 4, this.fileSize - 4n);
|
|
304
|
+
await this.fd.read(sizeBuf, 0, 4, Number(this.fileSize - 4n));
|
|
301
305
|
const footerSize = sizeBuf.readUInt32LE(0);
|
|
302
306
|
if (footerSize < 9 || BigInt(footerSize) + 4n > this.fileSize)
|
|
303
307
|
return false;
|
|
304
308
|
const footerStart = this.fileSize - 4n - BigInt(footerSize);
|
|
305
309
|
const footer = Buffer.alloc(footerSize);
|
|
306
|
-
await this.fd.read(footer, 0, footerSize, footerStart);
|
|
310
|
+
await this.fd.read(footer, 0, footerSize, Number(footerStart));
|
|
307
311
|
if (footer.toString("utf8", 0, 4) !== "ZPCK" || footer.readUInt8(4) !== this.version)
|
|
308
312
|
return false;
|
|
309
313
|
const count = footer.readUInt32LE(5);
|
|
@@ -327,12 +331,12 @@ class ZPackDatabase {
|
|
|
327
331
|
let offset = 0n;
|
|
328
332
|
const headerBuf = Buffer.alloc(2);
|
|
329
333
|
while (offset + 2n <= this.fileSize) {
|
|
330
|
-
const { bytesRead } = await this.fd.read(headerBuf, 0, 2, offset);
|
|
334
|
+
const { bytesRead } = await this.fd.read(headerBuf, 0, 2, Number(offset));
|
|
331
335
|
if (bytesRead < 2)
|
|
332
336
|
break;
|
|
333
337
|
const payloadSize = headerBuf.readUInt16LE(0);
|
|
334
338
|
const idBuf = Buffer.alloc(4);
|
|
335
|
-
await this.fd.read(idBuf, 0, 4, offset + 2n);
|
|
339
|
+
await this.fd.read(idBuf, 0, 4, Number(offset + 2n));
|
|
336
340
|
const docId = idBuf.readUInt32LE(0);
|
|
337
341
|
if (payloadSize === 4)
|
|
338
342
|
this.index.delete(docId);
|
|
@@ -343,6 +347,9 @@ class ZPackDatabase {
|
|
|
343
347
|
}
|
|
344
348
|
}
|
|
345
349
|
exports.ZPackDatabase = ZPackDatabase;
|
|
350
|
+
/**
|
|
351
|
+
* ZPackAdapter: IDatabase Implementation
|
|
352
|
+
*/
|
|
346
353
|
class ZPackAdapter extends IDatabase_1.IDatabase {
|
|
347
354
|
constructor(config) {
|
|
348
355
|
super();
|
|
@@ -351,6 +358,8 @@ class ZPackAdapter extends IDatabase_1.IDatabase {
|
|
|
351
358
|
this.rowCache = new Map();
|
|
352
359
|
this.secondary = new Map();
|
|
353
360
|
this.indexedFields = new Map();
|
|
361
|
+
this._isClosing = false;
|
|
362
|
+
this._executing = Promise.resolve();
|
|
354
363
|
this.db = new ZPackDatabase(config.path, { autoFlush: !!config.autoFlush, compression: !!config.cache });
|
|
355
364
|
if (config.indexFields) {
|
|
356
365
|
for (const [table, fields] of Object.entries(config.indexFields)) {
|
|
@@ -363,16 +372,66 @@ class ZPackAdapter extends IDatabase_1.IDatabase {
|
|
|
363
372
|
await this.db.open();
|
|
364
373
|
for (const physicalDocId of this.db.keys()) {
|
|
365
374
|
const doc = await this.db.get(physicalDocId);
|
|
366
|
-
if (!doc || !doc.t ||
|
|
375
|
+
if (!doc || !doc.t || isNaN(Number(doc._id)))
|
|
367
376
|
continue;
|
|
368
377
|
const table = String(doc.t), idNum = Number(doc._id);
|
|
369
378
|
await this.ensureTable(table);
|
|
370
|
-
this.keyIndex.get(table).set(idNum, physicalDocId);
|
|
379
|
+
this.keyIndex.get(table).set(idNum, BigInt(physicalDocId));
|
|
371
380
|
if (idNum > (this.tableMaxId.get(table) || 0))
|
|
372
381
|
this.tableMaxId.set(table, idNum);
|
|
373
382
|
this._updateSecondaryIndex(table, idNum, doc);
|
|
374
383
|
}
|
|
375
384
|
}
|
|
385
|
+
async _execute(fn) {
|
|
386
|
+
if (this._isClosing)
|
|
387
|
+
throw new Error("ZPack: Adaptör kapanıyor.");
|
|
388
|
+
const next = this._executing.then(async () => {
|
|
389
|
+
if (this._isClosing)
|
|
390
|
+
return;
|
|
391
|
+
await this.initPromise;
|
|
392
|
+
return fn();
|
|
393
|
+
});
|
|
394
|
+
this._executing = next.catch(() => { });
|
|
395
|
+
return next;
|
|
396
|
+
}
|
|
397
|
+
// --- INTERNAL RAW METHODS (No Queue) to prevent deadlocks ---
|
|
398
|
+
async _rawSelect(table, where = null) {
|
|
399
|
+
await this.ensureTable(table);
|
|
400
|
+
if (where && Object.keys(where).length === 1) {
|
|
401
|
+
const [field, value] = Object.entries(where)[0];
|
|
402
|
+
const index = this.secondary.get(table)?.get(field);
|
|
403
|
+
if (index) {
|
|
404
|
+
const matches = index.get(String(value));
|
|
405
|
+
if (matches) {
|
|
406
|
+
const results = [];
|
|
407
|
+
for (const logicalId of matches) {
|
|
408
|
+
const physicalId = this.keyIndex.get(table).get(logicalId);
|
|
409
|
+
if (physicalId !== undefined) {
|
|
410
|
+
const doc = await this.db.get(Number(physicalId));
|
|
411
|
+
if (doc)
|
|
412
|
+
results.push(doc);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
return results;
|
|
416
|
+
}
|
|
417
|
+
return [];
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
const results = [];
|
|
421
|
+
for (const [logicalId, physicalId] of this.keyIndex.get(table).entries()) {
|
|
422
|
+
let row = this.rowCache.get(table).get(logicalId);
|
|
423
|
+
if (!row) {
|
|
424
|
+
const doc = await this.db.get(Number(physicalId));
|
|
425
|
+
if (!doc)
|
|
426
|
+
continue;
|
|
427
|
+
row = doc;
|
|
428
|
+
this.rowCache.get(table).set(logicalId, row);
|
|
429
|
+
}
|
|
430
|
+
if (this._matches(row, where))
|
|
431
|
+
results.push({ ...row });
|
|
432
|
+
}
|
|
433
|
+
return results;
|
|
434
|
+
}
|
|
376
435
|
async ensureTable(table) {
|
|
377
436
|
if (!this.tableMaxId.has(table)) {
|
|
378
437
|
this.tableMaxId.set(table, 0);
|
|
@@ -409,125 +468,129 @@ class ZPackAdapter extends IDatabase_1.IDatabase {
|
|
|
409
468
|
return out;
|
|
410
469
|
}
|
|
411
470
|
_matches(row, where) {
|
|
412
|
-
if (!where)
|
|
471
|
+
if (!where || Object.keys(where).length === 0)
|
|
413
472
|
return true;
|
|
414
473
|
return Object.entries(where).every(([k, v]) => String(row[k]) === String(v));
|
|
415
474
|
}
|
|
475
|
+
// --- PUBLIC METHODS (With Queue) ---
|
|
416
476
|
async select(table, where = null) {
|
|
417
|
-
|
|
418
|
-
await this.initPromise;
|
|
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
|
-
}
|
|
441
|
-
const results = [];
|
|
442
|
-
for (const [logicalId, physicalId] of this.keyIndex.get(table).entries()) {
|
|
443
|
-
let row = this.rowCache.get(table).get(logicalId);
|
|
444
|
-
if (!row) {
|
|
445
|
-
const doc = await this.db.get(physicalId);
|
|
446
|
-
if (!doc)
|
|
447
|
-
continue;
|
|
448
|
-
row = doc;
|
|
449
|
-
this.rowCache.get(table).set(logicalId, row);
|
|
450
|
-
}
|
|
451
|
-
if (this._matches(row, where))
|
|
452
|
-
results.push({ ...row });
|
|
453
|
-
}
|
|
454
|
-
this.recordMetric('select', table, Date.now() - start);
|
|
455
|
-
return results;
|
|
477
|
+
return this._execute(() => this._rawSelect(table, where));
|
|
456
478
|
}
|
|
457
479
|
async selectOne(table, where = null) {
|
|
458
480
|
const res = await this.select(table, where);
|
|
459
481
|
return res[0] || null;
|
|
460
482
|
}
|
|
461
483
|
async insert(table, data) {
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
return nextId;
|
|
484
|
+
return this._execute(async () => {
|
|
485
|
+
await this.ensureTable(table);
|
|
486
|
+
await this.runHooks('beforeInsert', table, data);
|
|
487
|
+
const nextId = (this.tableMaxId.get(table) || 0) + 1;
|
|
488
|
+
const record = this._coerce(table, data, nextId);
|
|
489
|
+
const physicalId = await this.db.insert(record);
|
|
490
|
+
this.tableMaxId.set(table, nextId);
|
|
491
|
+
this.keyIndex.get(table).set(nextId, BigInt(physicalId));
|
|
492
|
+
const fullRow = { _id: nextId, ...data };
|
|
493
|
+
this.rowCache.get(table).set(nextId, fullRow);
|
|
494
|
+
this._updateSecondaryIndex(table, nextId, fullRow);
|
|
495
|
+
await this.runHooks('afterInsert', table, fullRow);
|
|
496
|
+
return nextId;
|
|
497
|
+
});
|
|
477
498
|
}
|
|
478
499
|
async update(table, data, where) {
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
500
|
+
return this._execute(async () => {
|
|
501
|
+
const rows = await this._rawSelect(table, where);
|
|
502
|
+
for (const row of rows) {
|
|
503
|
+
const logicalId = Number(row._id);
|
|
504
|
+
await this.runHooks('beforeUpdate', table, { old: row, new: data });
|
|
505
|
+
const merged = { ...row, ...data };
|
|
506
|
+
const record = this._coerce(table, merged, logicalId);
|
|
507
|
+
const physicalId = await this.db.insert(record);
|
|
508
|
+
this.keyIndex.get(table).set(logicalId, BigInt(physicalId));
|
|
509
|
+
this.rowCache.get(table).set(logicalId, merged);
|
|
510
|
+
this._updateSecondaryIndex(table, logicalId, merged, row);
|
|
511
|
+
await this.runHooks('afterUpdate', table, merged);
|
|
512
|
+
}
|
|
513
|
+
return rows.length;
|
|
514
|
+
});
|
|
494
515
|
}
|
|
495
516
|
async delete(table, where) {
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
517
|
+
return this._execute(async () => {
|
|
518
|
+
const rows = await this._rawSelect(table, where);
|
|
519
|
+
for (const row of rows) {
|
|
520
|
+
const logicalId = Number(row._id);
|
|
521
|
+
await this.runHooks('beforeDelete', table, row);
|
|
522
|
+
const physicalId = this.keyIndex.get(table).get(logicalId);
|
|
523
|
+
if (physicalId !== undefined) {
|
|
524
|
+
await this.db.delete(Number(physicalId));
|
|
525
|
+
this.keyIndex.get(table).delete(logicalId);
|
|
526
|
+
this.rowCache.get(table).delete(logicalId);
|
|
527
|
+
this._updateSecondaryIndex(table, logicalId, {}, row);
|
|
528
|
+
}
|
|
529
|
+
await this.runHooks('afterDelete', table, row);
|
|
507
530
|
}
|
|
508
|
-
|
|
509
|
-
}
|
|
510
|
-
this.recordMetric('delete', table, Date.now() - start);
|
|
511
|
-
return rows.length;
|
|
531
|
+
return rows.length;
|
|
532
|
+
});
|
|
512
533
|
}
|
|
513
534
|
async set(table, data, where) {
|
|
514
|
-
|
|
515
|
-
|
|
535
|
+
return this._execute(async () => {
|
|
536
|
+
const existing = await this._rawSelect(table, where);
|
|
537
|
+
if (existing.length > 0) {
|
|
538
|
+
// Update logic here directly using _raw logic
|
|
539
|
+
const row = existing[0];
|
|
540
|
+
const logicalId = Number(row._id);
|
|
541
|
+
const merged = { ...row, ...data };
|
|
542
|
+
const record = this._coerce(table, merged, logicalId);
|
|
543
|
+
const physicalId = await this.db.insert(record);
|
|
544
|
+
this.keyIndex.get(table).set(logicalId, BigInt(physicalId));
|
|
545
|
+
this.rowCache.get(table).set(logicalId, merged);
|
|
546
|
+
this._updateSecondaryIndex(table, logicalId, merged, row);
|
|
547
|
+
return logicalId;
|
|
548
|
+
}
|
|
549
|
+
else {
|
|
550
|
+
// Insert logic here directly
|
|
551
|
+
const nextId = (this.tableMaxId.get(table) || 0) + 1;
|
|
552
|
+
const record = this._coerce(table, { ...where, ...data }, nextId);
|
|
553
|
+
const physicalId = await this.db.insert(record);
|
|
554
|
+
this.tableMaxId.set(table, nextId);
|
|
555
|
+
this.keyIndex.get(table).set(nextId, BigInt(physicalId));
|
|
556
|
+
const fullRow = { _id: nextId, ...where, ...data };
|
|
557
|
+
this.rowCache.get(table).set(nextId, fullRow);
|
|
558
|
+
this._updateSecondaryIndex(table, nextId, fullRow);
|
|
559
|
+
return nextId;
|
|
560
|
+
}
|
|
561
|
+
});
|
|
516
562
|
}
|
|
517
563
|
async bulkInsert(table, dataArray) {
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
564
|
+
return this._execute(async () => {
|
|
565
|
+
for (const d of dataArray) {
|
|
566
|
+
const nextId = (this.tableMaxId.get(table) || 0) + 1;
|
|
567
|
+
const record = this._coerce(table, d, nextId);
|
|
568
|
+
const physicalId = await this.db.insert(record);
|
|
569
|
+
this.tableMaxId.set(table, nextId);
|
|
570
|
+
this.keyIndex.get(table).set(nextId, BigInt(physicalId));
|
|
571
|
+
const fullRow = { _id: nextId, ...d };
|
|
572
|
+
this.rowCache.get(table).set(nextId, fullRow);
|
|
573
|
+
this._updateSecondaryIndex(table, nextId, fullRow);
|
|
574
|
+
}
|
|
575
|
+
return dataArray.length;
|
|
576
|
+
});
|
|
521
577
|
}
|
|
522
578
|
async increment(table, incs, where = {}) {
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
const
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
579
|
+
return this._execute(async () => {
|
|
580
|
+
const rows = await this._rawSelect(table, where);
|
|
581
|
+
for (const row of rows) {
|
|
582
|
+
const logicalId = Number(row._id);
|
|
583
|
+
const merged = { ...row };
|
|
584
|
+
for (const [f, v] of Object.entries(incs))
|
|
585
|
+
merged[f] = (Number(merged[f]) || 0) + v;
|
|
586
|
+
const record = this._coerce(table, merged, logicalId);
|
|
587
|
+
const physicalId = await this.db.insert(record);
|
|
588
|
+
this.keyIndex.get(table).set(logicalId, BigInt(physicalId));
|
|
589
|
+
this.rowCache.get(table).set(logicalId, merged);
|
|
590
|
+
this._updateSecondaryIndex(table, logicalId, merged, row);
|
|
591
|
+
}
|
|
592
|
+
return rows.length;
|
|
593
|
+
});
|
|
531
594
|
}
|
|
532
595
|
async decrement(table, decs, where = {}) {
|
|
533
596
|
const incs = {};
|
|
@@ -535,8 +598,19 @@ class ZPackAdapter extends IDatabase_1.IDatabase {
|
|
|
535
598
|
incs[k] = -decs[k];
|
|
536
599
|
return this.increment(table, incs, where);
|
|
537
600
|
}
|
|
538
|
-
async vacuum() {
|
|
539
|
-
|
|
601
|
+
async vacuum() {
|
|
602
|
+
return this._execute(async () => {
|
|
603
|
+
await this.db.vacuum();
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
async close() {
|
|
607
|
+
this._isClosing = true;
|
|
608
|
+
try {
|
|
609
|
+
await this._executing;
|
|
610
|
+
await this.db.close();
|
|
611
|
+
}
|
|
612
|
+
catch (e) { }
|
|
613
|
+
}
|
|
540
614
|
}
|
|
541
615
|
exports.ZPackAdapter = ZPackAdapter;
|
|
542
616
|
exports.default = ZPackAdapter;
|
package/dist/functions/toon.d.ts
CHANGED
package/dist/functions/toon.js
CHANGED
|
@@ -14,7 +14,7 @@ function stringify(data, indent = 0) {
|
|
|
14
14
|
if (typeof data === 'boolean' || typeof data === 'number')
|
|
15
15
|
return String(data);
|
|
16
16
|
if (typeof data === 'string') {
|
|
17
|
-
const hasSpecial = new RegExp('[\,\n:]').test(data);
|
|
17
|
+
const hasSpecial = new RegExp('[\,\n: ]').test(data);
|
|
18
18
|
if (hasSpecial)
|
|
19
19
|
return '"' + data.replace(/"/g, '\\"') + '"';
|
|
20
20
|
return data;
|
|
@@ -36,7 +36,7 @@ function stringify(data, indent = 0) {
|
|
|
36
36
|
if (val === null)
|
|
37
37
|
return 'null';
|
|
38
38
|
const valStr = String(val);
|
|
39
|
-
const hasSpecialRow = new RegExp('[\,\n:]').test(valStr);
|
|
39
|
+
const hasSpecialRow = new RegExp('[\,\n: ]').test(valStr);
|
|
40
40
|
return (typeof val === 'string' && hasSpecialRow) ? '"' + valStr + '"' : valStr;
|
|
41
41
|
}).join(',');
|
|
42
42
|
return space + ' ' + rowValues;
|
|
@@ -59,60 +59,86 @@ function stringify(data, indent = 0) {
|
|
|
59
59
|
}
|
|
60
60
|
return '';
|
|
61
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Advanced TOON Parser with Indentation Support for Deep Nesting
|
|
64
|
+
*/
|
|
62
65
|
function parse(toonStr) {
|
|
63
66
|
if (!toonStr || toonStr.trim() === '')
|
|
64
67
|
return {};
|
|
65
|
-
const lines = toonStr.split('\n').filter(l => l.trim() !== '');
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
68
|
+
const lines = toonStr.split('\n').filter(l => l.trim() !== '' || l.startsWith(' '));
|
|
69
|
+
function parseValue(val) {
|
|
70
|
+
const trimmed = val.trim().replace(/^"|"$/g, '');
|
|
71
|
+
if (trimmed === 'true')
|
|
72
|
+
return true;
|
|
73
|
+
if (trimmed === 'false')
|
|
74
|
+
return false;
|
|
75
|
+
if (trimmed === 'null')
|
|
76
|
+
return null;
|
|
77
|
+
if (trimmed === '[]')
|
|
78
|
+
return [];
|
|
79
|
+
if (trimmed === '{}')
|
|
80
|
+
return {};
|
|
81
|
+
if (!isNaN(Number(trimmed)) && trimmed !== '')
|
|
82
|
+
return Number(trimmed);
|
|
83
|
+
return trimmed;
|
|
84
|
+
}
|
|
85
|
+
function getIndent(line) {
|
|
86
|
+
const match = line.match(/^(\s*)/);
|
|
87
|
+
return match ? match[1].length : 0;
|
|
88
|
+
}
|
|
89
|
+
function processLines(startIndex, currentIndent) {
|
|
90
|
+
const result = {};
|
|
91
|
+
let i = startIndex;
|
|
92
|
+
while (i < lines.length) {
|
|
93
|
+
const line = lines[i];
|
|
94
|
+
const indent = getIndent(line);
|
|
95
|
+
const content = line.trim();
|
|
96
|
+
if (content === '') {
|
|
77
97
|
i++;
|
|
78
|
-
|
|
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);
|
|
98
|
+
continue;
|
|
95
99
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
const
|
|
100
|
+
if (indent < currentIndent)
|
|
101
|
+
break;
|
|
102
|
+
// Tabular Array Match: key[count]{fields}:
|
|
103
|
+
const tabularMatch = content.match(/^(\w+)\[(\d+)\]\{(.*)\}:$/);
|
|
104
|
+
if (tabularMatch) {
|
|
105
|
+
const key = tabularMatch[1];
|
|
106
|
+
const rowCount = parseInt(tabularMatch[2]);
|
|
107
|
+
const fields = tabularMatch[3].split(',');
|
|
108
|
+
const rows = [];
|
|
109
|
+
for (let j = 0; j < rowCount; j++) {
|
|
110
|
+
i++;
|
|
111
|
+
if (!lines[i])
|
|
112
|
+
break;
|
|
113
|
+
const values = lines[i].trim().split(',').map(v => parseValue(v));
|
|
114
|
+
const row = {};
|
|
115
|
+
fields.forEach((f, idx) => row[f] = values[idx]);
|
|
116
|
+
rows.push(row);
|
|
117
|
+
}
|
|
118
|
+
result[key] = rows;
|
|
119
|
+
i++;
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
// Standard Key-Value or Nested Object: key: value
|
|
123
|
+
const kvMatch = content.match(/^(\w+):(.*)$/);
|
|
100
124
|
if (kvMatch) {
|
|
101
125
|
const key = kvMatch[1];
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
else
|
|
111
|
-
|
|
112
|
-
|
|
126
|
+
const valuePart = kvMatch[2].trim();
|
|
127
|
+
if (valuePart === '' && i + 1 < lines.length && getIndent(lines[i + 1]) > indent) {
|
|
128
|
+
// It's a nested object
|
|
129
|
+
const [nestedObj, nextIndex] = processLines(i + 1, getIndent(lines[i + 1]));
|
|
130
|
+
result[key] = nestedObj;
|
|
131
|
+
i = nextIndex;
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
result[key] = parseValue(valuePart);
|
|
136
|
+
}
|
|
113
137
|
}
|
|
138
|
+
i++;
|
|
114
139
|
}
|
|
115
|
-
i
|
|
140
|
+
return [result, i];
|
|
116
141
|
}
|
|
117
|
-
|
|
142
|
+
const [finalResult] = processLines(0, 0);
|
|
143
|
+
return finalResult;
|
|
118
144
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const database_1 = __importDefault(require("../database"));
|
|
7
|
+
const run = async () => {
|
|
8
|
+
const db = (0, database_1.default)({
|
|
9
|
+
adapter: 'toon',
|
|
10
|
+
config: {
|
|
11
|
+
path: './data.toon',
|
|
12
|
+
cache: {
|
|
13
|
+
type: 'memory',
|
|
14
|
+
ttl: 1000,
|
|
15
|
+
max: 1000,
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
await db.set('testTable', { userName: 'Onur Ege', age: 21 }, { userName: 'Onur Ege' });
|
|
20
|
+
console.log(await db.selectOne('testTable', { age: 21 }));
|
|
21
|
+
};
|
|
22
|
+
run();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onurege3467/zerohelper",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "10.0.0",
|
|
4
4
|
"description": "ZeroHelper is a versatile high-performance utility library and database framework for Node.js, fully written in TypeScript.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function isPhone(phone: string): boolean;
|