@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.
@@ -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.add(meta.docId); // Bugfix: added to deleted, should be removed
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 || !Number.isFinite(Number(doc._id)))
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
- const start = Date.now();
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
- const start = Date.now();
463
- await this.initPromise;
464
- await this.ensureTable(table);
465
- await this.runHooks('beforeInsert', table, data);
466
- const nextId = (this.tableMaxId.get(table) || 0) + 1;
467
- const record = this._coerce(table, data, nextId);
468
- const physicalId = await this.db.insert(record);
469
- this.tableMaxId.set(table, nextId);
470
- this.keyIndex.get(table).set(nextId, physicalId);
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);
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
- const start = Date.now();
480
- const rows = await this.select(table, where);
481
- for (const row of rows) {
482
- const logicalId = row._id;
483
- await this.runHooks('beforeUpdate', table, { old: row, new: data });
484
- const merged = { ...row, ...data };
485
- const record = this._coerce(table, merged, logicalId);
486
- const physicalId = await this.db.insert(record);
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);
491
- }
492
- this.recordMetric('update', table, Date.now() - start);
493
- return rows.length;
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
- const start = Date.now();
497
- const rows = await this.select(table, where);
498
- for (const row of rows) {
499
- const logicalId = row._id;
500
- await this.runHooks('beforeDelete', table, row);
501
- const physicalId = this.keyIndex.get(table).get(logicalId);
502
- if (physicalId !== undefined) {
503
- await this.db.delete(physicalId);
504
- this.keyIndex.get(table).delete(logicalId);
505
- this.rowCache.get(table).delete(logicalId);
506
- this._updateSecondaryIndex(table, logicalId, {}, row);
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
- await this.runHooks('afterDelete', table, row);
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
- const ex = await this.selectOne(table, where);
515
- return ex ? this.update(table, data, where) : this.insert(table, { ...where, ...data });
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
- for (const d of dataArray)
519
- await this.insert(table, d);
520
- return dataArray.length;
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
- const rows = await this.select(table, where);
524
- for (const row of rows) {
525
- const updated = { ...row };
526
- for (const [f, v] of Object.entries(incs))
527
- updated[f] = (Number(updated[f]) || 0) + v;
528
- await this.update(table, updated, { _id: row._id });
529
- }
530
- return rows.length;
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() { await this.db.vacuum(); }
539
- async close() { await this.db.close(); }
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;
@@ -4,4 +4,7 @@
4
4
  * API matches standard JSON object (stringify/parse).
5
5
  */
6
6
  export declare function stringify(data: any, indent?: number): string;
7
+ /**
8
+ * Advanced TOON Parser with Indentation Support for Deep Nesting
9
+ */
7
10
  export declare function parse(toonStr: string): any;
@@ -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
- 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++) {
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
- 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);
98
+ continue;
95
99
  }
96
- result[tableName] = rows;
97
- }
98
- else {
99
- const kvMatch = line.match(/^(\w+):\s*(.*)$/);
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 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;
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
- return result;
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": "9.2.0",
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;
@@ -1,7 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isPhone = isPhone;
4
- function isPhone(phone) {
5
- const phoneRegex = /^[\+]?[1-9][\d]{0,15}$/;
6
- return phoneRegex.test(phone.replace(/[\s\-\(\)]/g, ''));
7
- }