@frogfish/k2db 2.0.3 → 2.0.6
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/dist/db.d.ts +11 -0
- package/dist/db.js +44 -2
- package/dist/package.json +1 -1
- package/package.json +1 -1
package/dist/db.d.ts
CHANGED
|
@@ -47,6 +47,9 @@ export interface DropResult {
|
|
|
47
47
|
export interface PurgeResult {
|
|
48
48
|
id: string;
|
|
49
49
|
}
|
|
50
|
+
export interface PurgeManyResult {
|
|
51
|
+
purged: number;
|
|
52
|
+
}
|
|
50
53
|
export interface VersionedUpdateResult {
|
|
51
54
|
updated: number;
|
|
52
55
|
versionSaved: number;
|
|
@@ -150,6 +153,14 @@ export declare class K2DB {
|
|
|
150
153
|
* @param id - UUID of the document.
|
|
151
154
|
*/
|
|
152
155
|
purge(collectionName: string, id: string): Promise<PurgeResult>;
|
|
156
|
+
/**
|
|
157
|
+
* Permanently deletes all documents that are soft-deleted and whose _updated
|
|
158
|
+
* timestamp is older than the provided threshold (in milliseconds ago).
|
|
159
|
+
* @param collectionName - Name of the collection.
|
|
160
|
+
* @param olderThanMs - Age threshold in milliseconds; documents with
|
|
161
|
+
* `_updated <= (Date.now() - olderThanMs)` will be purged.
|
|
162
|
+
*/
|
|
163
|
+
purgeDeletedOlderThan(collectionName: string, olderThanMs: number): Promise<PurgeManyResult>;
|
|
153
164
|
/**
|
|
154
165
|
* Restores a soft-deleted document.
|
|
155
166
|
* @param collectionName - Name of the collection.
|
package/dist/db.js
CHANGED
|
@@ -398,9 +398,19 @@ export class K2DB {
|
|
|
398
398
|
this.validateCollectionName(collectionName);
|
|
399
399
|
const collection = await this.getCollection(collectionName);
|
|
400
400
|
debug(`Updating ${collectionName} with criteria: ${JSON.stringify(criteria)}`);
|
|
401
|
+
// Preserve intent to set _deleted during internal soft-delete operations.
|
|
402
|
+
// stripReservedFields removes underscore-prefixed keys (by design) to protect
|
|
403
|
+
// internal fields from user updates. However, deleteAll() legitimately passes
|
|
404
|
+
// {_deleted: true}. Capture and restore it here.
|
|
405
|
+
const deletedFlag = Object.prototype.hasOwnProperty.call(values, "_deleted")
|
|
406
|
+
? values._deleted
|
|
407
|
+
: undefined;
|
|
401
408
|
values = K2DB.stripReservedFields(values);
|
|
402
409
|
values = this.applySchema(collectionName, values, /*partial*/ true);
|
|
403
410
|
values._updated = Date.now();
|
|
411
|
+
if (deletedFlag !== undefined) {
|
|
412
|
+
values._deleted = deletedFlag;
|
|
413
|
+
}
|
|
404
414
|
criteria = {
|
|
405
415
|
...criteria,
|
|
406
416
|
_deleted: { $ne: true },
|
|
@@ -507,6 +517,10 @@ export class K2DB {
|
|
|
507
517
|
}
|
|
508
518
|
}
|
|
509
519
|
catch (err) {
|
|
520
|
+
// Preserve existing K2Error classifications (e.g., NOT_FOUND)
|
|
521
|
+
if (err instanceof K2Error) {
|
|
522
|
+
throw err;
|
|
523
|
+
}
|
|
510
524
|
throw new K2Error(ServiceError.SYSTEM_ERROR, "Error removing object from collection", "sys_mdb_remove_upd", this.normalizeError(err));
|
|
511
525
|
}
|
|
512
526
|
}
|
|
@@ -535,6 +549,31 @@ export class K2DB {
|
|
|
535
549
|
throw new K2Error(ServiceError.SYSTEM_ERROR, `Error purging item with id: ${id}`, "sys_mdb_pg", this.normalizeError(err));
|
|
536
550
|
}
|
|
537
551
|
}
|
|
552
|
+
/**
|
|
553
|
+
* Permanently deletes all documents that are soft-deleted and whose _updated
|
|
554
|
+
* timestamp is older than the provided threshold (in milliseconds ago).
|
|
555
|
+
* @param collectionName - Name of the collection.
|
|
556
|
+
* @param olderThanMs - Age threshold in milliseconds; documents with
|
|
557
|
+
* `_updated <= (Date.now() - olderThanMs)` will be purged.
|
|
558
|
+
*/
|
|
559
|
+
async purgeDeletedOlderThan(collectionName, olderThanMs) {
|
|
560
|
+
this.validateCollectionName(collectionName);
|
|
561
|
+
if (typeof olderThanMs !== 'number' || !isFinite(olderThanMs) || olderThanMs < 0) {
|
|
562
|
+
throw new K2Error(ServiceError.BAD_REQUEST, 'olderThanMs must be a non-negative number', 'sys_mdb_purge_older_invalid');
|
|
563
|
+
}
|
|
564
|
+
const collection = await this.getCollection(collectionName);
|
|
565
|
+
const cutoff = Date.now() - olderThanMs;
|
|
566
|
+
try {
|
|
567
|
+
const res = await this.runTimed('deleteMany', { collectionName, olderThanMs, cutoff }, async () => await collection.deleteMany({
|
|
568
|
+
_deleted: true,
|
|
569
|
+
_updated: { $lte: cutoff },
|
|
570
|
+
}));
|
|
571
|
+
return { purged: res.deletedCount ?? 0 };
|
|
572
|
+
}
|
|
573
|
+
catch (err) {
|
|
574
|
+
throw new K2Error(ServiceError.SYSTEM_ERROR, 'Error purging deleted items by age', 'sys_mdb_purge_older', this.normalizeError(err));
|
|
575
|
+
}
|
|
576
|
+
}
|
|
538
577
|
/**
|
|
539
578
|
* Restores a soft-deleted document.
|
|
540
579
|
* @param collectionName - Name of the collection.
|
|
@@ -545,7 +584,8 @@ export class K2DB {
|
|
|
545
584
|
const query = { ...(criteria || {}), _deleted: true };
|
|
546
585
|
try {
|
|
547
586
|
const res = await this.runTimed("updateMany", { collectionName, query }, async () => await collection.updateMany(query, {
|
|
548
|
-
|
|
587
|
+
// Restoring is a data change: flip _deleted and bump _updated
|
|
588
|
+
$set: { _deleted: false, _updated: Date.now() },
|
|
549
589
|
}));
|
|
550
590
|
return { status: "restored", modified: res.modifiedCount };
|
|
551
591
|
}
|
|
@@ -656,7 +696,9 @@ export class K2DB {
|
|
|
656
696
|
const { uuidUnique = false, uuidPartialUnique = true, ownerIndex = true, deletedIndex = true, } = opts;
|
|
657
697
|
const collection = await this.getCollection(collectionName);
|
|
658
698
|
if (uuidPartialUnique) {
|
|
659
|
-
|
|
699
|
+
// Use a compound unique index to ensure at most one non-deleted document per _uuid
|
|
700
|
+
// without relying on partialFilterExpression (which may be limited in some environments).
|
|
701
|
+
await collection.createIndex({ _uuid: 1, _deleted: 1 }, { unique: true });
|
|
660
702
|
}
|
|
661
703
|
else if (uuidUnique) {
|
|
662
704
|
await collection.createIndex({ _uuid: 1 }, { unique: true });
|
package/dist/package.json
CHANGED