@frogfish/k2db 3.0.6 → 3.0.7
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/db.js +154 -21
- package/package.json +1 -1
package/db.js
CHANGED
|
@@ -457,7 +457,23 @@ export class K2DB {
|
|
|
457
457
|
const msg = err instanceof Error
|
|
458
458
|
? `Failed to connect to MongoDB: ${err.message}`
|
|
459
459
|
: `Failed to connect to MongoDB: ${String(err)}`;
|
|
460
|
-
|
|
460
|
+
// Preserve existing K2Error severity if already typed; otherwise map to SERVICE_UNAVAILABLE.
|
|
461
|
+
const sev = err instanceof K2Error ? undefined : ServiceError.SERVICE_UNAVAILABLE;
|
|
462
|
+
const k2 = chain(err, "sys_mdb_init", msg, sev, "k2db.init")
|
|
463
|
+
.setSensitive({
|
|
464
|
+
op: "init",
|
|
465
|
+
db: this.conf?.name,
|
|
466
|
+
// safeConnectUrl is already masked (no credentials)
|
|
467
|
+
connectUrl: safeConnectUrl,
|
|
468
|
+
options: summariseValueShape(options),
|
|
469
|
+
mongo: normaliseMongoError(err),
|
|
470
|
+
});
|
|
471
|
+
// Emit once (deduped per error instance)
|
|
472
|
+
emitDbError(k2, {
|
|
473
|
+
op: "init",
|
|
474
|
+
db: this.conf?.name,
|
|
475
|
+
});
|
|
476
|
+
throw k2;
|
|
461
477
|
}
|
|
462
478
|
})().finally(() => {
|
|
463
479
|
// Allow retry after failure; once initialized, subsequent calls return early.
|
|
@@ -540,12 +556,16 @@ export class K2DB {
|
|
|
540
556
|
}
|
|
541
557
|
catch (err) {
|
|
542
558
|
const sev = err instanceof K2Error ? undefined : ServiceError.SYSTEM_ERROR;
|
|
543
|
-
|
|
544
|
-
.setSensitive({
|
|
559
|
+
const k2 = chain(err, "sys_mdb_gc", `Error getting collection: ${collectionName}`, sev, "k2db.getCollection").setSensitive({
|
|
545
560
|
op: "getCollection",
|
|
546
561
|
collection: collectionName,
|
|
547
562
|
mongo: normaliseMongoError(err),
|
|
548
563
|
});
|
|
564
|
+
emitDbError(k2, {
|
|
565
|
+
op: "getCollection",
|
|
566
|
+
collection: collectionName,
|
|
567
|
+
});
|
|
568
|
+
throw k2;
|
|
549
569
|
}
|
|
550
570
|
}
|
|
551
571
|
/**
|
|
@@ -557,10 +577,35 @@ export class K2DB {
|
|
|
557
577
|
async get(collectionName, uuid, scope) {
|
|
558
578
|
const id = K2DB.normalizeId(uuid);
|
|
559
579
|
// Note: findOne() decrypts secure-prefixed fields for single-record reads when encryption is enabled.
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
580
|
+
let res;
|
|
581
|
+
try {
|
|
582
|
+
res = await this.findOne(collectionName, {
|
|
583
|
+
_uuid: id,
|
|
584
|
+
_deleted: { $ne: true },
|
|
585
|
+
}, undefined, scope);
|
|
586
|
+
}
|
|
587
|
+
catch (err) {
|
|
588
|
+
const sev = err instanceof K2Error ? undefined : ServiceError.SYSTEM_ERROR;
|
|
589
|
+
const k2 = chain(err, "sys_mdb_get", "Error getting document", sev, "k2db.get");
|
|
590
|
+
// Merge/attach sensitive diagnostics without stomping any existing sensitive payload.
|
|
591
|
+
const prevSensitive = k2.sensitive;
|
|
592
|
+
const mergedSensitive = prevSensitive && typeof prevSensitive === "object" ? { ...prevSensitive } : {};
|
|
593
|
+
Object.assign(mergedSensitive, {
|
|
594
|
+
op: "get",
|
|
595
|
+
collection: collectionName,
|
|
596
|
+
uuid: id,
|
|
597
|
+
scope,
|
|
598
|
+
mongo: normaliseMongoError(err),
|
|
599
|
+
});
|
|
600
|
+
k2.setSensitive?.(mergedSensitive);
|
|
601
|
+
// Emit once (deduped per error instance)
|
|
602
|
+
emitDbError(k2, {
|
|
603
|
+
op: "get",
|
|
604
|
+
collection: collectionName,
|
|
605
|
+
uuid: id,
|
|
606
|
+
});
|
|
607
|
+
throw k2;
|
|
608
|
+
}
|
|
564
609
|
if (!res) {
|
|
565
610
|
throw new K2Error(ServiceError.NOT_FOUND, "Document not found", "sys_mdb_get_not_found");
|
|
566
611
|
}
|
|
@@ -628,8 +673,11 @@ export class K2DB {
|
|
|
628
673
|
}
|
|
629
674
|
catch (err) {
|
|
630
675
|
const sev = err instanceof K2Error ? undefined : ServiceError.SYSTEM_ERROR;
|
|
631
|
-
|
|
632
|
-
|
|
676
|
+
const k2 = chain(err, "sys_mdb_fo", "Error finding document", sev, "k2db.findOne");
|
|
677
|
+
// Merge/attach sensitive diagnostics without stomping any existing sensitive payload.
|
|
678
|
+
const prevSensitive = k2.sensitive;
|
|
679
|
+
const mergedSensitive = prevSensitive && typeof prevSensitive === "object" ? { ...prevSensitive } : {};
|
|
680
|
+
Object.assign(mergedSensitive, {
|
|
633
681
|
op: "findOne",
|
|
634
682
|
collection: collectionName,
|
|
635
683
|
scope,
|
|
@@ -640,6 +688,12 @@ export class K2DB {
|
|
|
640
688
|
projectionPreview: redactShallowSecrets(projection),
|
|
641
689
|
mongo: normaliseMongoError(err),
|
|
642
690
|
});
|
|
691
|
+
k2.setSensitive?.(mergedSensitive);
|
|
692
|
+
emitDbError(k2, {
|
|
693
|
+
op: "findOne",
|
|
694
|
+
collection: collectionName,
|
|
695
|
+
});
|
|
696
|
+
throw k2;
|
|
643
697
|
}
|
|
644
698
|
}
|
|
645
699
|
/**
|
|
@@ -720,7 +774,7 @@ export class K2DB {
|
|
|
720
774
|
}
|
|
721
775
|
catch (err) {
|
|
722
776
|
const sev = err instanceof K2Error ? undefined : ServiceError.SYSTEM_ERROR;
|
|
723
|
-
|
|
777
|
+
const k2 = chain(err, "sys_mdb_find_error", "Error executing find query", sev, "k2db.find")
|
|
724
778
|
.setSensitive({
|
|
725
779
|
op: "find",
|
|
726
780
|
collection: collectionName,
|
|
@@ -736,6 +790,13 @@ export class K2DB {
|
|
|
736
790
|
projectionPreview: redactShallowSecrets(projection),
|
|
737
791
|
mongo: normaliseMongoError(err),
|
|
738
792
|
});
|
|
793
|
+
emitDbError(k2, {
|
|
794
|
+
op: "find",
|
|
795
|
+
collection: collectionName,
|
|
796
|
+
skip,
|
|
797
|
+
limit,
|
|
798
|
+
});
|
|
799
|
+
throw k2;
|
|
739
800
|
}
|
|
740
801
|
}
|
|
741
802
|
/**
|
|
@@ -1385,7 +1446,7 @@ export class K2DB {
|
|
|
1385
1446
|
throw new K2Error(ServiceError.ALREADY_EXISTS, `A document with _uuid ${document._uuid} already exists.`, "sys_mdb_crv3");
|
|
1386
1447
|
}
|
|
1387
1448
|
const sev = err instanceof K2Error ? undefined : ServiceError.SYSTEM_ERROR;
|
|
1388
|
-
|
|
1449
|
+
const k2 = chain(err, "sys_mdb_sav", "Error saving object to database", sev, "k2db.create")
|
|
1389
1450
|
.setSensitive({
|
|
1390
1451
|
op: "insertOne",
|
|
1391
1452
|
collection: collectionName,
|
|
@@ -1395,6 +1456,12 @@ export class K2DB {
|
|
|
1395
1456
|
userFieldPreview: redactShallowSecrets(safeData),
|
|
1396
1457
|
mongo: normaliseMongoError(err),
|
|
1397
1458
|
});
|
|
1459
|
+
emitDbError(k2, {
|
|
1460
|
+
op: "create",
|
|
1461
|
+
collection: collectionName,
|
|
1462
|
+
uuid: document._uuid,
|
|
1463
|
+
});
|
|
1464
|
+
throw k2;
|
|
1398
1465
|
}
|
|
1399
1466
|
}
|
|
1400
1467
|
/**
|
|
@@ -1438,7 +1505,7 @@ export class K2DB {
|
|
|
1438
1505
|
}
|
|
1439
1506
|
catch (err) {
|
|
1440
1507
|
const sev = err instanceof K2Error ? undefined : ServiceError.SYSTEM_ERROR;
|
|
1441
|
-
|
|
1508
|
+
const k2 = chain(err, "sys_mdb_update1", `Error updating ${collectionName}`, sev, "k2db.updateAll")
|
|
1442
1509
|
.setSensitive({
|
|
1443
1510
|
op: "updateMany",
|
|
1444
1511
|
collection: collectionName,
|
|
@@ -1450,6 +1517,11 @@ export class K2DB {
|
|
|
1450
1517
|
valuesPreview: redactShallowSecrets(values),
|
|
1451
1518
|
mongo: normaliseMongoError(err),
|
|
1452
1519
|
});
|
|
1520
|
+
emitDbError(k2, {
|
|
1521
|
+
op: "updateAll",
|
|
1522
|
+
collection: collectionName,
|
|
1523
|
+
});
|
|
1524
|
+
throw k2;
|
|
1453
1525
|
}
|
|
1454
1526
|
}
|
|
1455
1527
|
/**
|
|
@@ -1506,7 +1578,7 @@ export class K2DB {
|
|
|
1506
1578
|
}
|
|
1507
1579
|
catch (err) {
|
|
1508
1580
|
const sev = err instanceof K2Error ? undefined : ServiceError.SYSTEM_ERROR;
|
|
1509
|
-
|
|
1581
|
+
const k2 = chain(err, "sys_mdb_update_error", `Error updating ${collectionName}`, sev, "k2db.update")
|
|
1510
1582
|
.setSensitive({
|
|
1511
1583
|
op: replace ? "replaceOne" : "updateOne",
|
|
1512
1584
|
collection: collectionName,
|
|
@@ -1517,6 +1589,13 @@ export class K2DB {
|
|
|
1517
1589
|
dataPreview: redactShallowSecrets(data),
|
|
1518
1590
|
mongo: normaliseMongoError(err),
|
|
1519
1591
|
});
|
|
1592
|
+
emitDbError(k2, {
|
|
1593
|
+
op: "update",
|
|
1594
|
+
collection: collectionName,
|
|
1595
|
+
uuid: id,
|
|
1596
|
+
replace,
|
|
1597
|
+
});
|
|
1598
|
+
throw k2;
|
|
1520
1599
|
}
|
|
1521
1600
|
}
|
|
1522
1601
|
/**
|
|
@@ -1535,8 +1614,7 @@ export class K2DB {
|
|
|
1535
1614
|
}
|
|
1536
1615
|
catch (err) {
|
|
1537
1616
|
const sev = err instanceof K2Error ? undefined : ServiceError.SYSTEM_ERROR;
|
|
1538
|
-
|
|
1539
|
-
.setSensitive({
|
|
1617
|
+
const k2 = chain(err, "sys_mdb_deleteall_update", `Error deleting from ${collectionName}`, sev, "k2db.deleteAll").setSensitive({
|
|
1540
1618
|
op: "softDeleteMany",
|
|
1541
1619
|
collection: collectionName,
|
|
1542
1620
|
scope,
|
|
@@ -1544,6 +1622,11 @@ export class K2DB {
|
|
|
1544
1622
|
criteriaPreview: redactShallowSecrets(criteria),
|
|
1545
1623
|
mongo: normaliseMongoError(err),
|
|
1546
1624
|
});
|
|
1625
|
+
emitDbError(k2, {
|
|
1626
|
+
op: "deleteAll",
|
|
1627
|
+
collection: collectionName,
|
|
1628
|
+
});
|
|
1629
|
+
throw k2;
|
|
1547
1630
|
}
|
|
1548
1631
|
}
|
|
1549
1632
|
/**
|
|
@@ -1573,14 +1656,19 @@ export class K2DB {
|
|
|
1573
1656
|
}
|
|
1574
1657
|
catch (err) {
|
|
1575
1658
|
const sev = err instanceof K2Error ? undefined : ServiceError.SYSTEM_ERROR;
|
|
1576
|
-
|
|
1577
|
-
.setSensitive({
|
|
1659
|
+
const k2 = chain(err, "sys_mdb_remove_upd", "Error removing object from collection", sev, "k2db.delete").setSensitive({
|
|
1578
1660
|
op: "softDeleteOne",
|
|
1579
1661
|
collection: collectionName,
|
|
1580
1662
|
uuid: id,
|
|
1581
1663
|
scope,
|
|
1582
1664
|
mongo: normaliseMongoError(err),
|
|
1583
1665
|
});
|
|
1666
|
+
emitDbError(k2, {
|
|
1667
|
+
op: "delete",
|
|
1668
|
+
collection: collectionName,
|
|
1669
|
+
uuid: id,
|
|
1670
|
+
});
|
|
1671
|
+
throw k2;
|
|
1584
1672
|
}
|
|
1585
1673
|
}
|
|
1586
1674
|
/**
|
|
@@ -1641,8 +1729,9 @@ export class K2DB {
|
|
|
1641
1729
|
}
|
|
1642
1730
|
const collection = await this.getCollection(collectionName);
|
|
1643
1731
|
const cutoff = Date.now() - olderThanMs;
|
|
1732
|
+
let delFilter;
|
|
1644
1733
|
try {
|
|
1645
|
-
|
|
1734
|
+
delFilter = this.applyScopeToCriteria({
|
|
1646
1735
|
_deleted: true,
|
|
1647
1736
|
_updated: { $lte: cutoff },
|
|
1648
1737
|
}, scope);
|
|
@@ -1650,7 +1739,23 @@ export class K2DB {
|
|
|
1650
1739
|
return { purged: res.deletedCount ?? 0 };
|
|
1651
1740
|
}
|
|
1652
1741
|
catch (err) {
|
|
1653
|
-
|
|
1742
|
+
const sev = err instanceof K2Error ? undefined : ServiceError.SYSTEM_ERROR;
|
|
1743
|
+
const k2 = chain(err, 'sys_mdb_purge_older', 'Error purging deleted items by age', sev, 'k2db.purgeDeletedOlderThan').setSensitive({
|
|
1744
|
+
op: 'purgeDeletedOlderThan',
|
|
1745
|
+
collection: collectionName,
|
|
1746
|
+
scope,
|
|
1747
|
+
olderThanMs,
|
|
1748
|
+
cutoff,
|
|
1749
|
+
delFilterShape: summariseValueShape(delFilter),
|
|
1750
|
+
delFilterPreview: redactShallowSecrets(delFilter),
|
|
1751
|
+
mongo: normaliseMongoError(err),
|
|
1752
|
+
});
|
|
1753
|
+
emitDbError(k2, {
|
|
1754
|
+
op: 'purgeDeletedOlderThan',
|
|
1755
|
+
collection: collectionName,
|
|
1756
|
+
olderThanMs,
|
|
1757
|
+
});
|
|
1758
|
+
throw k2;
|
|
1654
1759
|
}
|
|
1655
1760
|
}
|
|
1656
1761
|
/**
|
|
@@ -1672,7 +1777,23 @@ export class K2DB {
|
|
|
1672
1777
|
return { status: "restored", modified: res.modifiedCount };
|
|
1673
1778
|
}
|
|
1674
1779
|
catch (err) {
|
|
1675
|
-
|
|
1780
|
+
const sev = err instanceof K2Error ? undefined : ServiceError.SYSTEM_ERROR;
|
|
1781
|
+
const k2 = chain(err, "sys_mdb_pres", "Error restoring a deleted item", sev, "k2db.restore")
|
|
1782
|
+
.setSensitive({
|
|
1783
|
+
op: "restore",
|
|
1784
|
+
collection: collectionName,
|
|
1785
|
+
scope,
|
|
1786
|
+
criteriaShape: summariseValueShape(crit),
|
|
1787
|
+
criteriaPreview: redactShallowSecrets(crit),
|
|
1788
|
+
queryShape: summariseValueShape(query),
|
|
1789
|
+
queryPreview: redactShallowSecrets(query),
|
|
1790
|
+
mongo: normaliseMongoError(err),
|
|
1791
|
+
});
|
|
1792
|
+
emitDbError(k2, {
|
|
1793
|
+
op: "restore",
|
|
1794
|
+
collection: collectionName,
|
|
1795
|
+
});
|
|
1796
|
+
throw k2;
|
|
1676
1797
|
}
|
|
1677
1798
|
}
|
|
1678
1799
|
/**
|
|
@@ -1735,7 +1856,19 @@ export class K2DB {
|
|
|
1735
1856
|
return { status: "ok" };
|
|
1736
1857
|
}
|
|
1737
1858
|
catch (err) {
|
|
1738
|
-
|
|
1859
|
+
const sev = err instanceof K2Error ? undefined : ServiceError.SYSTEM_ERROR;
|
|
1860
|
+
const k2 = chain(err, "sys_mdb_drop", "Error dropping collection", sev, "k2db.drop").setSensitive({
|
|
1861
|
+
op: "drop",
|
|
1862
|
+
collection: collectionName,
|
|
1863
|
+
scope,
|
|
1864
|
+
normalizedScope,
|
|
1865
|
+
mongo: normaliseMongoError(err),
|
|
1866
|
+
});
|
|
1867
|
+
emitDbError(k2, {
|
|
1868
|
+
op: "drop",
|
|
1869
|
+
collection: collectionName,
|
|
1870
|
+
});
|
|
1871
|
+
throw k2;
|
|
1739
1872
|
}
|
|
1740
1873
|
}
|
|
1741
1874
|
/**
|