@lossless.org/client 0.1.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/.smartconfig.json +37 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/classes.losslessorgclient.d.ts +32 -0
- package/dist_ts/classes.losslessorgclient.js +103 -0
- package/dist_ts/core/classes.error.d.ts +16 -0
- package/dist_ts/core/classes.error.js +29 -0
- package/dist_ts/core/classes.operation.d.ts +17 -0
- package/dist_ts/core/classes.operation.js +70 -0
- package/dist_ts/core/interfaces.d.ts +18 -0
- package/dist_ts/core/interfaces.js +2 -0
- package/dist_ts/index.d.ts +4 -0
- package/dist_ts/index.js +3 -0
- package/dist_ts/nosqldb/classes.atomicdelete.d.ts +26 -0
- package/dist_ts/nosqldb/classes.atomicdelete.js +44 -0
- package/dist_ts/nosqldb/classes.atomicfindoneandupdate.d.ts +27 -0
- package/dist_ts/nosqldb/classes.atomicfindoneandupdate.js +86 -0
- package/dist_ts/nosqldb/classes.atomicupdate.d.ts +26 -0
- package/dist_ts/nosqldb/classes.atomicupdate.js +55 -0
- package/dist_ts/nosqldb/classes.bootstraprecord.d.ts +14 -0
- package/dist_ts/nosqldb/classes.bootstraprecord.js +80 -0
- package/dist_ts/nosqldb/classes.bsonassertion.d.ts +2 -0
- package/dist_ts/nosqldb/classes.bsonassertion.js +29 -0
- package/dist_ts/nosqldb/classes.bsonobjectid.d.ts +2 -0
- package/dist_ts/nosqldb/classes.bsonobjectid.js +50 -0
- package/dist_ts/nosqldb/classes.bsonsnapshot.d.ts +3 -0
- package/dist_ts/nosqldb/classes.bsonsnapshot.js +126 -0
- package/dist_ts/nosqldb/classes.cached-document.d.ts +27 -0
- package/dist_ts/nosqldb/classes.cached-document.js +112 -0
- package/dist_ts/nosqldb/classes.collection.d.ts +302 -0
- package/dist_ts/nosqldb/classes.collection.js +1568 -0
- package/dist_ts/nosqldb/classes.collectionfactory.d.ts +30 -0
- package/dist_ts/nosqldb/classes.collectionfactory.js +65 -0
- package/dist_ts/nosqldb/classes.collectionlifecycle.d.ts +4 -0
- package/dist_ts/nosqldb/classes.collectionlifecycle.js +15 -0
- package/dist_ts/nosqldb/classes.collectionpreparation.d.ts +34 -0
- package/dist_ts/nosqldb/classes.collectionpreparation.js +134 -0
- package/dist_ts/nosqldb/classes.collectiontopology.d.ts +47 -0
- package/dist_ts/nosqldb/classes.collectiontopology.js +388 -0
- package/dist_ts/nosqldb/classes.connection.d.ts +18 -0
- package/dist_ts/nosqldb/classes.connection.js +23 -0
- package/dist_ts/nosqldb/classes.convenience.d.ts +1 -0
- package/dist_ts/nosqldb/classes.convenience.js +5 -0
- package/dist_ts/nosqldb/classes.cursor.d.ts +15 -0
- package/dist_ts/nosqldb/classes.cursor.js +82 -0
- package/dist_ts/nosqldb/classes.cursoroperation.d.ts +7 -0
- package/dist_ts/nosqldb/classes.cursoroperation.js +36 -0
- package/dist_ts/nosqldb/classes.db.d.ts +98 -0
- package/dist_ts/nosqldb/classes.db.js +434 -0
- package/dist_ts/nosqldb/classes.distributedcoordinator.d.ts +52 -0
- package/dist_ts/nosqldb/classes.distributedcoordinator.js +314 -0
- package/dist_ts/nosqldb/classes.doc.d.ts +722 -0
- package/dist_ts/nosqldb/classes.doc.js +2976 -0
- package/dist_ts/nosqldb/classes.easystore.d.ts +42 -0
- package/dist_ts/nosqldb/classes.easystore.js +199 -0
- package/dist_ts/nosqldb/classes.exactpersistence.d.ts +141 -0
- package/dist_ts/nosqldb/classes.exactpersistence.js +1110 -0
- package/dist_ts/nosqldb/classes.lucene.adapter.d.ts +173 -0
- package/dist_ts/nosqldb/classes.lucene.adapter.js +623 -0
- package/dist_ts/nosqldb/classes.mongoadministration.d.ts +73 -0
- package/dist_ts/nosqldb/classes.mongoadministration.js +497 -0
- package/dist_ts/nosqldb/classes.namespaceinspection.d.ts +42 -0
- package/dist_ts/nosqldb/classes.namespaceinspection.js +138 -0
- package/dist_ts/nosqldb/classes.operationbudget.d.ts +22 -0
- package/dist_ts/nosqldb/classes.operationbudget.js +65 -0
- package/dist_ts/nosqldb/classes.ordinarypersistence.d.ts +18 -0
- package/dist_ts/nosqldb/classes.ordinarypersistence.js +71 -0
- package/dist_ts/nosqldb/classes.persistence.d.ts +14 -0
- package/dist_ts/nosqldb/classes.persistence.js +34 -0
- package/dist_ts/nosqldb/classes.session.d.ts +28 -0
- package/dist_ts/nosqldb/classes.session.js +246 -0
- package/dist_ts/nosqldb/classes.storedinspection.d.ts +44 -0
- package/dist_ts/nosqldb/classes.storedinspection.js +100 -0
- package/dist_ts/nosqldb/classes.testdatabase.d.ts +56 -0
- package/dist_ts/nosqldb/classes.testdatabase.js +250 -0
- package/dist_ts/nosqldb/classes.watcher.d.ts +37 -0
- package/dist_ts/nosqldb/classes.watcher.js +98 -0
- package/dist_ts/nosqldb/index.d.ts +27 -0
- package/dist_ts/nosqldb/index.js +18 -0
- package/dist_ts/nosqldb/logging.d.ts +2 -0
- package/dist_ts/nosqldb/logging.js +3 -0
- package/dist_ts/nosqldb/plugins.d.ts +17 -0
- package/dist_ts/nosqldb/plugins.js +20 -0
- package/dist_ts/nosqldb/shim.d.ts +1 -0
- package/dist_ts/nosqldb/shim.js +8 -0
- package/dist_ts/nosqldb/testsupport.d.ts +3 -0
- package/dist_ts/nosqldb/testsupport.js +3 -0
- package/dist_ts/objectstorage/classes.bucket.d.ts +227 -0
- package/dist_ts/objectstorage/classes.bucket.js +939 -0
- package/dist_ts/objectstorage/classes.connection.d.ts +21 -0
- package/dist_ts/objectstorage/classes.connection.js +27 -0
- package/dist_ts/objectstorage/classes.directory.d.ts +124 -0
- package/dist_ts/objectstorage/classes.directory.js +335 -0
- package/dist_ts/objectstorage/classes.exactpathpurgeerror.d.ts +5 -0
- package/dist_ts/objectstorage/classes.exactpathpurgeerror.js +18 -0
- package/dist_ts/objectstorage/classes.exactuploaderror.d.ts +5 -0
- package/dist_ts/objectstorage/classes.exactuploaderror.js +19 -0
- package/dist_ts/objectstorage/classes.file.d.ts +91 -0
- package/dist_ts/objectstorage/classes.file.js +255 -0
- package/dist_ts/objectstorage/classes.listcursor.d.ts +41 -0
- package/dist_ts/objectstorage/classes.listcursor.js +67 -0
- package/dist_ts/objectstorage/classes.metadata.d.ts +57 -0
- package/dist_ts/objectstorage/classes.metadata.js +113 -0
- package/dist_ts/objectstorage/classes.smartbucket.d.ts +57 -0
- package/dist_ts/objectstorage/classes.smartbucket.js +357 -0
- package/dist_ts/objectstorage/classes.trash.d.ts +11 -0
- package/dist_ts/objectstorage/classes.trash.js +22 -0
- package/dist_ts/objectstorage/classes.watcher.d.ts +79 -0
- package/dist_ts/objectstorage/classes.watcher.js +249 -0
- package/dist_ts/objectstorage/helpers.d.ts +25 -0
- package/dist_ts/objectstorage/helpers.js +215 -0
- package/dist_ts/objectstorage/index.d.ts +13 -0
- package/dist_ts/objectstorage/index.js +13 -0
- package/dist_ts/objectstorage/interfaces.d.ts +276 -0
- package/dist_ts/objectstorage/interfaces.js +2 -0
- package/dist_ts/objectstorage/internal.exactpathpurge.operations.d.ts +11 -0
- package/dist_ts/objectstorage/internal.exactpathpurge.operations.js +1069 -0
- package/dist_ts/objectstorage/internal.exactupload.capability.d.ts +40 -0
- package/dist_ts/objectstorage/internal.exactupload.capability.js +382 -0
- package/dist_ts/objectstorage/internal.exactupload.operations.d.ts +11 -0
- package/dist_ts/objectstorage/internal.exactupload.operations.js +1104 -0
- package/dist_ts/objectstorage/internal.multipart.planner.d.ts +8 -0
- package/dist_ts/objectstorage/internal.multipart.planner.js +63 -0
- package/dist_ts/objectstorage/internal.multipart.stream.d.ts +17 -0
- package/dist_ts/objectstorage/internal.multipart.stream.js +440 -0
- package/dist_ts/objectstorage/internal.multipart.types.d.ts +82 -0
- package/dist_ts/objectstorage/internal.multipart.types.js +2 -0
- package/dist_ts/objectstorage/plugins.d.ts +17 -0
- package/dist_ts/objectstorage/plugins.js +23 -0
- package/dist_ts/plugins.d.ts +4 -0
- package/dist_ts/plugins.js +5 -0
- package/dist_ts/sqldb/classes.clickhouseconnection.d.ts +39 -0
- package/dist_ts/sqldb/classes.clickhouseconnection.js +225 -0
- package/dist_ts/sqldb/classes.sqlconnection.d.ts +50 -0
- package/dist_ts/sqldb/classes.sqlconnection.js +376 -0
- package/dist_ts/sqldb/classes.sqltable.d.ts +29 -0
- package/dist_ts/sqldb/classes.sqltable.js +70 -0
- package/dist_ts/sqldb/clickhouse/classes.metricwriter.d.ts +27 -0
- package/dist_ts/sqldb/clickhouse/classes.metricwriter.js +89 -0
- package/dist_ts/sqldb/clickhouse/index.d.ts +9 -0
- package/dist_ts/sqldb/clickhouse/index.js +13 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.clickhousetable.d.ts +88 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.clickhousetable.js +304 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.httpclient.d.ts +28 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.httpclient.js +46 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.querybuilder.d.ts +43 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.querybuilder.js +155 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.resultset.d.ts +13 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.resultset.js +36 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.smartclickhouse.d.ts +49 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.smartclickhouse.js +106 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.timedatatable.d.ts +51 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.timedatatable.js +96 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.plugins.d.ts +5 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.plugins.js +6 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.types.d.ts +53 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.types.js +41 -0
- package/dist_ts/sqldb/index.d.ts +6 -0
- package/dist_ts/sqldb/index.js +6 -0
- package/dist_ts/sqldb/interfaces.d.ts +53 -0
- package/dist_ts/sqldb/interfaces.js +19 -0
- package/dist_ts/sqldb/internal.sqlpool.d.ts +51 -0
- package/dist_ts/sqldb/internal.sqlpool.js +214 -0
- package/dist_ts/sqldb/plugins.clickhouse.d.ts +4 -0
- package/dist_ts/sqldb/plugins.clickhouse.js +5 -0
- package/dist_ts/sqldb/plugins.mariadb.d.ts +4 -0
- package/dist_ts/sqldb/plugins.mariadb.js +5 -0
- package/docs/source/smartbucket/license.md +19 -0
- package/docs/source/smartclickhouse/license.md +19 -0
- package/license.md +21 -0
- package/package.json +101 -0
- package/readme.md +157 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/classes.losslessorgclient.ts +104 -0
- package/ts/core/classes.error.ts +31 -0
- package/ts/core/classes.operation.ts +60 -0
- package/ts/core/interfaces.ts +24 -0
- package/ts/index.ts +4 -0
- package/ts/nosqldb/classes.atomicdelete.ts +81 -0
- package/ts/nosqldb/classes.atomicfindoneandupdate.ts +152 -0
- package/ts/nosqldb/classes.atomicupdate.ts +99 -0
- package/ts/nosqldb/classes.bootstraprecord.ts +107 -0
- package/ts/nosqldb/classes.bsonassertion.ts +25 -0
- package/ts/nosqldb/classes.bsonobjectid.ts +45 -0
- package/ts/nosqldb/classes.bsonsnapshot.ts +105 -0
- package/ts/nosqldb/classes.cached-document.ts +67 -0
- package/ts/nosqldb/classes.collection.ts +2399 -0
- package/ts/nosqldb/classes.collectionfactory.ts +87 -0
- package/ts/nosqldb/classes.collectionlifecycle.ts +24 -0
- package/ts/nosqldb/classes.collectionpreparation.ts +164 -0
- package/ts/nosqldb/classes.collectiontopology.ts +645 -0
- package/ts/nosqldb/classes.connection.ts +31 -0
- package/ts/nosqldb/classes.convenience.ts +5 -0
- package/ts/nosqldb/classes.cursor.ts +88 -0
- package/ts/nosqldb/classes.cursoroperation.ts +38 -0
- package/ts/nosqldb/classes.db.ts +637 -0
- package/ts/nosqldb/classes.distributedcoordinator.ts +305 -0
- package/ts/nosqldb/classes.doc.ts +4928 -0
- package/ts/nosqldb/classes.easystore.ts +154 -0
- package/ts/nosqldb/classes.exactpersistence.ts +1974 -0
- package/ts/nosqldb/classes.lucene.adapter.ts +780 -0
- package/ts/nosqldb/classes.mongoadministration.ts +867 -0
- package/ts/nosqldb/classes.namespaceinspection.ts +199 -0
- package/ts/nosqldb/classes.operationbudget.ts +75 -0
- package/ts/nosqldb/classes.ordinarypersistence.ts +84 -0
- package/ts/nosqldb/classes.persistence.ts +62 -0
- package/ts/nosqldb/classes.session.ts +389 -0
- package/ts/nosqldb/classes.storedinspection.ts +151 -0
- package/ts/nosqldb/classes.testdatabase.ts +272 -0
- package/ts/nosqldb/classes.watcher.ts +96 -0
- package/ts/nosqldb/index.ts +51 -0
- package/ts/nosqldb/logging.ts +3 -0
- package/ts/nosqldb/plugins.ts +37 -0
- package/ts/nosqldb/shim.ts +6 -0
- package/ts/nosqldb/testsupport.ts +13 -0
- package/ts/objectstorage/classes.bucket.ts +1114 -0
- package/ts/objectstorage/classes.connection.ts +36 -0
- package/ts/objectstorage/classes.directory.ts +425 -0
- package/ts/objectstorage/classes.exactpathpurgeerror.ts +24 -0
- package/ts/objectstorage/classes.exactuploaderror.ts +25 -0
- package/ts/objectstorage/classes.file.ts +303 -0
- package/ts/objectstorage/classes.listcursor.ts +89 -0
- package/ts/objectstorage/classes.metadata.ts +134 -0
- package/ts/objectstorage/classes.smartbucket.ts +445 -0
- package/ts/objectstorage/classes.trash.ts +30 -0
- package/ts/objectstorage/classes.watcher.ts +289 -0
- package/ts/objectstorage/helpers.ts +254 -0
- package/ts/objectstorage/index.ts +13 -0
- package/ts/objectstorage/interfaces.ts +389 -0
- package/ts/objectstorage/internal.exactpathpurge.operations.ts +1936 -0
- package/ts/objectstorage/internal.exactupload.capability.ts +580 -0
- package/ts/objectstorage/internal.exactupload.operations.ts +1715 -0
- package/ts/objectstorage/internal.multipart.planner.ts +90 -0
- package/ts/objectstorage/internal.multipart.stream.ts +606 -0
- package/ts/objectstorage/internal.multipart.types.ts +106 -0
- package/ts/objectstorage/plugins.ts +35 -0
- package/ts/plugins.ts +4 -0
- package/ts/sqldb/classes.clickhouseconnection.ts +189 -0
- package/ts/sqldb/classes.sqlconnection.ts +350 -0
- package/ts/sqldb/classes.sqltable.ts +70 -0
- package/ts/sqldb/clickhouse/classes.metricwriter.ts +72 -0
- package/ts/sqldb/clickhouse/index.ts +16 -0
- package/ts/sqldb/clickhouse/smartclickhouse.classes.clickhousetable.ts +372 -0
- package/ts/sqldb/clickhouse/smartclickhouse.classes.httpclient.ts +52 -0
- package/ts/sqldb/clickhouse/smartclickhouse.classes.querybuilder.ts +120 -0
- package/ts/sqldb/clickhouse/smartclickhouse.classes.resultset.ts +44 -0
- package/ts/sqldb/clickhouse/smartclickhouse.classes.smartclickhouse.ts +123 -0
- package/ts/sqldb/clickhouse/smartclickhouse.classes.timedatatable.ts +114 -0
- package/ts/sqldb/clickhouse/smartclickhouse.plugins.ts +5 -0
- package/ts/sqldb/clickhouse/smartclickhouse.types.ts +134 -0
- package/ts/sqldb/index.ts +6 -0
- package/ts/sqldb/interfaces.ts +61 -0
- package/ts/sqldb/internal.sqlpool.ts +179 -0
- package/ts/sqldb/plugins.clickhouse.ts +4 -0
- package/ts/sqldb/plugins.mariadb.ts +4 -0
|
@@ -0,0 +1,2976 @@
|
|
|
1
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
2
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
3
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
4
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
5
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
6
|
+
var _, done = false;
|
|
7
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
8
|
+
var context = {};
|
|
9
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
10
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
11
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
12
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
13
|
+
if (kind === "accessor") {
|
|
14
|
+
if (result === void 0) continue;
|
|
15
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
16
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
17
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
18
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
19
|
+
}
|
|
20
|
+
else if (_ = accept(result)) {
|
|
21
|
+
if (kind === "field") initializers.unshift(_);
|
|
22
|
+
else descriptor[key] = _;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
26
|
+
done = true;
|
|
27
|
+
};
|
|
28
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
29
|
+
var useValue = arguments.length > 2;
|
|
30
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
31
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
32
|
+
}
|
|
33
|
+
return useValue ? value : void 0;
|
|
34
|
+
};
|
|
35
|
+
import * as plugins from './plugins.js';
|
|
36
|
+
import { SmartdataDb } from './classes.db.js';
|
|
37
|
+
import { logger } from './logging.js';
|
|
38
|
+
import { SmartdataDbCursor } from './classes.cursor.js';
|
|
39
|
+
import { runCursorOperation } from './classes.cursoroperation.js';
|
|
40
|
+
import { insertBootstrapRecord, } from './classes.bootstraprecord.js';
|
|
41
|
+
import { validateCollectionPreparationOptions, } from './classes.collectionpreparation.js';
|
|
42
|
+
import { getOrdinaryPersistencePolicy, validateOrdinaryStoredDocument } from './classes.ordinarypersistence.js';
|
|
43
|
+
import { inspectStoredDocuments, inspectStoredDocumentEvidence, } from './classes.storedinspection.js';
|
|
44
|
+
import { SmartdataCollection, } from './classes.collection.js';
|
|
45
|
+
import { SmartdataDbWatcher } from './classes.watcher.js';
|
|
46
|
+
import { SmartdataLuceneAdapter } from './classes.lucene.adapter.js';
|
|
47
|
+
import { executeAtomicDelete, executeAtomicDeleteMany } from './classes.atomicdelete.js';
|
|
48
|
+
import { executeAtomicFindOneAndUpdate } from './classes.atomicfindoneandupdate.js';
|
|
49
|
+
import { executeAtomicUpdate, executeAtomicUpdateMany } from './classes.atomicupdate.js';
|
|
50
|
+
import { SmartdataPersistenceError, } from './classes.persistence.js';
|
|
51
|
+
import { isOrdinarySessionInTransaction, runWithOrdinarySmartdataSession, } from './classes.session.js';
|
|
52
|
+
import { getExpectedCollectionTopologyForModel, inspectCollectionTopologyForModel, } from './classes.collectiontopology.js';
|
|
53
|
+
const exactPersistencePolicySymbol = Symbol.for('@push.rocks/smartdata.exactPersistencePolicy');
|
|
54
|
+
/**
|
|
55
|
+
* Detects plain object literals only. Anything carrying a custom prototype
|
|
56
|
+
* (Date, ObjectId, Binary, Buffer, RegExp, Decimal128, class instances, ...) is
|
|
57
|
+
* deliberately excluded so that BSON types are never rebuilt or otherwise
|
|
58
|
+
* altered while stripping undefined values.
|
|
59
|
+
*/
|
|
60
|
+
const isPlainObject = (valueArg) => {
|
|
61
|
+
if (typeof valueArg !== 'object' || valueArg === null) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
const prototype = Object.getPrototypeOf(valueArg);
|
|
65
|
+
return prototype === Object.prototype || prototype === null;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Recursively drops object properties whose value is `undefined` so MongoDB
|
|
69
|
+
* stores them as absent rather than as BSON null.
|
|
70
|
+
*
|
|
71
|
+
* Notes on the deliberate boundaries of this traversal:
|
|
72
|
+
* - Array positions are preserved: an `undefined` element stays in place and is
|
|
73
|
+
* serialized as null, exactly as `JSON.stringify` does. Removing it would
|
|
74
|
+
* shift every following index.
|
|
75
|
+
* - Only plain objects are recursed into, so BSON types keep their identity.
|
|
76
|
+
* - On a circular structure the offending value is returned untouched, letting
|
|
77
|
+
* BSON raise its usual "Cannot convert circular structure to BSON" error
|
|
78
|
+
* instead of overflowing the stack here.
|
|
79
|
+
*/
|
|
80
|
+
const stripUndefinedValues = (valueArg, seenArg) => {
|
|
81
|
+
if (typeof valueArg !== 'object' || valueArg === null) {
|
|
82
|
+
return valueArg;
|
|
83
|
+
}
|
|
84
|
+
const isArray = Array.isArray(valueArg);
|
|
85
|
+
if (!isArray && !isPlainObject(valueArg)) {
|
|
86
|
+
return valueArg;
|
|
87
|
+
}
|
|
88
|
+
const seen = seenArg ?? new WeakSet();
|
|
89
|
+
if (seen.has(valueArg)) {
|
|
90
|
+
return valueArg;
|
|
91
|
+
}
|
|
92
|
+
seen.add(valueArg);
|
|
93
|
+
if (isArray) {
|
|
94
|
+
return valueArg.map((entryArg) => entryArg === undefined ? null : stripUndefinedValues(entryArg, seen));
|
|
95
|
+
}
|
|
96
|
+
const strippedObject = {};
|
|
97
|
+
for (const keyArg of Object.keys(valueArg)) {
|
|
98
|
+
const entry = valueArg[keyArg];
|
|
99
|
+
if (entry === undefined) {
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
strippedObject[keyArg] = stripUndefinedValues(entry, seen);
|
|
103
|
+
}
|
|
104
|
+
return strippedObject;
|
|
105
|
+
};
|
|
106
|
+
export function globalSvDb() {
|
|
107
|
+
return (value, context) => {
|
|
108
|
+
if (context.kind !== 'field') {
|
|
109
|
+
throw new Error('globalSvDb can only decorate fields');
|
|
110
|
+
}
|
|
111
|
+
// Store metadata at class level using Symbol.metadata
|
|
112
|
+
const metadata = context.metadata;
|
|
113
|
+
if (!Object.prototype.hasOwnProperty.call(metadata, 'globalSaveableProperties')) {
|
|
114
|
+
metadata.globalSaveableProperties = [
|
|
115
|
+
...(metadata.globalSaveableProperties || []),
|
|
116
|
+
];
|
|
117
|
+
}
|
|
118
|
+
const propName = String(context.name);
|
|
119
|
+
if (!metadata.globalSaveableProperties.includes(propName)) {
|
|
120
|
+
metadata.globalSaveableProperties.push(propName);
|
|
121
|
+
}
|
|
122
|
+
// Use addInitializer to ensure prototype arrays are set up once
|
|
123
|
+
context.addInitializer(function () {
|
|
124
|
+
const proto = this.constructor.prototype;
|
|
125
|
+
const metadata = this.constructor[Symbol.metadata];
|
|
126
|
+
if (metadata && metadata.globalSaveableProperties && !proto.globalSaveableProperties) {
|
|
127
|
+
// Initialize prototype array from metadata (runs once per class)
|
|
128
|
+
proto.globalSaveableProperties = [...metadata.globalSaveableProperties];
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* saveable - saveable decorator to be used on class properties
|
|
135
|
+
*/
|
|
136
|
+
export function svDb(options) {
|
|
137
|
+
if (options?.numeric !== undefined && typeof options.numeric !== 'boolean') {
|
|
138
|
+
throw new SmartdataPersistenceError('invalid_configuration', 'svDb numeric must be a boolean.');
|
|
139
|
+
}
|
|
140
|
+
const storedOptions = options
|
|
141
|
+
? {
|
|
142
|
+
...options,
|
|
143
|
+
...(options.atomicPaths !== undefined
|
|
144
|
+
? {
|
|
145
|
+
atomicPaths: Array.isArray(options.atomicPaths)
|
|
146
|
+
? [...options.atomicPaths]
|
|
147
|
+
: options.atomicPaths,
|
|
148
|
+
}
|
|
149
|
+
: {}),
|
|
150
|
+
}
|
|
151
|
+
: undefined;
|
|
152
|
+
return (value, context) => {
|
|
153
|
+
if (context.kind !== 'field') {
|
|
154
|
+
throw new Error('svDb can only decorate fields');
|
|
155
|
+
}
|
|
156
|
+
const propName = String(context.name);
|
|
157
|
+
// Store metadata at class level using Symbol.metadata
|
|
158
|
+
const metadata = context.metadata;
|
|
159
|
+
if (!Object.prototype.hasOwnProperty.call(metadata, 'saveableProperties')) {
|
|
160
|
+
metadata.saveableProperties = [...(metadata.saveableProperties || [])];
|
|
161
|
+
}
|
|
162
|
+
if (!metadata.saveableProperties.includes(propName)) {
|
|
163
|
+
metadata.saveableProperties.push(propName);
|
|
164
|
+
}
|
|
165
|
+
// Store options in metadata
|
|
166
|
+
if (storedOptions) {
|
|
167
|
+
if (!Object.prototype.hasOwnProperty.call(metadata, '_svDbOptions')) {
|
|
168
|
+
metadata._svDbOptions = { ...(metadata._svDbOptions || {}) };
|
|
169
|
+
}
|
|
170
|
+
metadata._svDbOptions[propName] = storedOptions;
|
|
171
|
+
}
|
|
172
|
+
// Use addInitializer to ensure prototype arrays are set up once
|
|
173
|
+
context.addInitializer(function () {
|
|
174
|
+
const proto = this.constructor.prototype;
|
|
175
|
+
const ctor = this.constructor;
|
|
176
|
+
const metadata = ctor[Symbol.metadata];
|
|
177
|
+
if (metadata && metadata.saveableProperties && !proto.saveableProperties) {
|
|
178
|
+
// Initialize prototype array from metadata (runs once per class)
|
|
179
|
+
proto.saveableProperties = [...metadata.saveableProperties];
|
|
180
|
+
}
|
|
181
|
+
// Initialize svDbOptions from metadata
|
|
182
|
+
if (metadata && metadata._svDbOptions && !ctor._svDbOptions) {
|
|
183
|
+
ctor._svDbOptions = { ...metadata._svDbOptions };
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* searchable - marks a property as searchable with Lucene query syntax
|
|
190
|
+
*/
|
|
191
|
+
export function searchable() {
|
|
192
|
+
return (value, context) => {
|
|
193
|
+
if (context.kind !== 'field') {
|
|
194
|
+
throw new Error('searchable can only decorate fields');
|
|
195
|
+
}
|
|
196
|
+
const propName = String(context.name);
|
|
197
|
+
// Store metadata at class level
|
|
198
|
+
const metadata = context.metadata;
|
|
199
|
+
if (!Object.prototype.hasOwnProperty.call(metadata, 'searchableFields')) {
|
|
200
|
+
metadata.searchableFields = [...(metadata.searchableFields || [])];
|
|
201
|
+
}
|
|
202
|
+
if (!metadata.searchableFields.includes(propName)) {
|
|
203
|
+
metadata.searchableFields.push(propName);
|
|
204
|
+
}
|
|
205
|
+
// Use addInitializer to set up constructor property once
|
|
206
|
+
context.addInitializer(function () {
|
|
207
|
+
const ctor = this.constructor;
|
|
208
|
+
const metadata = ctor[Symbol.metadata];
|
|
209
|
+
if (metadata && metadata.searchableFields && !Array.isArray(ctor.searchableFields)) {
|
|
210
|
+
// Initialize from metadata (runs once per class)
|
|
211
|
+
ctor.searchableFields = [...metadata.searchableFields];
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
// Escape user input for safe use in MongoDB regular expressions
|
|
217
|
+
function escapeForRegex(input) {
|
|
218
|
+
return input.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* unique index - decorator to mark a unique index
|
|
222
|
+
*/
|
|
223
|
+
export function unI(optionsArg = {}) {
|
|
224
|
+
if (typeof optionsArg !== 'object'
|
|
225
|
+
|| optionsArg === null
|
|
226
|
+
|| Array.isArray(optionsArg)
|
|
227
|
+
|| Object.keys(optionsArg).some((keyArg) => keyArg !== 'valueType')) {
|
|
228
|
+
throw new SmartdataPersistenceError('invalid_configuration', 'unI options must be an object containing only valueType.');
|
|
229
|
+
}
|
|
230
|
+
const valueType = optionsArg.valueType ?? 'string';
|
|
231
|
+
if (valueType !== 'string' && valueType !== 'positiveSafeInteger') {
|
|
232
|
+
throw new SmartdataPersistenceError('invalid_configuration', 'unI valueType must be "string" or "positiveSafeInteger".');
|
|
233
|
+
}
|
|
234
|
+
return (value, context) => {
|
|
235
|
+
if (context.kind !== 'field') {
|
|
236
|
+
throw new Error('unI can only decorate fields');
|
|
237
|
+
}
|
|
238
|
+
const propName = String(context.name);
|
|
239
|
+
// Store metadata at class level
|
|
240
|
+
const metadata = context.metadata;
|
|
241
|
+
if (!Object.prototype.hasOwnProperty.call(metadata, 'uniqueIndexes')) {
|
|
242
|
+
metadata.uniqueIndexes = [...(metadata.uniqueIndexes || [])];
|
|
243
|
+
}
|
|
244
|
+
if (!metadata.uniqueIndexes.includes(propName)) {
|
|
245
|
+
metadata.uniqueIndexes.push(propName);
|
|
246
|
+
}
|
|
247
|
+
if (!Object.prototype.hasOwnProperty.call(metadata, 'identityValueTypes')) {
|
|
248
|
+
metadata.identityValueTypes = { ...(metadata.identityValueTypes || {}) };
|
|
249
|
+
}
|
|
250
|
+
const existingValueType = metadata.identityValueTypes[propName];
|
|
251
|
+
if (existingValueType && existingValueType !== valueType) {
|
|
252
|
+
throw new SmartdataPersistenceError('invalid_configuration', `Identity field "${propName}" has divergent valueType declarations.`);
|
|
253
|
+
}
|
|
254
|
+
metadata.identityValueTypes[propName] = valueType;
|
|
255
|
+
// Also mark as saveable
|
|
256
|
+
if (!Object.prototype.hasOwnProperty.call(metadata, 'saveableProperties')) {
|
|
257
|
+
metadata.saveableProperties = [...(metadata.saveableProperties || [])];
|
|
258
|
+
}
|
|
259
|
+
if (!metadata.saveableProperties.includes(propName)) {
|
|
260
|
+
metadata.saveableProperties.push(propName);
|
|
261
|
+
}
|
|
262
|
+
// Use addInitializer to ensure prototype arrays are set up once
|
|
263
|
+
context.addInitializer(function () {
|
|
264
|
+
const proto = this.constructor.prototype;
|
|
265
|
+
const metadata = this.constructor[Symbol.metadata];
|
|
266
|
+
if (metadata && metadata.uniqueIndexes && !proto.uniqueIndexes) {
|
|
267
|
+
proto.uniqueIndexes = [...metadata.uniqueIndexes];
|
|
268
|
+
}
|
|
269
|
+
if (metadata
|
|
270
|
+
&& metadata.identityValueTypes
|
|
271
|
+
&& !Object.prototype.hasOwnProperty.call(proto, 'identityValueTypes')) {
|
|
272
|
+
proto.identityValueTypes = { ...metadata.identityValueTypes };
|
|
273
|
+
}
|
|
274
|
+
if (metadata && metadata.saveableProperties && !proto.saveableProperties) {
|
|
275
|
+
proto.saveableProperties = [...metadata.saveableProperties];
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* index - decorator to mark a field for regular indexing
|
|
282
|
+
*/
|
|
283
|
+
export function index(options) {
|
|
284
|
+
return (value, context) => {
|
|
285
|
+
if (context.kind !== 'field') {
|
|
286
|
+
throw new Error('index can only decorate fields');
|
|
287
|
+
}
|
|
288
|
+
const propName = String(context.name);
|
|
289
|
+
// Store metadata at class level
|
|
290
|
+
const metadata = context.metadata;
|
|
291
|
+
if (!Object.prototype.hasOwnProperty.call(metadata, 'regularIndexes')) {
|
|
292
|
+
metadata.regularIndexes = [...(metadata.regularIndexes || [])];
|
|
293
|
+
}
|
|
294
|
+
metadata.regularIndexes.push({
|
|
295
|
+
field: propName,
|
|
296
|
+
options: { ...(options || {}) }
|
|
297
|
+
});
|
|
298
|
+
// Also mark as saveable
|
|
299
|
+
if (!Object.prototype.hasOwnProperty.call(metadata, 'saveableProperties')) {
|
|
300
|
+
metadata.saveableProperties = [...(metadata.saveableProperties || [])];
|
|
301
|
+
}
|
|
302
|
+
if (!metadata.saveableProperties.includes(propName)) {
|
|
303
|
+
metadata.saveableProperties.push(propName);
|
|
304
|
+
}
|
|
305
|
+
// Use addInitializer to ensure prototype arrays are set up once
|
|
306
|
+
context.addInitializer(function () {
|
|
307
|
+
const proto = this.constructor.prototype;
|
|
308
|
+
const metadata = this.constructor[Symbol.metadata];
|
|
309
|
+
if (metadata && metadata.regularIndexes && !proto.regularIndexes) {
|
|
310
|
+
proto.regularIndexes = [...metadata.regularIndexes];
|
|
311
|
+
}
|
|
312
|
+
if (metadata && metadata.saveableProperties && !proto.saveableProperties) {
|
|
313
|
+
proto.saveableProperties = [...metadata.saveableProperties];
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
const normalizeAtomicFindOneAndUpdateOptions = (optionsArg) => {
|
|
319
|
+
if (typeof optionsArg !== 'object'
|
|
320
|
+
|| optionsArg === null
|
|
321
|
+
|| plugins.nodeUtil.types.isProxy(optionsArg)
|
|
322
|
+
|| !isPlainObject(optionsArg)) {
|
|
323
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Atomic find-one-and-update options must be an inert plain object.');
|
|
324
|
+
}
|
|
325
|
+
const allowedKeys = new Set(['returnDocument', 'upsert', 'sort', 'session']);
|
|
326
|
+
const keys = Reflect.ownKeys(optionsArg);
|
|
327
|
+
for (const key of keys) {
|
|
328
|
+
if (typeof key !== 'string' || !allowedKeys.has(key)) {
|
|
329
|
+
throw new SmartdataPersistenceError('invalid_argument', `Atomic find-one-and-update received unsupported option "${String(key)}".`);
|
|
330
|
+
}
|
|
331
|
+
const descriptor = Object.getOwnPropertyDescriptor(optionsArg, key);
|
|
332
|
+
if (!descriptor || !('value' in descriptor) || descriptor.enumerable !== true) {
|
|
333
|
+
throw new SmartdataPersistenceError('invalid_argument', `Atomic find-one-and-update option "${key}" must be an inert enumerable data property.`);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
const returnDocumentDescriptor = Object.getOwnPropertyDescriptor(optionsArg, 'returnDocument');
|
|
337
|
+
if (!returnDocumentDescriptor
|
|
338
|
+
|| !('value' in returnDocumentDescriptor)
|
|
339
|
+
|| (returnDocumentDescriptor.value !== 'before'
|
|
340
|
+
&& returnDocumentDescriptor.value !== 'after')) {
|
|
341
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Atomic find-one-and-update requires returnDocument to be "before" or "after".');
|
|
342
|
+
}
|
|
343
|
+
const upsertDescriptor = Object.getOwnPropertyDescriptor(optionsArg, 'upsert');
|
|
344
|
+
if (upsertDescriptor && upsertDescriptor.value !== undefined
|
|
345
|
+
&& typeof upsertDescriptor.value !== 'boolean') {
|
|
346
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Atomic find-one-and-update upsert must be a boolean.');
|
|
347
|
+
}
|
|
348
|
+
const sortDescriptor = Object.getOwnPropertyDescriptor(optionsArg, 'sort');
|
|
349
|
+
const sessionDescriptor = Object.getOwnPropertyDescriptor(optionsArg, 'session');
|
|
350
|
+
return {
|
|
351
|
+
returnDocument: returnDocumentDescriptor.value,
|
|
352
|
+
upsert: upsertDescriptor?.value === true,
|
|
353
|
+
...(sortDescriptor?.value !== undefined
|
|
354
|
+
? { sort: sortDescriptor.value }
|
|
355
|
+
: {}),
|
|
356
|
+
...(sessionDescriptor?.value !== undefined
|
|
357
|
+
? { session: sessionDescriptor.value }
|
|
358
|
+
: {}),
|
|
359
|
+
};
|
|
360
|
+
};
|
|
361
|
+
const normalizeAtomicExpressionUpdateOptions = (optionsArg) => {
|
|
362
|
+
if (optionsArg === undefined) {
|
|
363
|
+
return undefined;
|
|
364
|
+
}
|
|
365
|
+
if (typeof optionsArg !== 'object'
|
|
366
|
+
|| optionsArg === null
|
|
367
|
+
|| plugins.nodeUtil.types.isProxy(optionsArg)
|
|
368
|
+
|| Object.getPrototypeOf(optionsArg) !== Object.prototype) {
|
|
369
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Atomic update options used with $expr must be an inert ordinary object.');
|
|
370
|
+
}
|
|
371
|
+
const allowedKeys = new Set(['upsert', 'session']);
|
|
372
|
+
const normalized = {};
|
|
373
|
+
for (const key of Reflect.ownKeys(optionsArg)) {
|
|
374
|
+
if (typeof key !== 'string' || !allowedKeys.has(key)) {
|
|
375
|
+
throw new SmartdataPersistenceError('invalid_argument', `Atomic update received unsupported option "${String(key)}".`);
|
|
376
|
+
}
|
|
377
|
+
const descriptor = Object.getOwnPropertyDescriptor(optionsArg, key);
|
|
378
|
+
if (!descriptor
|
|
379
|
+
|| !('value' in descriptor)
|
|
380
|
+
|| descriptor.enumerable !== true) {
|
|
381
|
+
throw new SmartdataPersistenceError('invalid_argument', `Atomic update option "${key}" must be an inert enumerable data property.`);
|
|
382
|
+
}
|
|
383
|
+
if (key === 'upsert') {
|
|
384
|
+
if (descriptor.value !== undefined
|
|
385
|
+
&& typeof descriptor.value !== 'boolean') {
|
|
386
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Atomic update upsert must be a boolean.');
|
|
387
|
+
}
|
|
388
|
+
if (descriptor.value !== undefined) {
|
|
389
|
+
normalized.upsert = descriptor.value;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
else if (descriptor.value !== undefined) {
|
|
393
|
+
normalized.session = descriptor.value;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
return normalized;
|
|
397
|
+
};
|
|
398
|
+
const reservedOrdinaryPersistenceFields = new Set([
|
|
399
|
+
'_id',
|
|
400
|
+
'_createdAt',
|
|
401
|
+
'_updatedAt',
|
|
402
|
+
'_smartdataRevision',
|
|
403
|
+
]);
|
|
404
|
+
const stringIdRootSets = new WeakSet();
|
|
405
|
+
const requireBoundedInteger = (valueArg, labelArg, maximumArg) => {
|
|
406
|
+
if (valueArg === undefined) {
|
|
407
|
+
return undefined;
|
|
408
|
+
}
|
|
409
|
+
if (!Number.isSafeInteger(valueArg) ||
|
|
410
|
+
valueArg <= 0 ||
|
|
411
|
+
valueArg > maximumArg) {
|
|
412
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} must be a positive safe integer no greater than ${maximumArg}.`);
|
|
413
|
+
}
|
|
414
|
+
return valueArg;
|
|
415
|
+
};
|
|
416
|
+
const requireDeclaredPath = (pathArg, declaredRootsArg, labelArg, declaredNestedPathsArg) => {
|
|
417
|
+
const pathSegments = typeof pathArg === 'string'
|
|
418
|
+
? pathArg.split('.')
|
|
419
|
+
: [];
|
|
420
|
+
if (typeof pathArg !== 'string' ||
|
|
421
|
+
pathArg.length === 0 ||
|
|
422
|
+
pathArg.length > 1024 ||
|
|
423
|
+
pathArg.includes('\0') ||
|
|
424
|
+
pathArg.startsWith('$') ||
|
|
425
|
+
pathSegments.length > 32 ||
|
|
426
|
+
pathSegments.some((segmentArg) => (segmentArg.length === 0
|
|
427
|
+
|| segmentArg.startsWith('$')
|
|
428
|
+
|| segmentArg.includes('\0')
|
|
429
|
+
|| unsafePersistedObjectKeys.has(segmentArg))) ||
|
|
430
|
+
(pathSegments.length > 1
|
|
431
|
+
&& !declaredNestedPathsArg?.has(pathArg))) {
|
|
432
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} contains invalid persisted path "${pathArg}".`);
|
|
433
|
+
}
|
|
434
|
+
const root = pathSegments[0];
|
|
435
|
+
if ((reservedOrdinaryPersistenceFields.has(root) &&
|
|
436
|
+
!(root === '_id' && stringIdRootSets.has(declaredRootsArg))) ||
|
|
437
|
+
!declaredRootsArg.has(root)) {
|
|
438
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} references undeclared or reserved persisted path "${pathArg}".`);
|
|
439
|
+
}
|
|
440
|
+
return root;
|
|
441
|
+
};
|
|
442
|
+
const unsafePersistedObjectKeys = new Set([
|
|
443
|
+
'__proto__',
|
|
444
|
+
'prototype',
|
|
445
|
+
'constructor',
|
|
446
|
+
]);
|
|
447
|
+
const assertSafePersistedValue = (valueArg, labelArg, seenArg = new WeakSet()) => {
|
|
448
|
+
if (typeof valueArg !== 'object' || valueArg === null) {
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
if (seenArg.has(valueArg)) {
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
454
|
+
seenArg.add(valueArg);
|
|
455
|
+
if (Array.isArray(valueArg)) {
|
|
456
|
+
for (const entryArg of valueArg) {
|
|
457
|
+
assertSafePersistedValue(entryArg, labelArg, seenArg);
|
|
458
|
+
}
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
if (!isPlainObject(valueArg)) {
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
for (const [keyArg, entryArg] of Object.entries(valueArg)) {
|
|
465
|
+
if (unsafePersistedObjectKeys.has(keyArg) ||
|
|
466
|
+
keyArg.startsWith('$') ||
|
|
467
|
+
keyArg.includes('.') ||
|
|
468
|
+
keyArg.includes('\0')) {
|
|
469
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} contains unsafe object key "${keyArg}".`);
|
|
470
|
+
}
|
|
471
|
+
assertSafePersistedValue(entryArg, labelArg, seenArg);
|
|
472
|
+
}
|
|
473
|
+
};
|
|
474
|
+
const atomicFilterComparisonOperators = new Set([
|
|
475
|
+
'$eq',
|
|
476
|
+
'$ne',
|
|
477
|
+
'$gt',
|
|
478
|
+
'$gte',
|
|
479
|
+
'$lt',
|
|
480
|
+
'$lte',
|
|
481
|
+
]);
|
|
482
|
+
const atomicFilterArrayOperators = new Set(['$in', '$nin']);
|
|
483
|
+
const atomicFilterOperators = new Set([
|
|
484
|
+
...atomicFilterComparisonOperators,
|
|
485
|
+
...atomicFilterArrayOperators,
|
|
486
|
+
'$exists',
|
|
487
|
+
'$type',
|
|
488
|
+
'$regex',
|
|
489
|
+
'$options',
|
|
490
|
+
'$not',
|
|
491
|
+
]);
|
|
492
|
+
const atomicFilterBsonTypes = new Set([
|
|
493
|
+
...Object.keys(plugins.mongodb.BSONType),
|
|
494
|
+
...Object.values(plugins.mongodb.BSONType),
|
|
495
|
+
]);
|
|
496
|
+
const atomicBsonScalarPrototypes = new Map([
|
|
497
|
+
[plugins.mongodb.ObjectId.prototype, 'ObjectId'],
|
|
498
|
+
[plugins.mongodb.Binary.prototype, 'Binary'],
|
|
499
|
+
[plugins.mongodb.Decimal128.prototype, 'Decimal128'],
|
|
500
|
+
[plugins.mongodb.Long.prototype, 'Long'],
|
|
501
|
+
[plugins.mongodb.Int32.prototype, 'Int32'],
|
|
502
|
+
[plugins.mongodb.Double.prototype, 'Double'],
|
|
503
|
+
[plugins.mongodb.Timestamp.prototype, 'Timestamp'],
|
|
504
|
+
[plugins.mongodb.MinKey.prototype, 'MinKey'],
|
|
505
|
+
[plugins.mongodb.MaxKey.prototype, 'MaxKey'],
|
|
506
|
+
]);
|
|
507
|
+
const getTrustedAtomicBsonScalarType = (valueArg) => {
|
|
508
|
+
if (typeof valueArg !== 'object'
|
|
509
|
+
|| valueArg === null
|
|
510
|
+
|| plugins.nodeUtil.types.isProxy(valueArg)) {
|
|
511
|
+
return undefined;
|
|
512
|
+
}
|
|
513
|
+
const expectedType = atomicBsonScalarPrototypes.get(Object.getPrototypeOf(valueArg));
|
|
514
|
+
if (!expectedType) {
|
|
515
|
+
return undefined;
|
|
516
|
+
}
|
|
517
|
+
const ownBsonTypeDescriptor = Object.getOwnPropertyDescriptor(valueArg, '_bsontype');
|
|
518
|
+
if (ownBsonTypeDescriptor
|
|
519
|
+
&& (!('value' in ownBsonTypeDescriptor)
|
|
520
|
+
|| ownBsonTypeDescriptor.value !== expectedType)) {
|
|
521
|
+
return undefined;
|
|
522
|
+
}
|
|
523
|
+
return expectedType;
|
|
524
|
+
};
|
|
525
|
+
const hasAtomicBsonTypeClaim = (valueArg) => {
|
|
526
|
+
if (typeof valueArg !== 'object'
|
|
527
|
+
|| valueArg === null
|
|
528
|
+
|| plugins.nodeUtil.types.isProxy(valueArg)) {
|
|
529
|
+
return false;
|
|
530
|
+
}
|
|
531
|
+
for (let prototype = valueArg; prototype; prototype = Object.getPrototypeOf(prototype)) {
|
|
532
|
+
if (Object.getOwnPropertyDescriptor(prototype, '_bsontype')) {
|
|
533
|
+
return true;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
return false;
|
|
537
|
+
};
|
|
538
|
+
const isAtomicMongoScalar = (valueArg) => {
|
|
539
|
+
if (typeof valueArg !== 'object'
|
|
540
|
+
|| valueArg === null
|
|
541
|
+
|| plugins.nodeUtil.types.isProxy(valueArg)) {
|
|
542
|
+
return false;
|
|
543
|
+
}
|
|
544
|
+
const valuePrototype = Object.getPrototypeOf(valueArg);
|
|
545
|
+
if (valuePrototype === Date.prototype
|
|
546
|
+
|| valuePrototype === RegExp.prototype) {
|
|
547
|
+
return true;
|
|
548
|
+
}
|
|
549
|
+
if (ArrayBuffer.isView(valueArg)) {
|
|
550
|
+
return true;
|
|
551
|
+
}
|
|
552
|
+
return getTrustedAtomicBsonScalarType(valueArg) !== undefined;
|
|
553
|
+
};
|
|
554
|
+
const allowedAtomicBsonScalarTypes = new Set([
|
|
555
|
+
'ObjectId',
|
|
556
|
+
'Binary',
|
|
557
|
+
'Decimal128',
|
|
558
|
+
'Long',
|
|
559
|
+
'Int32',
|
|
560
|
+
'Double',
|
|
561
|
+
'Timestamp',
|
|
562
|
+
'MinKey',
|
|
563
|
+
'MaxKey',
|
|
564
|
+
]);
|
|
565
|
+
const requireSafeAtomicEqualityScalar = (valueArg, labelArg) => {
|
|
566
|
+
if (typeof valueArg === 'object'
|
|
567
|
+
&& valueArg !== null
|
|
568
|
+
&& plugins.nodeUtil.types.isProxy(valueArg)) {
|
|
569
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} may not use a Proxy object.`);
|
|
570
|
+
}
|
|
571
|
+
if (valueArg instanceof RegExp) {
|
|
572
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} may not use a regular expression as an equality value.`);
|
|
573
|
+
}
|
|
574
|
+
if (valueArg instanceof Date &&
|
|
575
|
+
Object.getPrototypeOf(valueArg) !== Date.prototype) {
|
|
576
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} may not use a Date subclass with custom BSON behavior.`);
|
|
577
|
+
}
|
|
578
|
+
const bsonType = getTrustedAtomicBsonScalarType(valueArg);
|
|
579
|
+
if (hasAtomicBsonTypeClaim(valueArg)
|
|
580
|
+
&& (!bsonType
|
|
581
|
+
|| !allowedAtomicBsonScalarTypes.has(bsonType))) {
|
|
582
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} uses an unsupported BSON equality scalar.`);
|
|
583
|
+
}
|
|
584
|
+
};
|
|
585
|
+
const requireUsableIdentityValue = (valueArg, labelArg, valueTypeArg) => {
|
|
586
|
+
if (valueTypeArg === 'positiveSafeInteger') {
|
|
587
|
+
if (typeof valueArg === 'number'
|
|
588
|
+
&& Number.isSafeInteger(valueArg)
|
|
589
|
+
&& valueArg > 0) {
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} must contain a positive safe integer identity value.`);
|
|
593
|
+
}
|
|
594
|
+
if (typeof valueArg !== 'string' || valueArg.trim().length === 0) {
|
|
595
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} must contain a non-empty string identity value.`);
|
|
596
|
+
}
|
|
597
|
+
};
|
|
598
|
+
const assertUsableIdentityValues = (documentArg, identityFieldsArg, identityValueTypesArg) => {
|
|
599
|
+
for (const identityField of identityFieldsArg) {
|
|
600
|
+
requireUsableIdentityValue(documentArg[identityField], `Identity field "${identityField}"`, identityValueTypesArg?.[identityField] ?? 'string');
|
|
601
|
+
}
|
|
602
|
+
};
|
|
603
|
+
/**
|
|
604
|
+
* Validates the explicit `$eq` operand used for whole-object compare-and-set
|
|
605
|
+
* filters. Direct nested object selectors remain forbidden; the operator is
|
|
606
|
+
* required so object equality cannot be confused with query structure.
|
|
607
|
+
*/
|
|
608
|
+
const assertOnlyDataProperties = (valueArg, labelArg, arrayArg) => {
|
|
609
|
+
for (const ownKey of Reflect.ownKeys(valueArg)) {
|
|
610
|
+
if (typeof ownKey === 'symbol') {
|
|
611
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} may not contain symbol properties.`);
|
|
612
|
+
}
|
|
613
|
+
if (arrayArg && ownKey === 'length') {
|
|
614
|
+
continue;
|
|
615
|
+
}
|
|
616
|
+
const descriptor = Object.getOwnPropertyDescriptor(valueArg, ownKey);
|
|
617
|
+
if (!descriptor ||
|
|
618
|
+
!('value' in descriptor) ||
|
|
619
|
+
typeof descriptor.value === 'function') {
|
|
620
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} may contain only inert data properties.`);
|
|
621
|
+
}
|
|
622
|
+
if (!descriptor.enumerable && !arrayArg) {
|
|
623
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} may not contain hidden data properties.`);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
};
|
|
627
|
+
const typedArrayPrototype = Object.getPrototypeOf(Uint8Array.prototype);
|
|
628
|
+
const typedArrayBufferGetter = Object.getOwnPropertyDescriptor(typedArrayPrototype, 'buffer')?.get;
|
|
629
|
+
const typedArrayByteOffsetGetter = Object.getOwnPropertyDescriptor(typedArrayPrototype, 'byteOffset')?.get;
|
|
630
|
+
const typedArrayByteLengthGetter = Object.getOwnPropertyDescriptor(typedArrayPrototype, 'byteLength')?.get;
|
|
631
|
+
const dataViewBufferGetter = Object.getOwnPropertyDescriptor(DataView.prototype, 'buffer')?.get;
|
|
632
|
+
const dataViewByteOffsetGetter = Object.getOwnPropertyDescriptor(DataView.prototype, 'byteOffset')?.get;
|
|
633
|
+
const dataViewByteLengthGetter = Object.getOwnPropertyDescriptor(DataView.prototype, 'byteLength')?.get;
|
|
634
|
+
const regExpSourceGetter = Object.getOwnPropertyDescriptor(RegExp.prototype, 'source')?.get;
|
|
635
|
+
const regExpFlagGetters = [
|
|
636
|
+
['d', 'hasIndices'],
|
|
637
|
+
['g', 'global'],
|
|
638
|
+
['i', 'ignoreCase'],
|
|
639
|
+
['m', 'multiline'],
|
|
640
|
+
['s', 'dotAll'],
|
|
641
|
+
['u', 'unicode'],
|
|
642
|
+
['v', 'unicodeSets'],
|
|
643
|
+
['y', 'sticky'],
|
|
644
|
+
].map(([flag, property]) => ({
|
|
645
|
+
flag,
|
|
646
|
+
getter: Object.getOwnPropertyDescriptor(RegExp.prototype, property)?.get,
|
|
647
|
+
}));
|
|
648
|
+
const getIntrinsicArrayBufferViewBytes = (valueArg, labelArg) => {
|
|
649
|
+
const readView = (bufferGetterArg, byteOffsetGetterArg, byteLengthGetterArg) => {
|
|
650
|
+
if (!bufferGetterArg
|
|
651
|
+
|| !byteOffsetGetterArg
|
|
652
|
+
|| !byteLengthGetterArg) {
|
|
653
|
+
return undefined;
|
|
654
|
+
}
|
|
655
|
+
try {
|
|
656
|
+
const buffer = Reflect.apply(bufferGetterArg, valueArg, []);
|
|
657
|
+
const byteOffset = Reflect.apply(byteOffsetGetterArg, valueArg, []);
|
|
658
|
+
const byteLength = Reflect.apply(byteLengthGetterArg, valueArg, []);
|
|
659
|
+
return new Uint8Array(buffer, byteOffset, byteLength);
|
|
660
|
+
}
|
|
661
|
+
catch {
|
|
662
|
+
return undefined;
|
|
663
|
+
}
|
|
664
|
+
};
|
|
665
|
+
const bytes = readView(typedArrayBufferGetter, typedArrayByteOffsetGetter, typedArrayByteLengthGetter)
|
|
666
|
+
|| readView(dataViewBufferGetter, dataViewByteOffsetGetter, dataViewByteLengthGetter);
|
|
667
|
+
if (!bytes) {
|
|
668
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} contains an invalid ArrayBuffer view.`);
|
|
669
|
+
}
|
|
670
|
+
return bytes;
|
|
671
|
+
};
|
|
672
|
+
const createInertAtomicBsonScalarSnapshot = (valueArg, labelArg) => {
|
|
673
|
+
if (valueArg instanceof Date) {
|
|
674
|
+
if (Object.getPrototypeOf(valueArg) !== Date.prototype ||
|
|
675
|
+
Reflect.ownKeys(valueArg).length !== 0) {
|
|
676
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} may not use a customized Date value.`);
|
|
677
|
+
}
|
|
678
|
+
const snapshot = new Date(valueArg.getTime());
|
|
679
|
+
Object.defineProperty(snapshot, 'toBSON', {
|
|
680
|
+
value: undefined,
|
|
681
|
+
enumerable: false,
|
|
682
|
+
});
|
|
683
|
+
return snapshot;
|
|
684
|
+
}
|
|
685
|
+
if (ArrayBuffer.isView(valueArg)) {
|
|
686
|
+
assertOnlyDataProperties(valueArg, labelArg, false);
|
|
687
|
+
const snapshot = Uint8Array.from(getIntrinsicArrayBufferViewBytes(valueArg, labelArg));
|
|
688
|
+
Object.defineProperty(snapshot, 'toBSON', {
|
|
689
|
+
value: undefined,
|
|
690
|
+
enumerable: false,
|
|
691
|
+
});
|
|
692
|
+
return snapshot;
|
|
693
|
+
}
|
|
694
|
+
const originalBsonType = getTrustedAtomicBsonScalarType(valueArg);
|
|
695
|
+
if (!originalBsonType) {
|
|
696
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} contains an untrusted BSON scalar.`);
|
|
697
|
+
}
|
|
698
|
+
assertOnlyDataProperties(valueArg, labelArg, false);
|
|
699
|
+
for (let prototype = valueArg; prototype; prototype = Object.getPrototypeOf(prototype)) {
|
|
700
|
+
if (Object.getOwnPropertyDescriptor(prototype, 'toBSON')) {
|
|
701
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} may not use a custom BSON encoder.`);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
try {
|
|
705
|
+
const snapshotDocument = plugins.mongodb.BSON.deserialize(plugins.mongodb.BSON.serialize({ value: valueArg }), {
|
|
706
|
+
promoteBuffers: false,
|
|
707
|
+
promoteValues: false,
|
|
708
|
+
});
|
|
709
|
+
const snapshot = snapshotDocument.value;
|
|
710
|
+
if (getTrustedAtomicBsonScalarType(snapshot) !== originalBsonType) {
|
|
711
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} changed BSON scalar type while being captured.`);
|
|
712
|
+
}
|
|
713
|
+
Object.defineProperty(snapshot, 'toBSON', {
|
|
714
|
+
value: undefined,
|
|
715
|
+
enumerable: false,
|
|
716
|
+
});
|
|
717
|
+
return snapshot;
|
|
718
|
+
}
|
|
719
|
+
catch (cause) {
|
|
720
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} contains an invalid BSON scalar.`, { cause });
|
|
721
|
+
}
|
|
722
|
+
};
|
|
723
|
+
const createSafeAtomicExactObjectEqualitySnapshot = (valueArg, labelArg, seenArg = new WeakSet()) => {
|
|
724
|
+
if (valueArg === undefined) {
|
|
725
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} may not contain undefined.`);
|
|
726
|
+
}
|
|
727
|
+
if (typeof valueArg === 'function'
|
|
728
|
+
|| typeof valueArg === 'symbol') {
|
|
729
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} contains a value that cannot be encoded as safe BSON.`);
|
|
730
|
+
}
|
|
731
|
+
if (typeof valueArg !== 'object' || valueArg === null) {
|
|
732
|
+
return valueArg;
|
|
733
|
+
}
|
|
734
|
+
if (plugins.nodeUtil.types.isProxy(valueArg)) {
|
|
735
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} may not contain Proxy objects.`);
|
|
736
|
+
}
|
|
737
|
+
if (seenArg.has(valueArg)) {
|
|
738
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} may not contain a circular object graph.`);
|
|
739
|
+
}
|
|
740
|
+
if (isAtomicMongoScalar(valueArg)) {
|
|
741
|
+
requireSafeAtomicEqualityScalar(valueArg, labelArg);
|
|
742
|
+
return createInertAtomicBsonScalarSnapshot(valueArg, labelArg);
|
|
743
|
+
}
|
|
744
|
+
if (!Array.isArray(valueArg) && !isPlainObject(valueArg)) {
|
|
745
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} contains an object with a custom BSON encoding boundary.`);
|
|
746
|
+
}
|
|
747
|
+
if (Array.isArray(valueArg) &&
|
|
748
|
+
Object.getPrototypeOf(valueArg) !== Array.prototype) {
|
|
749
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} may not use an Array subclass.`);
|
|
750
|
+
}
|
|
751
|
+
assertOnlyDataProperties(valueArg, labelArg, Array.isArray(valueArg));
|
|
752
|
+
seenArg.add(valueArg);
|
|
753
|
+
if (Array.isArray(valueArg)) {
|
|
754
|
+
const snapshot = [];
|
|
755
|
+
for (let index = 0; index < valueArg.length; index++) {
|
|
756
|
+
if (!Object.prototype.hasOwnProperty.call(valueArg, index)) {
|
|
757
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} may not contain sparse array positions.`);
|
|
758
|
+
}
|
|
759
|
+
snapshot.push(createSafeAtomicExactObjectEqualitySnapshot(valueArg[index], labelArg, seenArg));
|
|
760
|
+
}
|
|
761
|
+
seenArg.delete(valueArg);
|
|
762
|
+
Object.defineProperty(snapshot, 'toBSON', {
|
|
763
|
+
value: undefined,
|
|
764
|
+
enumerable: false,
|
|
765
|
+
});
|
|
766
|
+
return snapshot;
|
|
767
|
+
}
|
|
768
|
+
const snapshot = {};
|
|
769
|
+
for (const [keyArg, entryArg] of Object.entries(valueArg)) {
|
|
770
|
+
if (unsafePersistedObjectKeys.has(keyArg)
|
|
771
|
+
|| keyArg === 'toBSON'
|
|
772
|
+
|| keyArg === '_bsontype'
|
|
773
|
+
|| keyArg.startsWith('$')
|
|
774
|
+
|| keyArg.includes('.')
|
|
775
|
+
|| keyArg.includes('\0')) {
|
|
776
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} contains unsafe object key "${keyArg}".`);
|
|
777
|
+
}
|
|
778
|
+
Object.defineProperty(snapshot, keyArg, {
|
|
779
|
+
value: createSafeAtomicExactObjectEqualitySnapshot(entryArg, labelArg, seenArg),
|
|
780
|
+
enumerable: true,
|
|
781
|
+
writable: false,
|
|
782
|
+
configurable: false,
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
seenArg.delete(valueArg);
|
|
786
|
+
Object.defineProperty(snapshot, 'toBSON', {
|
|
787
|
+
value: undefined,
|
|
788
|
+
enumerable: false,
|
|
789
|
+
});
|
|
790
|
+
return snapshot;
|
|
791
|
+
};
|
|
792
|
+
const createSafeAtomicFilterValueSnapshot = (valueArg, labelArg) => {
|
|
793
|
+
if (valueArg === undefined
|
|
794
|
+
|| typeof valueArg === 'function'
|
|
795
|
+
|| typeof valueArg === 'symbol') {
|
|
796
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} contains a value that cannot be encoded as safe BSON.`);
|
|
797
|
+
}
|
|
798
|
+
if (typeof valueArg === 'object'
|
|
799
|
+
&& valueArg !== null
|
|
800
|
+
&& plugins.nodeUtil.types.isProxy(valueArg)) {
|
|
801
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} may not use a Proxy object.`);
|
|
802
|
+
}
|
|
803
|
+
if (Array.isArray(valueArg)) {
|
|
804
|
+
if (Object.getPrototypeOf(valueArg) !== Array.prototype) {
|
|
805
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} may not use an Array subclass.`);
|
|
806
|
+
}
|
|
807
|
+
assertOnlyDataProperties(valueArg, labelArg, true);
|
|
808
|
+
const snapshot = [];
|
|
809
|
+
for (let index = 0; index < valueArg.length; index++) {
|
|
810
|
+
if (!Object.prototype.hasOwnProperty.call(valueArg, index)) {
|
|
811
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} may not contain sparse array positions.`);
|
|
812
|
+
}
|
|
813
|
+
snapshot.push(createSafeAtomicFilterValueSnapshot(valueArg[index], labelArg));
|
|
814
|
+
}
|
|
815
|
+
return snapshot;
|
|
816
|
+
}
|
|
817
|
+
if (typeof valueArg !== 'object' || valueArg === null) {
|
|
818
|
+
return valueArg;
|
|
819
|
+
}
|
|
820
|
+
requireSafeAtomicEqualityScalar(valueArg, labelArg);
|
|
821
|
+
if (!isAtomicMongoScalar(valueArg)) {
|
|
822
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} must be a scalar BSON value.`);
|
|
823
|
+
}
|
|
824
|
+
return createInertAtomicBsonScalarSnapshot(valueArg, labelArg);
|
|
825
|
+
};
|
|
826
|
+
const createSafeAtomicRegExpSnapshot = (valueArg, labelArg) => {
|
|
827
|
+
if (plugins.nodeUtil.types.isProxy(valueArg)
|
|
828
|
+
|| Object.getPrototypeOf(valueArg) !== RegExp.prototype
|
|
829
|
+
|| !regExpSourceGetter) {
|
|
830
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} may not use a Proxy or RegExp subclass.`);
|
|
831
|
+
}
|
|
832
|
+
const source = Reflect.apply(regExpSourceGetter, valueArg, []);
|
|
833
|
+
const flags = regExpFlagGetters
|
|
834
|
+
.filter(({ getter }) => getter && Reflect.apply(getter, valueArg, []))
|
|
835
|
+
.map(({ flag }) => flag)
|
|
836
|
+
.join('');
|
|
837
|
+
return new RegExp(source, flags);
|
|
838
|
+
};
|
|
839
|
+
const normalizeAtomicFilterCondition = (valueArg, labelArg, identityValueTypeArg) => {
|
|
840
|
+
if (valueArg === undefined) {
|
|
841
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} may not contain undefined.`);
|
|
842
|
+
}
|
|
843
|
+
if (typeof valueArg === 'object'
|
|
844
|
+
&& valueArg !== null
|
|
845
|
+
&& plugins.nodeUtil.types.isProxy(valueArg)) {
|
|
846
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} may not use a Proxy object.`);
|
|
847
|
+
}
|
|
848
|
+
if (!isPlainObject(valueArg) || isAtomicMongoScalar(valueArg)) {
|
|
849
|
+
requireSafeAtomicEqualityScalar(valueArg, labelArg);
|
|
850
|
+
if (identityValueTypeArg) {
|
|
851
|
+
requireUsableIdentityValue(valueArg, labelArg, identityValueTypeArg);
|
|
852
|
+
}
|
|
853
|
+
return createSafeAtomicFilterValueSnapshot(valueArg, labelArg);
|
|
854
|
+
}
|
|
855
|
+
assertOnlyDataProperties(valueArg, labelArg, false);
|
|
856
|
+
const entries = Object.entries(valueArg);
|
|
857
|
+
if (entries.length === 0) {
|
|
858
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} may not be an empty object.`);
|
|
859
|
+
}
|
|
860
|
+
const operatorEntries = entries.filter(([key]) => key.startsWith('$'));
|
|
861
|
+
if (operatorEntries.length === 0) {
|
|
862
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} must use supported field operators instead of a nested object selector.`);
|
|
863
|
+
}
|
|
864
|
+
if (operatorEntries.length !== entries.length) {
|
|
865
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} may not mix operator and literal object keys.`);
|
|
866
|
+
}
|
|
867
|
+
const normalized = {};
|
|
868
|
+
for (const [operator, operand] of operatorEntries) {
|
|
869
|
+
if (!atomicFilterOperators.has(operator)) {
|
|
870
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} uses unsupported operator "${operator}".`);
|
|
871
|
+
}
|
|
872
|
+
if (atomicFilterComparisonOperators.has(operator)) {
|
|
873
|
+
if (operator === '$eq'
|
|
874
|
+
&& typeof operand === 'object'
|
|
875
|
+
&& operand !== null
|
|
876
|
+
&& !isAtomicMongoScalar(operand)) {
|
|
877
|
+
if (identityValueTypeArg) {
|
|
878
|
+
requireUsableIdentityValue(operand, `${labelArg} ${operator}`, identityValueTypeArg);
|
|
879
|
+
}
|
|
880
|
+
normalized[operator] =
|
|
881
|
+
createSafeAtomicExactObjectEqualitySnapshot(operand, `${labelArg} ${operator}`);
|
|
882
|
+
continue;
|
|
883
|
+
}
|
|
884
|
+
if (identityValueTypeArg) {
|
|
885
|
+
requireUsableIdentityValue(operand, `${labelArg} ${operator}`, identityValueTypeArg);
|
|
886
|
+
}
|
|
887
|
+
normalized[operator] = createSafeAtomicFilterValueSnapshot(operand, `${labelArg} ${operator}`);
|
|
888
|
+
continue;
|
|
889
|
+
}
|
|
890
|
+
if (atomicFilterArrayOperators.has(operator)) {
|
|
891
|
+
if (!Array.isArray(operand)
|
|
892
|
+
|| plugins.nodeUtil.types.isProxy(operand)
|
|
893
|
+
|| Object.getPrototypeOf(operand) !== Array.prototype) {
|
|
894
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} ${operator} must be an ordinary non-empty array.`);
|
|
895
|
+
}
|
|
896
|
+
assertOnlyDataProperties(operand, `${labelArg} ${operator}`, true);
|
|
897
|
+
if (operand.length === 0) {
|
|
898
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} ${operator} must be an ordinary non-empty array.`);
|
|
899
|
+
}
|
|
900
|
+
if (identityValueTypeArg) {
|
|
901
|
+
for (const entry of operand) {
|
|
902
|
+
requireUsableIdentityValue(entry, `${labelArg} ${operator}`, identityValueTypeArg);
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
normalized[operator] = createSafeAtomicFilterValueSnapshot(operand, `${labelArg} ${operator}`);
|
|
906
|
+
continue;
|
|
907
|
+
}
|
|
908
|
+
if (operator === '$exists') {
|
|
909
|
+
if (typeof operand !== 'boolean') {
|
|
910
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} $exists must be a boolean.`);
|
|
911
|
+
}
|
|
912
|
+
normalized[operator] = operand;
|
|
913
|
+
continue;
|
|
914
|
+
}
|
|
915
|
+
if (operator === '$type') {
|
|
916
|
+
if (!atomicFilterBsonTypes.has(operand)) {
|
|
917
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} $type must use a MongoDB BSON type alias or numeric code.`);
|
|
918
|
+
}
|
|
919
|
+
normalized[operator] = operand;
|
|
920
|
+
continue;
|
|
921
|
+
}
|
|
922
|
+
if (operator === '$regex') {
|
|
923
|
+
if (typeof operand === 'string' && operand.length > 0) {
|
|
924
|
+
normalized[operator] = operand;
|
|
925
|
+
continue;
|
|
926
|
+
}
|
|
927
|
+
if (typeof operand !== 'object' || operand === null) {
|
|
928
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} $regex must be a non-empty string or RegExp.`);
|
|
929
|
+
}
|
|
930
|
+
normalized[operator] = createSafeAtomicRegExpSnapshot(operand, `${labelArg} ${operator}`);
|
|
931
|
+
continue;
|
|
932
|
+
}
|
|
933
|
+
if (operator === '$options') {
|
|
934
|
+
if (typeof operand !== 'string' ||
|
|
935
|
+
!/^[imsx]*$/.test(operand) ||
|
|
936
|
+
!('$regex' in valueArg)) {
|
|
937
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} $options must contain only imsx flags and accompany $regex.`);
|
|
938
|
+
}
|
|
939
|
+
normalized[operator] = operand;
|
|
940
|
+
continue;
|
|
941
|
+
}
|
|
942
|
+
if (operator === '$not') {
|
|
943
|
+
if ((typeof operand === 'object'
|
|
944
|
+
&& operand !== null
|
|
945
|
+
&& plugins.nodeUtil.types.isProxy(operand))
|
|
946
|
+
||
|
|
947
|
+
!isPlainObject(operand) ||
|
|
948
|
+
Object.keys(operand).length === 0 ||
|
|
949
|
+
Object.keys(operand).some((key) => !key.startsWith('$'))) {
|
|
950
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} $not must contain a non-empty operator object.`);
|
|
951
|
+
}
|
|
952
|
+
assertOnlyDataProperties(operand, `${labelArg} $not`, false);
|
|
953
|
+
normalized[operator] = normalizeAtomicFilterCondition(operand, `${labelArg} $not`, identityValueTypeArg);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
return normalized;
|
|
957
|
+
};
|
|
958
|
+
const atomicNumericExpressionMaximumDepth = 8;
|
|
959
|
+
const atomicNumericExpressionMaximumAddOperands = 16;
|
|
960
|
+
const atomicNumericExpressionMaximumLeafOperands = 64;
|
|
961
|
+
const getAtomicExpressionProperty = (valueArg, expectedKeyArg, labelArg) => {
|
|
962
|
+
if (typeof valueArg !== 'object'
|
|
963
|
+
|| valueArg === null
|
|
964
|
+
|| Array.isArray(valueArg)
|
|
965
|
+
|| plugins.nodeUtil.types.isProxy(valueArg)
|
|
966
|
+
|| Object.getPrototypeOf(valueArg) !== Object.prototype) {
|
|
967
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} must be an inert ordinary object containing only ${expectedKeyArg}.`);
|
|
968
|
+
}
|
|
969
|
+
const keys = Reflect.ownKeys(valueArg);
|
|
970
|
+
if (keys.length !== 1 || keys[0] !== expectedKeyArg) {
|
|
971
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} must contain exactly the ${expectedKeyArg} operator.`);
|
|
972
|
+
}
|
|
973
|
+
const descriptor = Object.getOwnPropertyDescriptor(valueArg, expectedKeyArg);
|
|
974
|
+
if (!descriptor
|
|
975
|
+
|| !('value' in descriptor)
|
|
976
|
+
|| descriptor.enumerable !== true) {
|
|
977
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} ${expectedKeyArg} must be an inert enumerable data property.`);
|
|
978
|
+
}
|
|
979
|
+
return descriptor.value;
|
|
980
|
+
};
|
|
981
|
+
const getAtomicExpressionArrayValues = (valueArg, minimumLengthArg, maximumLengthArg, labelArg) => {
|
|
982
|
+
if (typeof valueArg !== 'object'
|
|
983
|
+
|| valueArg === null
|
|
984
|
+
|| plugins.nodeUtil.types.isProxy(valueArg)
|
|
985
|
+
|| !Array.isArray(valueArg)
|
|
986
|
+
|| Object.getPrototypeOf(valueArg) !== Array.prototype) {
|
|
987
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} must be an inert ordinary array.`);
|
|
988
|
+
}
|
|
989
|
+
const lengthDescriptor = Object.getOwnPropertyDescriptor(valueArg, 'length');
|
|
990
|
+
const length = lengthDescriptor && 'value' in lengthDescriptor
|
|
991
|
+
? lengthDescriptor.value
|
|
992
|
+
: undefined;
|
|
993
|
+
if (!Number.isSafeInteger(length)
|
|
994
|
+
|| length < minimumLengthArg
|
|
995
|
+
|| length > maximumLengthArg) {
|
|
996
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} must contain between ${minimumLengthArg} and ${maximumLengthArg} operands.`);
|
|
997
|
+
}
|
|
998
|
+
const ownKeys = Reflect.ownKeys(valueArg);
|
|
999
|
+
if (ownKeys.length !== length + 1 || !ownKeys.includes('length')) {
|
|
1000
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} may not contain sparse positions or extra properties.`);
|
|
1001
|
+
}
|
|
1002
|
+
const values = [];
|
|
1003
|
+
for (let index = 0; index < length; index++) {
|
|
1004
|
+
const key = String(index);
|
|
1005
|
+
const descriptor = Object.getOwnPropertyDescriptor(valueArg, key);
|
|
1006
|
+
if (!descriptor
|
|
1007
|
+
|| !('value' in descriptor)
|
|
1008
|
+
|| descriptor.enumerable !== true) {
|
|
1009
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} may contain only dense enumerable data operands.`);
|
|
1010
|
+
}
|
|
1011
|
+
values.push(descriptor.value);
|
|
1012
|
+
}
|
|
1013
|
+
return values;
|
|
1014
|
+
};
|
|
1015
|
+
const normalizeAtomicNumericExpression = (expressionArg, declaredRootsArg, numericRootsArg, serializedRootsArg, operationLabelArg) => {
|
|
1016
|
+
let leafOperandCount = 0;
|
|
1017
|
+
const normalizeOperand = (operandArg, depthArg) => {
|
|
1018
|
+
if (typeof operandArg === 'number') {
|
|
1019
|
+
leafOperandCount++;
|
|
1020
|
+
if (!Number.isFinite(operandArg)
|
|
1021
|
+
|| leafOperandCount > atomicNumericExpressionMaximumLeafOperands) {
|
|
1022
|
+
throw new SmartdataPersistenceError('invalid_argument', `${operationLabelArg} $expr requires finite numeric literals and no more than ${atomicNumericExpressionMaximumLeafOperands} leaf operands.`);
|
|
1023
|
+
}
|
|
1024
|
+
return {
|
|
1025
|
+
mongoExpression: operandArg,
|
|
1026
|
+
referencedFields: new Set(),
|
|
1027
|
+
};
|
|
1028
|
+
}
|
|
1029
|
+
if (typeof operandArg === 'string') {
|
|
1030
|
+
leafOperandCount++;
|
|
1031
|
+
if (leafOperandCount > atomicNumericExpressionMaximumLeafOperands) {
|
|
1032
|
+
throw new SmartdataPersistenceError('invalid_argument', `${operationLabelArg} $expr may not exceed ${atomicNumericExpressionMaximumLeafOperands} leaf operands.`);
|
|
1033
|
+
}
|
|
1034
|
+
if (!operandArg.startsWith('$')
|
|
1035
|
+
|| operandArg.startsWith('$$')
|
|
1036
|
+
|| operandArg.length < 2) {
|
|
1037
|
+
throw new SmartdataPersistenceError('invalid_argument', `${operationLabelArg} $expr field references must use exactly one leading $.`);
|
|
1038
|
+
}
|
|
1039
|
+
const field = operandArg.slice(1);
|
|
1040
|
+
if (field === 'toBSON' || field === '_bsontype') {
|
|
1041
|
+
throw new SmartdataPersistenceError('invalid_argument', `${operationLabelArg} $expr field "${field}" is reserved.`);
|
|
1042
|
+
}
|
|
1043
|
+
const root = requireDeclaredPath(field, declaredRootsArg, `${operationLabelArg} $expr`);
|
|
1044
|
+
if (field !== root) {
|
|
1045
|
+
throw new SmartdataPersistenceError('invalid_argument', `${operationLabelArg} $expr may reference only declared top-level fields.`);
|
|
1046
|
+
}
|
|
1047
|
+
if (!numericRootsArg.has(root)) {
|
|
1048
|
+
throw new SmartdataPersistenceError('invalid_argument', `${operationLabelArg} $expr field "${root}" is not declared numeric.`);
|
|
1049
|
+
}
|
|
1050
|
+
if (serializedRootsArg.has(root)) {
|
|
1051
|
+
throw new SmartdataPersistenceError('unsupported_operation', `${operationLabelArg} $expr cannot reference serialized field "${root}".`);
|
|
1052
|
+
}
|
|
1053
|
+
return {
|
|
1054
|
+
mongoExpression: `$${root}`,
|
|
1055
|
+
referencedFields: new Set([root]),
|
|
1056
|
+
};
|
|
1057
|
+
}
|
|
1058
|
+
if (depthArg >= atomicNumericExpressionMaximumDepth) {
|
|
1059
|
+
throw new SmartdataPersistenceError('invalid_argument', `${operationLabelArg} $expr exceeds the maximum $add depth of ${atomicNumericExpressionMaximumDepth}.`);
|
|
1060
|
+
}
|
|
1061
|
+
const rawOperands = getAtomicExpressionArrayValues(getAtomicExpressionProperty(operandArg, '$add', `${operationLabelArg} $expr operand`), 2, atomicNumericExpressionMaximumAddOperands, `${operationLabelArg} $expr $add`);
|
|
1062
|
+
const normalizedOperands = rawOperands.map((entryArg) => normalizeOperand(entryArg, depthArg + 1));
|
|
1063
|
+
return {
|
|
1064
|
+
mongoExpression: {
|
|
1065
|
+
$add: normalizedOperands.map((entryArg) => entryArg.mongoExpression),
|
|
1066
|
+
},
|
|
1067
|
+
referencedFields: new Set(normalizedOperands.flatMap((entryArg) => [
|
|
1068
|
+
...entryArg.referencedFields,
|
|
1069
|
+
])),
|
|
1070
|
+
};
|
|
1071
|
+
};
|
|
1072
|
+
const lteOperands = getAtomicExpressionArrayValues(getAtomicExpressionProperty(expressionArg, '$lte', `${operationLabelArg} $expr`), 2, 2, `${operationLabelArg} $expr $lte`);
|
|
1073
|
+
const left = normalizeOperand(lteOperands[0], 0);
|
|
1074
|
+
const right = normalizeOperand(lteOperands[1], 0);
|
|
1075
|
+
const referencedFields = new Set([
|
|
1076
|
+
...left.referencedFields,
|
|
1077
|
+
...right.referencedFields,
|
|
1078
|
+
]);
|
|
1079
|
+
const fieldGuards = [...referencedFields].map((fieldArg) => ({
|
|
1080
|
+
$cond: [
|
|
1081
|
+
{ $isNumber: `$${fieldArg}` },
|
|
1082
|
+
{
|
|
1083
|
+
$eq: [
|
|
1084
|
+
{ $subtract: [`$${fieldArg}`, `$${fieldArg}`] },
|
|
1085
|
+
0,
|
|
1086
|
+
],
|
|
1087
|
+
},
|
|
1088
|
+
false,
|
|
1089
|
+
],
|
|
1090
|
+
}));
|
|
1091
|
+
const guardedComparison = {
|
|
1092
|
+
$let: {
|
|
1093
|
+
vars: {
|
|
1094
|
+
smartdataAtomicExprLeft: left.mongoExpression,
|
|
1095
|
+
smartdataAtomicExprRight: right.mongoExpression,
|
|
1096
|
+
},
|
|
1097
|
+
in: {
|
|
1098
|
+
$cond: [
|
|
1099
|
+
{
|
|
1100
|
+
$and: [
|
|
1101
|
+
{ $isNumber: '$$smartdataAtomicExprLeft' },
|
|
1102
|
+
{ $isNumber: '$$smartdataAtomicExprRight' },
|
|
1103
|
+
{
|
|
1104
|
+
$eq: [
|
|
1105
|
+
{
|
|
1106
|
+
$subtract: [
|
|
1107
|
+
'$$smartdataAtomicExprLeft',
|
|
1108
|
+
'$$smartdataAtomicExprLeft',
|
|
1109
|
+
],
|
|
1110
|
+
},
|
|
1111
|
+
0,
|
|
1112
|
+
],
|
|
1113
|
+
},
|
|
1114
|
+
{
|
|
1115
|
+
$eq: [
|
|
1116
|
+
{
|
|
1117
|
+
$subtract: [
|
|
1118
|
+
'$$smartdataAtomicExprRight',
|
|
1119
|
+
'$$smartdataAtomicExprRight',
|
|
1120
|
+
],
|
|
1121
|
+
},
|
|
1122
|
+
0,
|
|
1123
|
+
],
|
|
1124
|
+
},
|
|
1125
|
+
],
|
|
1126
|
+
},
|
|
1127
|
+
{
|
|
1128
|
+
$lte: [
|
|
1129
|
+
'$$smartdataAtomicExprLeft',
|
|
1130
|
+
'$$smartdataAtomicExprRight',
|
|
1131
|
+
],
|
|
1132
|
+
},
|
|
1133
|
+
false,
|
|
1134
|
+
],
|
|
1135
|
+
},
|
|
1136
|
+
},
|
|
1137
|
+
};
|
|
1138
|
+
return fieldGuards.length > 0
|
|
1139
|
+
? {
|
|
1140
|
+
$cond: [
|
|
1141
|
+
{ $and: fieldGuards },
|
|
1142
|
+
guardedComparison,
|
|
1143
|
+
false,
|
|
1144
|
+
],
|
|
1145
|
+
}
|
|
1146
|
+
: guardedComparison;
|
|
1147
|
+
};
|
|
1148
|
+
const normalizeStrictFilter = (filterArg, declaredRootsArg, declaredNestedPathsArg, identityValueTypesArg, numericRootsArg, serializedRootsArg, operationLabelArg, globallyConstrainingKeySetsArg) => {
|
|
1149
|
+
if (typeof filterArg !== 'object' ||
|
|
1150
|
+
filterArg === null ||
|
|
1151
|
+
Array.isArray(filterArg) ||
|
|
1152
|
+
plugins.nodeUtil.types.isProxy(filterArg) ||
|
|
1153
|
+
!isPlainObject(filterArg) ||
|
|
1154
|
+
Object.keys(filterArg).length === 0) {
|
|
1155
|
+
throw new SmartdataPersistenceError('invalid_argument', `${operationLabelArg} requires a non-empty filter object.`);
|
|
1156
|
+
}
|
|
1157
|
+
assertOnlyDataProperties(filterArg, `${operationLabelArg} filter`, false);
|
|
1158
|
+
const requireInertLogicalFilterArray = (valueArg, labelArg) => {
|
|
1159
|
+
if (!Array.isArray(valueArg)
|
|
1160
|
+
|| plugins.nodeUtil.types.isProxy(valueArg)
|
|
1161
|
+
|| Object.getPrototypeOf(valueArg) !== Array.prototype
|
|
1162
|
+
|| valueArg.length === 0) {
|
|
1163
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} must be a non-empty ordinary array of filters.`);
|
|
1164
|
+
}
|
|
1165
|
+
assertOnlyDataProperties(valueArg, labelArg, true);
|
|
1166
|
+
for (let index = 0; index < valueArg.length; index++) {
|
|
1167
|
+
if (!Object.prototype.hasOwnProperty.call(valueArg, index)) {
|
|
1168
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} may not contain sparse array positions.`);
|
|
1169
|
+
}
|
|
1170
|
+
const entry = valueArg[index];
|
|
1171
|
+
if (typeof entry !== 'object'
|
|
1172
|
+
|| entry === null
|
|
1173
|
+
|| Array.isArray(entry)
|
|
1174
|
+
|| plugins.nodeUtil.types.isProxy(entry)
|
|
1175
|
+
|| !isPlainObject(entry)) {
|
|
1176
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} entries must be plain filter objects.`);
|
|
1177
|
+
}
|
|
1178
|
+
assertOnlyDataProperties(entry, `${labelArg} entry`, false);
|
|
1179
|
+
}
|
|
1180
|
+
};
|
|
1181
|
+
const conditionIsEqualityAnchor = (valueArg) => {
|
|
1182
|
+
if (Array.isArray(valueArg)) {
|
|
1183
|
+
return false;
|
|
1184
|
+
}
|
|
1185
|
+
if (typeof valueArg !== 'object' || valueArg === null) {
|
|
1186
|
+
return (valueArg !== undefined
|
|
1187
|
+
&& typeof valueArg !== 'function'
|
|
1188
|
+
&& typeof valueArg !== 'symbol');
|
|
1189
|
+
}
|
|
1190
|
+
if (plugins.nodeUtil.types.isProxy(valueArg)) {
|
|
1191
|
+
throw new SmartdataPersistenceError('invalid_argument', `${operationLabelArg} filters may not contain Proxy values.`);
|
|
1192
|
+
}
|
|
1193
|
+
if (isAtomicMongoScalar(valueArg)) {
|
|
1194
|
+
return true;
|
|
1195
|
+
}
|
|
1196
|
+
if (!isPlainObject(valueArg)) {
|
|
1197
|
+
return false;
|
|
1198
|
+
}
|
|
1199
|
+
assertOnlyDataProperties(valueArg, `${operationLabelArg} filter condition`, false);
|
|
1200
|
+
const entries = Object.entries(valueArg);
|
|
1201
|
+
if (entries.length !== 1 || entries[0][0] !== '$eq') {
|
|
1202
|
+
return false;
|
|
1203
|
+
}
|
|
1204
|
+
const operand = entries[0][1];
|
|
1205
|
+
if (Array.isArray(operand)) {
|
|
1206
|
+
return false;
|
|
1207
|
+
}
|
|
1208
|
+
if (typeof operand !== 'object' || operand === null) {
|
|
1209
|
+
return (operand !== undefined
|
|
1210
|
+
&& typeof operand !== 'function'
|
|
1211
|
+
&& typeof operand !== 'symbol');
|
|
1212
|
+
}
|
|
1213
|
+
if (plugins.nodeUtil.types.isProxy(operand)) {
|
|
1214
|
+
throw new SmartdataPersistenceError('invalid_argument', `${operationLabelArg} filters may not contain Proxy values.`);
|
|
1215
|
+
}
|
|
1216
|
+
return isAtomicMongoScalar(operand);
|
|
1217
|
+
};
|
|
1218
|
+
const filterHasEqualityAnchor = (filterObjectArg) => {
|
|
1219
|
+
for (const [key, value] of Object.entries(filterObjectArg)) {
|
|
1220
|
+
if (key === '$and' && Array.isArray(value)) {
|
|
1221
|
+
requireInertLogicalFilterArray(value, '$and');
|
|
1222
|
+
if (value.some((entryArg) => isPlainObject(entryArg) &&
|
|
1223
|
+
filterHasEqualityAnchor(entryArg))) {
|
|
1224
|
+
return true;
|
|
1225
|
+
}
|
|
1226
|
+
continue;
|
|
1227
|
+
}
|
|
1228
|
+
if (key === '$or' && Array.isArray(value)) {
|
|
1229
|
+
requireInertLogicalFilterArray(value, '$or');
|
|
1230
|
+
if (value.length > 0 &&
|
|
1231
|
+
value.every((entryArg) => isPlainObject(entryArg) &&
|
|
1232
|
+
filterHasEqualityAnchor(entryArg))) {
|
|
1233
|
+
return true;
|
|
1234
|
+
}
|
|
1235
|
+
continue;
|
|
1236
|
+
}
|
|
1237
|
+
if (!key.startsWith('$') && conditionIsEqualityAnchor(value)) {
|
|
1238
|
+
return true;
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
return false;
|
|
1242
|
+
};
|
|
1243
|
+
if (!filterHasEqualityAnchor(filterArg)) {
|
|
1244
|
+
throw new SmartdataPersistenceError('invalid_argument', `${operationLabelArg} filters require at least one top-level equality anchor.`);
|
|
1245
|
+
}
|
|
1246
|
+
const collectEqualityAnchoredKeys = (filterObjectArg, anchoredKeysArg) => {
|
|
1247
|
+
for (const [key, value] of Object.entries(filterObjectArg)) {
|
|
1248
|
+
if (key === '$and' && Array.isArray(value)) {
|
|
1249
|
+
requireInertLogicalFilterArray(value, '$and');
|
|
1250
|
+
for (const entryArg of value) {
|
|
1251
|
+
if (isPlainObject(entryArg)) {
|
|
1252
|
+
collectEqualityAnchoredKeys(entryArg, anchoredKeysArg);
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
continue;
|
|
1256
|
+
}
|
|
1257
|
+
// $or branches are deliberately excluded: an equality inside one $or
|
|
1258
|
+
// branch does not globally constrain the matched document.
|
|
1259
|
+
if (!key.startsWith('$') && conditionIsEqualityAnchor(value)) {
|
|
1260
|
+
anchoredKeysArg.add(key);
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
};
|
|
1264
|
+
if (globallyConstrainingKeySetsArg) {
|
|
1265
|
+
const anchoredKeys = new Set();
|
|
1266
|
+
collectEqualityAnchoredKeys(filterArg, anchoredKeys);
|
|
1267
|
+
const filterIsGloballyConstraining = globallyConstrainingKeySetsArg.some((keySetArg) => keySetArg.size > 0 &&
|
|
1268
|
+
[...keySetArg].every((keyArg) => anchoredKeys.has(keyArg)));
|
|
1269
|
+
if (!filterIsGloballyConstraining) {
|
|
1270
|
+
throw new SmartdataPersistenceError('invalid_argument', `${operationLabelArg} filters require equality anchors that fully pin an identity field or a declared unqualified unique index.`);
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
const normalizeFilterObject = (filterObjectArg, rootArg = false) => {
|
|
1274
|
+
assertOnlyDataProperties(filterObjectArg, `${operationLabelArg} filter`, false);
|
|
1275
|
+
const normalized = {};
|
|
1276
|
+
for (const [key, value] of Object.entries(filterObjectArg)) {
|
|
1277
|
+
if (key === '$and' || key === '$or' || key === '$nor') {
|
|
1278
|
+
requireInertLogicalFilterArray(value, key);
|
|
1279
|
+
normalized[key] = value.map((entry) => {
|
|
1280
|
+
if (Object.keys(entry).length === 0) {
|
|
1281
|
+
throw new SmartdataPersistenceError('invalid_argument', `${key} entries must be non-empty filter objects.`);
|
|
1282
|
+
}
|
|
1283
|
+
return normalizeFilterObject(entry, false);
|
|
1284
|
+
});
|
|
1285
|
+
continue;
|
|
1286
|
+
}
|
|
1287
|
+
if (key === '$expr') {
|
|
1288
|
+
if (!rootArg) {
|
|
1289
|
+
throw new SmartdataPersistenceError('invalid_argument', `${operationLabelArg} permits $expr only at the root of the filter.`);
|
|
1290
|
+
}
|
|
1291
|
+
normalized[key] = normalizeAtomicNumericExpression(value, declaredRootsArg, numericRootsArg, serializedRootsArg, operationLabelArg);
|
|
1292
|
+
continue;
|
|
1293
|
+
}
|
|
1294
|
+
const root = requireDeclaredPath(key, declaredRootsArg, `${operationLabelArg} filter`, declaredNestedPathsArg);
|
|
1295
|
+
if (serializedRootsArg.has(root)) {
|
|
1296
|
+
throw new SmartdataPersistenceError('unsupported_operation', `${operationLabelArg} filters cannot target serialized field "${key}".`);
|
|
1297
|
+
}
|
|
1298
|
+
if (identityValueTypesArg.has(root) && key !== root) {
|
|
1299
|
+
throw new SmartdataPersistenceError('invalid_argument', `${operationLabelArg} filters cannot target a nested path below immutable @unI() field "${root}".`);
|
|
1300
|
+
}
|
|
1301
|
+
normalized[key] = normalizeAtomicFilterCondition(value, `${operationLabelArg} filter path "${key}"`, identityValueTypesArg.get(root));
|
|
1302
|
+
}
|
|
1303
|
+
return normalized;
|
|
1304
|
+
};
|
|
1305
|
+
return normalizeFilterObject(filterArg, true);
|
|
1306
|
+
};
|
|
1307
|
+
const pathsConflict = (leftArg, rightArg) => leftArg === rightArg ||
|
|
1308
|
+
leftArg.startsWith(`${rightArg}.`) ||
|
|
1309
|
+
rightArg.startsWith(`${leftArg}.`);
|
|
1310
|
+
const normalizeAtomicUpdate = (updateArg, declaredRootsArg, declaredNestedPathsArg, uniqueRootsArg, serializedRootsArg) => {
|
|
1311
|
+
if (typeof updateArg !== 'object' ||
|
|
1312
|
+
updateArg === null ||
|
|
1313
|
+
Array.isArray(updateArg)) {
|
|
1314
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Atomic update must be an update object.');
|
|
1315
|
+
}
|
|
1316
|
+
const allowedOperators = new Set([
|
|
1317
|
+
'$set',
|
|
1318
|
+
'$unset',
|
|
1319
|
+
'$inc',
|
|
1320
|
+
'$setOnInsert',
|
|
1321
|
+
'$push',
|
|
1322
|
+
'$addToSet',
|
|
1323
|
+
'$pull',
|
|
1324
|
+
]);
|
|
1325
|
+
const arrayOperators = new Set(['$push', '$addToSet', '$pull']);
|
|
1326
|
+
for (const operator of Object.keys(updateArg)) {
|
|
1327
|
+
if (!allowedOperators.has(operator)) {
|
|
1328
|
+
throw new SmartdataPersistenceError('invalid_argument', `Atomic update operator "${operator}" is not supported.`);
|
|
1329
|
+
}
|
|
1330
|
+
}
|
|
1331
|
+
const normalized = {};
|
|
1332
|
+
const occupiedPaths = [];
|
|
1333
|
+
for (const operator of allowedOperators) {
|
|
1334
|
+
const operation = updateArg[operator];
|
|
1335
|
+
if (operation === undefined) {
|
|
1336
|
+
continue;
|
|
1337
|
+
}
|
|
1338
|
+
if (!isPlainObject(operation)) {
|
|
1339
|
+
throw new SmartdataPersistenceError('invalid_argument', `${operator} must be a plain object.`);
|
|
1340
|
+
}
|
|
1341
|
+
const entries = Object.entries(operation);
|
|
1342
|
+
if (entries.length === 0) {
|
|
1343
|
+
continue;
|
|
1344
|
+
}
|
|
1345
|
+
const normalizedOperation = {};
|
|
1346
|
+
for (const [path, value] of entries) {
|
|
1347
|
+
const root = requireDeclaredPath(path, declaredRootsArg, operator, declaredNestedPathsArg);
|
|
1348
|
+
if (serializedRootsArg.has(root)) {
|
|
1349
|
+
throw new SmartdataPersistenceError('unsupported_operation', `${operator} cannot target serialized field "${path}".`);
|
|
1350
|
+
}
|
|
1351
|
+
if (uniqueRootsArg.has(root)) {
|
|
1352
|
+
throw new SmartdataPersistenceError('invalid_argument', `${operator} may not modify immutable @unI() field "${root}".`);
|
|
1353
|
+
}
|
|
1354
|
+
const conflict = occupiedPaths.find((occupiedPath) => pathsConflict(path, occupiedPath.path));
|
|
1355
|
+
if (conflict) {
|
|
1356
|
+
throw new SmartdataPersistenceError('invalid_argument', `${operator} path "${path}" conflicts with ${conflict.operator} path "${conflict.path}".`);
|
|
1357
|
+
}
|
|
1358
|
+
occupiedPaths.push({ path, operator });
|
|
1359
|
+
if (arrayOperators.has(operator)) {
|
|
1360
|
+
if (path !== root) {
|
|
1361
|
+
throw new SmartdataPersistenceError('invalid_argument', `${operator} may only target declared top-level array fields; "${path}" is a nested path.`);
|
|
1362
|
+
}
|
|
1363
|
+
if (value === undefined) {
|
|
1364
|
+
throw new SmartdataPersistenceError('invalid_argument', `${operator} path "${path}" may not be undefined.`);
|
|
1365
|
+
}
|
|
1366
|
+
if (operator === '$pull') {
|
|
1367
|
+
if (value === null
|
|
1368
|
+
|| typeof value === 'string'
|
|
1369
|
+
|| typeof value === 'boolean'
|
|
1370
|
+
|| (typeof value === 'number' && Number.isFinite(value))) {
|
|
1371
|
+
normalizedOperation[path] = value;
|
|
1372
|
+
continue;
|
|
1373
|
+
}
|
|
1374
|
+
if (typeof value !== 'object'
|
|
1375
|
+
|| Array.isArray(value)
|
|
1376
|
+
|| isPlainObject(value)
|
|
1377
|
+
|| value instanceof RegExp) {
|
|
1378
|
+
throw new SmartdataPersistenceError('invalid_argument', `$pull path "${path}" must use a scalar equality operand.`);
|
|
1379
|
+
}
|
|
1380
|
+
// Scalar BSON objects are stored as inert snapshots so a custom
|
|
1381
|
+
// toBSON encoder can never rewrite the equality operand into an
|
|
1382
|
+
// operator document at serialization time.
|
|
1383
|
+
normalizedOperation[path] = createInertAtomicBsonScalarSnapshot(value, `$pull path "${path}"`);
|
|
1384
|
+
continue;
|
|
1385
|
+
}
|
|
1386
|
+
if (typeof value === 'object'
|
|
1387
|
+
&& value !== null
|
|
1388
|
+
&& !Array.isArray(value)
|
|
1389
|
+
&& !isPlainObject(value)) {
|
|
1390
|
+
// Non-plain element objects (dates, binary views, BSON scalars)
|
|
1391
|
+
// must be inert: a custom toBSON encoder could otherwise smuggle a
|
|
1392
|
+
// modifier document such as $each past validation.
|
|
1393
|
+
normalizedOperation[path] = createInertAtomicBsonScalarSnapshot(value, `${operator} path "${path}"`);
|
|
1394
|
+
continue;
|
|
1395
|
+
}
|
|
1396
|
+
assertSafePersistedValue(value, `${operator} path "${path}"`);
|
|
1397
|
+
normalizedOperation[path] = stripUndefinedValues(value);
|
|
1398
|
+
continue;
|
|
1399
|
+
}
|
|
1400
|
+
if (operator === '$unset') {
|
|
1401
|
+
if (value !== '' && value !== true && value !== 1) {
|
|
1402
|
+
throw new SmartdataPersistenceError('invalid_argument', `$unset path "${path}" must use "", true, or 1.`);
|
|
1403
|
+
}
|
|
1404
|
+
normalizedOperation[path] = '';
|
|
1405
|
+
continue;
|
|
1406
|
+
}
|
|
1407
|
+
if (value === undefined) {
|
|
1408
|
+
throw new SmartdataPersistenceError('invalid_argument', `${operator} path "${path}" may not be undefined.`);
|
|
1409
|
+
}
|
|
1410
|
+
if (operator === '$inc' &&
|
|
1411
|
+
(typeof value !== 'number' || !Number.isFinite(value))) {
|
|
1412
|
+
throw new SmartdataPersistenceError('invalid_argument', `$inc path "${path}" must be a finite number.`);
|
|
1413
|
+
}
|
|
1414
|
+
if (operator !== '$inc') {
|
|
1415
|
+
assertSafePersistedValue(value, `${operator} path "${path}"`);
|
|
1416
|
+
}
|
|
1417
|
+
normalizedOperation[path] =
|
|
1418
|
+
operator === '$inc' ? value : stripUndefinedValues(value);
|
|
1419
|
+
}
|
|
1420
|
+
normalized[operator] = normalizedOperation;
|
|
1421
|
+
}
|
|
1422
|
+
if (Object.keys(normalized).length === 0) {
|
|
1423
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Atomic update must contain at least one non-empty operation.');
|
|
1424
|
+
}
|
|
1425
|
+
return normalized;
|
|
1426
|
+
};
|
|
1427
|
+
const normalizeProjection = (projectionArg, declaredRootsArg, declaredNestedPathsArg) => {
|
|
1428
|
+
if (projectionArg === undefined) {
|
|
1429
|
+
return undefined;
|
|
1430
|
+
}
|
|
1431
|
+
if (!isPlainObject(projectionArg) || Object.keys(projectionArg).length === 0) {
|
|
1432
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Projection must be a non-empty plain object.');
|
|
1433
|
+
}
|
|
1434
|
+
let inclusionMode;
|
|
1435
|
+
const normalized = {};
|
|
1436
|
+
for (const [path, value] of Object.entries(projectionArg)) {
|
|
1437
|
+
if (path !== '_id') {
|
|
1438
|
+
requireDeclaredPath(path, declaredRootsArg, 'Projection', declaredNestedPathsArg);
|
|
1439
|
+
if (inclusionMode === undefined) {
|
|
1440
|
+
inclusionMode = value;
|
|
1441
|
+
}
|
|
1442
|
+
else if (inclusionMode !== value) {
|
|
1443
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Projection may not mix included and excluded fields except for _id.');
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
if (value !== 0 && value !== 1) {
|
|
1447
|
+
throw new SmartdataPersistenceError('invalid_argument', `Projection path "${path}" must use 0 or 1.`);
|
|
1448
|
+
}
|
|
1449
|
+
normalized[path] = value;
|
|
1450
|
+
}
|
|
1451
|
+
return normalized;
|
|
1452
|
+
};
|
|
1453
|
+
const normalizeSort = (sortArg, declaredRootsArg, declaredNestedPathsArg) => {
|
|
1454
|
+
if (sortArg === undefined) {
|
|
1455
|
+
return undefined;
|
|
1456
|
+
}
|
|
1457
|
+
if (!isPlainObject(sortArg) || Object.keys(sortArg).length === 0) {
|
|
1458
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Sort must be a non-empty ordered object.');
|
|
1459
|
+
}
|
|
1460
|
+
const normalized = {};
|
|
1461
|
+
for (const [path, direction] of Object.entries(sortArg)) {
|
|
1462
|
+
if (path !== '_id') {
|
|
1463
|
+
requireDeclaredPath(path, declaredRootsArg, 'Sort', declaredNestedPathsArg);
|
|
1464
|
+
}
|
|
1465
|
+
if (direction !== 1 && direction !== -1) {
|
|
1466
|
+
throw new SmartdataPersistenceError('invalid_argument', `Sort path "${path}" must use 1 or -1.`);
|
|
1467
|
+
}
|
|
1468
|
+
normalized[path] = direction;
|
|
1469
|
+
}
|
|
1470
|
+
return normalized;
|
|
1471
|
+
};
|
|
1472
|
+
const normalizeQueryHint = (hintArg, modelArg) => {
|
|
1473
|
+
if (hintArg === undefined) {
|
|
1474
|
+
return undefined;
|
|
1475
|
+
}
|
|
1476
|
+
if (typeof hintArg !== 'string' ||
|
|
1477
|
+
!getExpectedCollectionTopologyForModel(modelArg).indexes.some((indexArg) => indexArg.name === hintArg)) {
|
|
1478
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Query hint must name an index declared by this model or the built-in _id_ index.');
|
|
1479
|
+
}
|
|
1480
|
+
return hintArg;
|
|
1481
|
+
};
|
|
1482
|
+
export const convertFilterForMongoDb = (filterArg) => {
|
|
1483
|
+
// SECURITY: Block $where to prevent server-side JS execution
|
|
1484
|
+
if (filterArg.$where !== undefined) {
|
|
1485
|
+
throw new Error('$where operator is not allowed for security reasons');
|
|
1486
|
+
}
|
|
1487
|
+
// Handle logical operators recursively
|
|
1488
|
+
const logicalOperators = ['$and', '$or', '$nor', '$not'];
|
|
1489
|
+
const processedFilter = {};
|
|
1490
|
+
for (const key of Object.keys(filterArg)) {
|
|
1491
|
+
if (logicalOperators.includes(key)) {
|
|
1492
|
+
if (key === '$not') {
|
|
1493
|
+
processedFilter[key] = convertFilterForMongoDb(filterArg[key]);
|
|
1494
|
+
}
|
|
1495
|
+
else if (Array.isArray(filterArg[key])) {
|
|
1496
|
+
processedFilter[key] = filterArg[key].map((subFilter) => convertFilterForMongoDb(subFilter));
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
// If only logical operators, return them
|
|
1501
|
+
const hasOnlyLogicalOperators = Object.keys(filterArg).every(key => logicalOperators.includes(key));
|
|
1502
|
+
if (hasOnlyLogicalOperators) {
|
|
1503
|
+
return processedFilter;
|
|
1504
|
+
}
|
|
1505
|
+
// Original conversion logic for non-MongoDB query objects
|
|
1506
|
+
const convertedFilter = {};
|
|
1507
|
+
// Helper to merge operator objects
|
|
1508
|
+
const mergeIntoConverted = (path, value) => {
|
|
1509
|
+
const existing = convertedFilter[path];
|
|
1510
|
+
if (!existing) {
|
|
1511
|
+
convertedFilter[path] = value;
|
|
1512
|
+
}
|
|
1513
|
+
else if (typeof existing === 'object' && !Array.isArray(existing) &&
|
|
1514
|
+
typeof value === 'object' && !Array.isArray(value) &&
|
|
1515
|
+
(Object.keys(existing).some(k => k.startsWith('$')) || Object.keys(value).some(k => k.startsWith('$')))) {
|
|
1516
|
+
// Both have operators, merge them
|
|
1517
|
+
convertedFilter[path] = { ...existing, ...value };
|
|
1518
|
+
}
|
|
1519
|
+
else {
|
|
1520
|
+
// Otherwise later wins
|
|
1521
|
+
convertedFilter[path] = value;
|
|
1522
|
+
}
|
|
1523
|
+
};
|
|
1524
|
+
const isAtomicMongoValue = (valueArg) => {
|
|
1525
|
+
if (valueArg instanceof Date || valueArg instanceof RegExp) {
|
|
1526
|
+
return true;
|
|
1527
|
+
}
|
|
1528
|
+
if (ArrayBuffer.isView(valueArg)) {
|
|
1529
|
+
return true;
|
|
1530
|
+
}
|
|
1531
|
+
return (typeof valueArg === 'object' &&
|
|
1532
|
+
valueArg !== null &&
|
|
1533
|
+
typeof valueArg._bsontype === 'string');
|
|
1534
|
+
};
|
|
1535
|
+
const convertFilterArgument = (keyPathArg2, filterArg2) => {
|
|
1536
|
+
if (Array.isArray(filterArg2)) {
|
|
1537
|
+
// Arrays are typically used as values for operators like $in or as direct equality matches
|
|
1538
|
+
mergeIntoConverted(keyPathArg2, filterArg2);
|
|
1539
|
+
return;
|
|
1540
|
+
}
|
|
1541
|
+
else if (isAtomicMongoValue(filterArg2)) {
|
|
1542
|
+
// BSON values, dates, regexes, and binary views are scalar query values.
|
|
1543
|
+
// Recursing into them can silently turn an _id filter into an empty filter.
|
|
1544
|
+
mergeIntoConverted(keyPathArg2, filterArg2);
|
|
1545
|
+
return;
|
|
1546
|
+
}
|
|
1547
|
+
else if (typeof filterArg2 === 'object' && filterArg2 !== null) {
|
|
1548
|
+
// Check if this is an object with MongoDB operators
|
|
1549
|
+
const keys = Object.keys(filterArg2);
|
|
1550
|
+
const hasOperators = keys.some(key => key.startsWith('$'));
|
|
1551
|
+
if (hasOperators) {
|
|
1552
|
+
// This object contains MongoDB operators
|
|
1553
|
+
// Validate and pass through allowed operators
|
|
1554
|
+
const allowedOperators = [
|
|
1555
|
+
// Comparison operators
|
|
1556
|
+
'$eq', '$ne', '$gt', '$gte', '$lt', '$lte',
|
|
1557
|
+
// Array operators
|
|
1558
|
+
'$in', '$nin', '$all', '$elemMatch', '$size',
|
|
1559
|
+
// Element operators
|
|
1560
|
+
'$exists', '$type',
|
|
1561
|
+
// Evaluation operators (safe ones only)
|
|
1562
|
+
'$regex', '$options', '$text', '$mod',
|
|
1563
|
+
// Logical operators (nested)
|
|
1564
|
+
'$and', '$or', '$nor', '$not'
|
|
1565
|
+
];
|
|
1566
|
+
// Check for dangerous operators
|
|
1567
|
+
if (keys.includes('$where')) {
|
|
1568
|
+
throw new Error('$where operator is not allowed for security reasons');
|
|
1569
|
+
}
|
|
1570
|
+
// Validate all operators are in the allowed list
|
|
1571
|
+
const invalidOperators = keys.filter(key => key.startsWith('$') && !allowedOperators.includes(key));
|
|
1572
|
+
if (invalidOperators.length > 0) {
|
|
1573
|
+
console.warn(`Warning: Unknown MongoDB operators detected: ${invalidOperators.join(', ')}`);
|
|
1574
|
+
}
|
|
1575
|
+
// For array operators, ensure the values are appropriate
|
|
1576
|
+
if (filterArg2.$in && !Array.isArray(filterArg2.$in)) {
|
|
1577
|
+
throw new Error('$in operator requires an array value');
|
|
1578
|
+
}
|
|
1579
|
+
if (filterArg2.$nin && !Array.isArray(filterArg2.$nin)) {
|
|
1580
|
+
throw new Error('$nin operator requires an array value');
|
|
1581
|
+
}
|
|
1582
|
+
if (filterArg2.$all && !Array.isArray(filterArg2.$all)) {
|
|
1583
|
+
throw new Error('$all operator requires an array value');
|
|
1584
|
+
}
|
|
1585
|
+
if (filterArg2.$size && typeof filterArg2.$size !== 'number') {
|
|
1586
|
+
throw new Error('$size operator requires a numeric value');
|
|
1587
|
+
}
|
|
1588
|
+
// Use merge helper to handle duplicate paths
|
|
1589
|
+
mergeIntoConverted(keyPathArg2, filterArg2);
|
|
1590
|
+
return;
|
|
1591
|
+
}
|
|
1592
|
+
// No operators, check for dots in keys
|
|
1593
|
+
for (const key of keys) {
|
|
1594
|
+
if (key.includes('.')) {
|
|
1595
|
+
throw new Error('keys cannot contain dots');
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
// Recursively process nested objects
|
|
1599
|
+
for (const key of keys) {
|
|
1600
|
+
convertFilterArgument(`${keyPathArg2}.${key}`, filterArg2[key]);
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
else {
|
|
1604
|
+
// Primitive values
|
|
1605
|
+
mergeIntoConverted(keyPathArg2, filterArg2);
|
|
1606
|
+
}
|
|
1607
|
+
};
|
|
1608
|
+
for (const key of Object.keys(filterArg)) {
|
|
1609
|
+
// Skip logical operators, they were already processed
|
|
1610
|
+
if (!logicalOperators.includes(key)) {
|
|
1611
|
+
convertFilterArgument(key, filterArg[key]);
|
|
1612
|
+
}
|
|
1613
|
+
}
|
|
1614
|
+
// Add back processed logical operators
|
|
1615
|
+
Object.assign(convertedFilter, processedFilter);
|
|
1616
|
+
return convertedFilter;
|
|
1617
|
+
};
|
|
1618
|
+
let SmartDataDbDoc = (() => {
|
|
1619
|
+
let __createdAt_decorators;
|
|
1620
|
+
let __createdAt_initializers = [];
|
|
1621
|
+
let __createdAt_extraInitializers = [];
|
|
1622
|
+
let __updatedAt_decorators;
|
|
1623
|
+
let __updatedAt_initializers = [];
|
|
1624
|
+
let __updatedAt_extraInitializers = [];
|
|
1625
|
+
return class SmartDataDbDoc {
|
|
1626
|
+
static {
|
|
1627
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
1628
|
+
__createdAt_decorators = [globalSvDb()];
|
|
1629
|
+
__updatedAt_decorators = [globalSvDb()];
|
|
1630
|
+
__esDecorate(null, null, __createdAt_decorators, { kind: "field", name: "_createdAt", static: false, private: false, access: { has: obj => "_createdAt" in obj, get: obj => obj._createdAt, set: (obj, value) => { obj._createdAt = value; } }, metadata: _metadata }, __createdAt_initializers, __createdAt_extraInitializers);
|
|
1631
|
+
__esDecorate(null, null, __updatedAt_decorators, { kind: "field", name: "_updatedAt", static: false, private: false, access: { has: obj => "_updatedAt" in obj, get: obj => obj._updatedAt, set: (obj, value) => { obj._updatedAt = value; } }, metadata: _metadata }, __updatedAt_initializers, __updatedAt_extraInitializers);
|
|
1632
|
+
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
1633
|
+
}
|
|
1634
|
+
/**
|
|
1635
|
+
* the collection object an Doc belongs to
|
|
1636
|
+
*/
|
|
1637
|
+
static collection;
|
|
1638
|
+
static get exact() {
|
|
1639
|
+
throw new Error('Model is not configured for exact persistence.');
|
|
1640
|
+
}
|
|
1641
|
+
static defaultManager;
|
|
1642
|
+
static manager;
|
|
1643
|
+
/**
|
|
1644
|
+
* Helper to get collection with fallback to static for Deno compatibility
|
|
1645
|
+
*/
|
|
1646
|
+
getCollectionSafe() {
|
|
1647
|
+
return this.collection || this.constructor.collection;
|
|
1648
|
+
}
|
|
1649
|
+
// STATIC
|
|
1650
|
+
/** Insert a strict primary-only bootstrap record without separate collection/index DDL. */
|
|
1651
|
+
static async insertBootstrapRecord(dbArg, recordArg, optionsArg) {
|
|
1652
|
+
return insertBootstrapRecord(this, dbArg, recordArg, optionsArg);
|
|
1653
|
+
}
|
|
1654
|
+
/** Inspect bounded stored BSON without initializing or hydrating the model. */
|
|
1655
|
+
static async inspectStoredDocuments(dbArg, optionsArg) {
|
|
1656
|
+
return inspectStoredDocuments(this, dbArg, optionsArg);
|
|
1657
|
+
}
|
|
1658
|
+
/** Diagnose stored BSON with explicit ordinary validation evidence, without hydration. */
|
|
1659
|
+
static async inspectStoredDocumentEvidence(dbArg, optionsArg = {}) {
|
|
1660
|
+
return inspectStoredDocumentEvidence(this, dbArg, optionsArg);
|
|
1661
|
+
}
|
|
1662
|
+
static createInstanceFromMongoDbNativeDoc(mongoDbNativeDocArg) {
|
|
1663
|
+
const policy = getOrdinaryPersistencePolicy(this);
|
|
1664
|
+
if (policy) {
|
|
1665
|
+
mongoDbNativeDocArg = validateOrdinaryStoredDocument(mongoDbNativeDocArg, policy, [...this.getDeclaredPersistedRoots()]);
|
|
1666
|
+
}
|
|
1667
|
+
const newInstance = new this();
|
|
1668
|
+
if (policy) {
|
|
1669
|
+
for (const field of this.getDeclaredPersistedRoots()) {
|
|
1670
|
+
if (!Object.prototype.hasOwnProperty.call(mongoDbNativeDocArg, field)) {
|
|
1671
|
+
delete newInstance[field];
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
if (policy?.timestamps === 'none') {
|
|
1676
|
+
delete newInstance['_createdAt'];
|
|
1677
|
+
delete newInstance['_updatedAt'];
|
|
1678
|
+
}
|
|
1679
|
+
newInstance.creationStatus = 'db';
|
|
1680
|
+
for (const key of Object.keys(mongoDbNativeDocArg)) {
|
|
1681
|
+
const rawValue = mongoDbNativeDocArg[key];
|
|
1682
|
+
const optionsMap = this._svDbOptions || {};
|
|
1683
|
+
const opts = optionsMap[key];
|
|
1684
|
+
newInstance[key] = opts && typeof opts.deserialize === 'function'
|
|
1685
|
+
? opts.deserialize(rawValue)
|
|
1686
|
+
: rawValue;
|
|
1687
|
+
}
|
|
1688
|
+
return newInstance;
|
|
1689
|
+
}
|
|
1690
|
+
static getDeclaredPersistedRoots() {
|
|
1691
|
+
const prototype = this.prototype;
|
|
1692
|
+
const roots = new Set([
|
|
1693
|
+
...(prototype.globalSaveableProperties || []),
|
|
1694
|
+
...(prototype.saveableProperties || []),
|
|
1695
|
+
]);
|
|
1696
|
+
if (getOrdinaryPersistencePolicy(this)?.idType === 'string') {
|
|
1697
|
+
roots.add('_id');
|
|
1698
|
+
stringIdRootSets.add(roots);
|
|
1699
|
+
}
|
|
1700
|
+
return roots;
|
|
1701
|
+
}
|
|
1702
|
+
static getDeclaredUniqueRoots() {
|
|
1703
|
+
const prototype = this.prototype;
|
|
1704
|
+
return new Set([
|
|
1705
|
+
...(prototype.uniqueIndexes || []),
|
|
1706
|
+
...(getOrdinaryPersistencePolicy(this)?.idType === 'string' ? ['_id'] : []),
|
|
1707
|
+
]);
|
|
1708
|
+
}
|
|
1709
|
+
static getDeclaredIdentityValueTypes() {
|
|
1710
|
+
const prototype = this.prototype;
|
|
1711
|
+
return new Map([...this.getDeclaredUniqueRoots()].map((identityFieldArg) => [
|
|
1712
|
+
identityFieldArg,
|
|
1713
|
+
prototype.identityValueTypes?.[identityFieldArg] ?? 'string',
|
|
1714
|
+
]));
|
|
1715
|
+
}
|
|
1716
|
+
static getDeclaredNumericRoots() {
|
|
1717
|
+
const collection = this.collection;
|
|
1718
|
+
return new Set(collection.getBoundModelSchema()?.numericFields || []);
|
|
1719
|
+
}
|
|
1720
|
+
/**
|
|
1721
|
+
* Returns every equality key set that globally constrains a single document
|
|
1722
|
+
* of this model: each declared identity field on its own, plus the full key
|
|
1723
|
+
* set of every declared unqualified unique index. Unique indexes that carry
|
|
1724
|
+
* any option beyond `unique` (sparse, partial, or otherwise uninterpretable)
|
|
1725
|
+
* or a non-numeric key direction do not qualify — such indexes do not
|
|
1726
|
+
* guarantee at most one matching document for an equality filter.
|
|
1727
|
+
*/
|
|
1728
|
+
static getGloballyConstrainingKeySets() {
|
|
1729
|
+
const keySets = [];
|
|
1730
|
+
for (const identityField of this.getDeclaredUniqueRoots()) {
|
|
1731
|
+
keySets.push(new Set([identityField]));
|
|
1732
|
+
}
|
|
1733
|
+
const collection = this.collection;
|
|
1734
|
+
const modelSchema = collection.getBoundModelSchema();
|
|
1735
|
+
if (modelSchema) {
|
|
1736
|
+
for (const index of modelSchema.indexes) {
|
|
1737
|
+
if (index.options.unique !== true) {
|
|
1738
|
+
continue;
|
|
1739
|
+
}
|
|
1740
|
+
const hasUnqualifiedOptions = Object.keys(index.options).every((optionKeyArg) => optionKeyArg === 'unique' || optionKeyArg === 'background');
|
|
1741
|
+
if (!hasUnqualifiedOptions) {
|
|
1742
|
+
continue;
|
|
1743
|
+
}
|
|
1744
|
+
if (index.key.length === 0 ||
|
|
1745
|
+
index.key.some(([, directionArg]) => directionArg !== 1 && directionArg !== -1)) {
|
|
1746
|
+
continue;
|
|
1747
|
+
}
|
|
1748
|
+
keySets.push(new Set(index.key.map(([fieldArg]) => fieldArg)));
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1751
|
+
return keySets;
|
|
1752
|
+
}
|
|
1753
|
+
static getDeclaredAtomicPaths() {
|
|
1754
|
+
const declaredRoots = this.getDeclaredPersistedRoots();
|
|
1755
|
+
const uniqueRoots = this.getDeclaredUniqueRoots();
|
|
1756
|
+
const options = this._svDbOptions;
|
|
1757
|
+
const atomicPaths = new Set();
|
|
1758
|
+
for (const [root, fieldOptions] of Object.entries(options || {})) {
|
|
1759
|
+
if (fieldOptions.atomicPaths === undefined) {
|
|
1760
|
+
continue;
|
|
1761
|
+
}
|
|
1762
|
+
if (!Array.isArray(fieldOptions.atomicPaths)) {
|
|
1763
|
+
throw new SmartdataPersistenceError('invalid_configuration', `Atomic paths for persisted field "${root}" must be an array.`);
|
|
1764
|
+
}
|
|
1765
|
+
if (typeof fieldOptions.serialize === 'function'
|
|
1766
|
+
|| typeof fieldOptions.deserialize === 'function') {
|
|
1767
|
+
throw new SmartdataPersistenceError('invalid_configuration', `Serialized persisted field "${root}" may not declare atomic nested paths.`);
|
|
1768
|
+
}
|
|
1769
|
+
if (uniqueRoots.has(root)) {
|
|
1770
|
+
throw new SmartdataPersistenceError('invalid_configuration', `Immutable @unI() field "${root}" may not declare atomic nested paths.`);
|
|
1771
|
+
}
|
|
1772
|
+
for (const relativePath of fieldOptions.atomicPaths) {
|
|
1773
|
+
if (typeof relativePath !== 'string' || relativePath.length === 0) {
|
|
1774
|
+
throw new SmartdataPersistenceError('invalid_configuration', `Atomic paths for persisted field "${root}" must be non-empty strings.`);
|
|
1775
|
+
}
|
|
1776
|
+
const fullPath = `${root}.${relativePath}`;
|
|
1777
|
+
try {
|
|
1778
|
+
requireDeclaredPath(fullPath, declaredRoots, 'Atomic path declaration', new Set([fullPath]));
|
|
1779
|
+
}
|
|
1780
|
+
catch (errorArg) {
|
|
1781
|
+
throw new SmartdataPersistenceError('invalid_configuration', `Atomic path declaration "${fullPath}" is invalid.`, { cause: errorArg });
|
|
1782
|
+
}
|
|
1783
|
+
atomicPaths.add(fullPath);
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
return atomicPaths;
|
|
1787
|
+
}
|
|
1788
|
+
static getSerializedPersistedRoots() {
|
|
1789
|
+
const options = this._svDbOptions;
|
|
1790
|
+
return new Set(Object.entries(options || {})
|
|
1791
|
+
.filter(([, fieldOptions]) => typeof fieldOptions.serialize === 'function' ||
|
|
1792
|
+
typeof fieldOptions.deserialize === 'function')
|
|
1793
|
+
.map(([field]) => field));
|
|
1794
|
+
}
|
|
1795
|
+
static getDeclaredQueryPaths() {
|
|
1796
|
+
return new Set([
|
|
1797
|
+
...this.getDeclaredAtomicPaths(),
|
|
1798
|
+
...getExpectedCollectionTopologyForModel(this).indexes.flatMap((indexArg) => indexArg.keys.map((keyArg) => keyArg.path)),
|
|
1799
|
+
]);
|
|
1800
|
+
}
|
|
1801
|
+
static assertHydratedProjection(projectionArg, modifierArg) {
|
|
1802
|
+
if (getOrdinaryPersistencePolicy(this) && (projectionArg !== undefined || modifierArg !== undefined)) {
|
|
1803
|
+
throw new SmartdataPersistenceError('unsupported_operation', 'Whole-stored-document validation requires an unprojected read without native modifiers.');
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
/**
|
|
1807
|
+
* Initializes the model collection and all model-owned indexes. Failed
|
|
1808
|
+
* initialization is retryable after the underlying conflict is repaired.
|
|
1809
|
+
*/
|
|
1810
|
+
static async init() {
|
|
1811
|
+
const collection = this.collection;
|
|
1812
|
+
await collection.init();
|
|
1813
|
+
}
|
|
1814
|
+
static async ensureInitialized() {
|
|
1815
|
+
await this.init();
|
|
1816
|
+
}
|
|
1817
|
+
/** Verify or install the model's exact topology within one explicit deadline. */
|
|
1818
|
+
static async prepareCollection(opts) {
|
|
1819
|
+
validateCollectionPreparationOptions(opts);
|
|
1820
|
+
const collection = this.collection;
|
|
1821
|
+
await collection.prepareCollection(opts);
|
|
1822
|
+
}
|
|
1823
|
+
/**
|
|
1824
|
+
* Returns a sanitized view of the indexes installed for this model.
|
|
1825
|
+
*/
|
|
1826
|
+
static async getIndexInfo() {
|
|
1827
|
+
const collection = this.collection;
|
|
1828
|
+
return collection.getIndexInfo();
|
|
1829
|
+
}
|
|
1830
|
+
/**
|
|
1831
|
+
* Returns the model's immutable collection and index contract without
|
|
1832
|
+
* resolving a manager, database, or SmartdataCollection.
|
|
1833
|
+
*/
|
|
1834
|
+
static getExpectedCollectionTopology() {
|
|
1835
|
+
return getExpectedCollectionTopologyForModel(this);
|
|
1836
|
+
}
|
|
1837
|
+
/**
|
|
1838
|
+
* Inspects an explicitly supplied connected database without initializing or
|
|
1839
|
+
* mutating the model collection.
|
|
1840
|
+
*/
|
|
1841
|
+
static async inspectCollectionTopology(dbArg) {
|
|
1842
|
+
return inspectCollectionTopologyForModel(this, dbArg);
|
|
1843
|
+
}
|
|
1844
|
+
/**
|
|
1845
|
+
* Inserts a newly constructed ordinary model through SmartData.
|
|
1846
|
+
*/
|
|
1847
|
+
static async insert(documentArg, opts) {
|
|
1848
|
+
if (this[exactPersistencePolicySymbol]) {
|
|
1849
|
+
throw new SmartdataPersistenceError('unsupported_operation', 'Ordinary insert is unavailable for exact-persistence models.');
|
|
1850
|
+
}
|
|
1851
|
+
if (!(documentArg instanceof this)) {
|
|
1852
|
+
throw new SmartdataPersistenceError('invalid_argument', `Model insert requires an instance of "${this.name}".`);
|
|
1853
|
+
}
|
|
1854
|
+
if (documentArg.creationStatus !== 'new') {
|
|
1855
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Model insert requires a newly constructed document.');
|
|
1856
|
+
}
|
|
1857
|
+
assertUsableIdentityValues(documentArg, this.prototype.uniqueIndexes || [], this.prototype.identityValueTypes);
|
|
1858
|
+
const now = new Date().toISOString();
|
|
1859
|
+
if (getOrdinaryPersistencePolicy(this)?.timestamps !== 'none') {
|
|
1860
|
+
documentArg._createdAt = now;
|
|
1861
|
+
documentArg._updatedAt = now;
|
|
1862
|
+
}
|
|
1863
|
+
const collection = this.collection;
|
|
1864
|
+
const result = await collection.insert(documentArg, opts);
|
|
1865
|
+
if (!isOrdinarySessionInTransaction(opts?.session)) {
|
|
1866
|
+
documentArg.creationStatus = 'db';
|
|
1867
|
+
}
|
|
1868
|
+
return result;
|
|
1869
|
+
}
|
|
1870
|
+
/**
|
|
1871
|
+
* Inserts a batch of newly constructed ordinary models through SmartData.
|
|
1872
|
+
* Each document inserts atomically; the batch as a whole is not isolated
|
|
1873
|
+
* unless the caller supplies a transaction session. With ordered semantics
|
|
1874
|
+
* (the default) MongoDB stops at the first failure; documents MongoDB
|
|
1875
|
+
* reports as inserted are marked database-backed even when the batch fails
|
|
1876
|
+
* part-way, so callers can compensate precisely.
|
|
1877
|
+
*/
|
|
1878
|
+
static async insertMany(documentsArg, opts) {
|
|
1879
|
+
if (this[exactPersistencePolicySymbol]) {
|
|
1880
|
+
throw new SmartdataPersistenceError('unsupported_operation', 'Ordinary insertMany is unavailable for exact-persistence models.');
|
|
1881
|
+
}
|
|
1882
|
+
if (!Array.isArray(documentsArg) || documentsArg.length === 0) {
|
|
1883
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Model insertMany requires a non-empty array of documents.');
|
|
1884
|
+
}
|
|
1885
|
+
if (opts?.ordered !== undefined
|
|
1886
|
+
&& typeof opts.ordered !== 'boolean') {
|
|
1887
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Model insertMany ordered must be a boolean.');
|
|
1888
|
+
}
|
|
1889
|
+
const seenDocuments = new Set();
|
|
1890
|
+
for (const documentArg of documentsArg) {
|
|
1891
|
+
if (!(documentArg instanceof this)) {
|
|
1892
|
+
throw new SmartdataPersistenceError('invalid_argument', `Model insertMany requires instances of "${this.name}".`);
|
|
1893
|
+
}
|
|
1894
|
+
if (documentArg.creationStatus !== 'new') {
|
|
1895
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Model insertMany requires newly constructed documents.');
|
|
1896
|
+
}
|
|
1897
|
+
if (seenDocuments.has(documentArg)) {
|
|
1898
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Model insertMany may not contain the same document instance twice.');
|
|
1899
|
+
}
|
|
1900
|
+
seenDocuments.add(documentArg);
|
|
1901
|
+
assertUsableIdentityValues(documentArg, this.prototype.uniqueIndexes || [], this.prototype.identityValueTypes);
|
|
1902
|
+
}
|
|
1903
|
+
const now = new Date().toISOString();
|
|
1904
|
+
for (const documentArg of documentsArg) {
|
|
1905
|
+
if (getOrdinaryPersistencePolicy(this)?.timestamps !== 'none') {
|
|
1906
|
+
documentArg._createdAt = now;
|
|
1907
|
+
documentArg._updatedAt = now;
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
const collection = this.collection;
|
|
1911
|
+
const inTransaction = isOrdinarySessionInTransaction(opts?.session);
|
|
1912
|
+
const markInsertedDocuments = (insertedIdsArg) => {
|
|
1913
|
+
if (inTransaction || !insertedIdsArg) {
|
|
1914
|
+
return;
|
|
1915
|
+
}
|
|
1916
|
+
for (const indexKey of Object.keys(insertedIdsArg)) {
|
|
1917
|
+
const insertedDocument = documentsArg[Number(indexKey)];
|
|
1918
|
+
if (insertedDocument) {
|
|
1919
|
+
insertedDocument.creationStatus = 'db';
|
|
1920
|
+
}
|
|
1921
|
+
}
|
|
1922
|
+
};
|
|
1923
|
+
try {
|
|
1924
|
+
const result = await collection.insertMany(documentsArg, opts);
|
|
1925
|
+
markInsertedDocuments(result.insertedIds);
|
|
1926
|
+
return result;
|
|
1927
|
+
}
|
|
1928
|
+
catch (error) {
|
|
1929
|
+
const bulkError = error instanceof SmartdataPersistenceError
|
|
1930
|
+
? error.cause
|
|
1931
|
+
: error;
|
|
1932
|
+
if (bulkError instanceof plugins.mongodb.MongoBulkWriteError) {
|
|
1933
|
+
markInsertedDocuments(bulkError.result?.insertedIds);
|
|
1934
|
+
}
|
|
1935
|
+
throw error;
|
|
1936
|
+
}
|
|
1937
|
+
}
|
|
1938
|
+
/**
|
|
1939
|
+
* Inserts absent identities without changing existing documents, including
|
|
1940
|
+
* their timestamps. The unordered batch is bounded to 1000 documents and
|
|
1941
|
+
* 16 MiB of serialized BSON. New-model timestamps are preserved. Inputs stay
|
|
1942
|
+
* new so the same batch can be retried after an ambiguous result; read a
|
|
1943
|
+
* stored instance before updating it because an existing body may differ.
|
|
1944
|
+
*/
|
|
1945
|
+
static async insertManyIfAbsent(documentsArg, opts) {
|
|
1946
|
+
if (this[exactPersistencePolicySymbol]) {
|
|
1947
|
+
throw new SmartdataPersistenceError('unsupported_operation', 'insertManyIfAbsent is unavailable for exact-persistence models.');
|
|
1948
|
+
}
|
|
1949
|
+
if (!Array.isArray(documentsArg) || documentsArg.length < 1 || documentsArg.length > 1000) {
|
|
1950
|
+
throw new SmartdataPersistenceError('invalid_argument', 'insertManyIfAbsent requires 1 to 1000 newly constructed documents.');
|
|
1951
|
+
}
|
|
1952
|
+
const identityTypes = this.getDeclaredIdentityValueTypes();
|
|
1953
|
+
const serializedRoots = this.getSerializedPersistedRoots();
|
|
1954
|
+
const identityField = opts?.identityField;
|
|
1955
|
+
if (typeof identityField !== 'string' || !identityTypes.has(identityField) || serializedRoots.has(identityField)) {
|
|
1956
|
+
throw new SmartdataPersistenceError('invalid_argument', 'insertManyIfAbsent requires a declared, non-serialized @unI identity field.');
|
|
1957
|
+
}
|
|
1958
|
+
const timeoutMS = requireBoundedInteger(opts?.timeoutMS, 'insertManyIfAbsent timeoutMS', 120_000);
|
|
1959
|
+
const identities = new Set();
|
|
1960
|
+
for (const document of documentsArg) {
|
|
1961
|
+
if (!(document instanceof this) || document.creationStatus !== 'new') {
|
|
1962
|
+
throw new SmartdataPersistenceError('invalid_argument', 'insertManyIfAbsent requires newly constructed instances of the receiving model.');
|
|
1963
|
+
}
|
|
1964
|
+
assertUsableIdentityValues(document, this.prototype.uniqueIndexes || [], this.prototype.identityValueTypes);
|
|
1965
|
+
const identity = document[identityField];
|
|
1966
|
+
if (identities.has(identity)) {
|
|
1967
|
+
throw new SmartdataPersistenceError('invalid_argument', 'insertManyIfAbsent may not repeat an identity within one batch.');
|
|
1968
|
+
}
|
|
1969
|
+
identities.add(identity);
|
|
1970
|
+
if (getOrdinaryPersistencePolicy(this)?.timestamps !== 'none') {
|
|
1971
|
+
for (const timestamp of [document._createdAt, document._updatedAt]) {
|
|
1972
|
+
if (typeof timestamp !== 'string' || !Number.isFinite(Date.parse(timestamp))) {
|
|
1973
|
+
throw new SmartdataPersistenceError('invalid_argument', 'insertManyIfAbsent requires valid creation and update timestamps.');
|
|
1974
|
+
}
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
const collection = this.collection;
|
|
1979
|
+
return await collection.insertManyIfAbsent(documentsArg, identityField, {
|
|
1980
|
+
session: opts.session,
|
|
1981
|
+
timeoutMS,
|
|
1982
|
+
});
|
|
1983
|
+
}
|
|
1984
|
+
/**
|
|
1985
|
+
* Atomically updates one ordinary model document using a strict selector
|
|
1986
|
+
* and a bounded set of MongoDB update operators.
|
|
1987
|
+
*/
|
|
1988
|
+
static async atomicUpdate(filterArg, updateArg, opts) {
|
|
1989
|
+
if (getOrdinaryPersistencePolicy(this)) {
|
|
1990
|
+
throw new SmartdataPersistenceError('unsupported_operation', 'Validated ordinary models require a transactional postimage update.');
|
|
1991
|
+
}
|
|
1992
|
+
if (this[exactPersistencePolicySymbol]) {
|
|
1993
|
+
throw new SmartdataPersistenceError('unsupported_operation', 'atomicUpdate is unavailable for exact-persistence models.');
|
|
1994
|
+
}
|
|
1995
|
+
const declaredRoots = this.getDeclaredPersistedRoots();
|
|
1996
|
+
const declaredAtomicPaths = this.getDeclaredAtomicPaths();
|
|
1997
|
+
const identityValueTypes = this.getDeclaredIdentityValueTypes();
|
|
1998
|
+
const numericRoots = this.getDeclaredNumericRoots();
|
|
1999
|
+
const uniqueRoots = new Set(identityValueTypes.keys());
|
|
2000
|
+
const serializedRoots = this.getSerializedPersistedRoots();
|
|
2001
|
+
const normalizedFilter = normalizeStrictFilter(filterArg, declaredRoots, declaredAtomicPaths, identityValueTypes, numericRoots, serializedRoots, 'Atomic update');
|
|
2002
|
+
const normalizedOptions = '$expr' in normalizedFilter
|
|
2003
|
+
? normalizeAtomicExpressionUpdateOptions(opts)
|
|
2004
|
+
: opts;
|
|
2005
|
+
if (normalizedOptions?.upsert === true && '$expr' in normalizedFilter) {
|
|
2006
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Atomic update does not support upsert when the filter contains $expr.');
|
|
2007
|
+
}
|
|
2008
|
+
const normalizedUpdate = normalizeAtomicUpdate(updateArg, declaredRoots, declaredAtomicPaths, uniqueRoots, serializedRoots);
|
|
2009
|
+
const now = new Date().toISOString();
|
|
2010
|
+
normalizedUpdate.$set = {
|
|
2011
|
+
...(normalizedUpdate.$set || {}),
|
|
2012
|
+
_updatedAt: now,
|
|
2013
|
+
};
|
|
2014
|
+
if (normalizedOptions?.upsert === true) {
|
|
2015
|
+
normalizedUpdate.$setOnInsert = {
|
|
2016
|
+
...(normalizedUpdate.$setOnInsert || {}),
|
|
2017
|
+
_createdAt: now,
|
|
2018
|
+
};
|
|
2019
|
+
}
|
|
2020
|
+
const collection = this.collection;
|
|
2021
|
+
const result = await executeAtomicUpdate(collection, normalizedFilter, normalizedUpdate, normalizedOptions);
|
|
2022
|
+
return {
|
|
2023
|
+
acknowledged: result.acknowledged,
|
|
2024
|
+
matchedCount: result.matchedCount,
|
|
2025
|
+
modifiedCount: result.modifiedCount,
|
|
2026
|
+
upsertedId: result.upsertedId,
|
|
2027
|
+
};
|
|
2028
|
+
}
|
|
2029
|
+
/**
|
|
2030
|
+
* Atomically updates one ordinary model document and returns a hydrated
|
|
2031
|
+
* before or after image with a sanitized persistence outcome.
|
|
2032
|
+
*/
|
|
2033
|
+
static async atomicFindOneAndUpdate(filterArg, updateArg, optionsArg) {
|
|
2034
|
+
if (this[exactPersistencePolicySymbol]) {
|
|
2035
|
+
throw new SmartdataPersistenceError('unsupported_operation', 'atomicFindOneAndUpdate is unavailable for exact-persistence models.');
|
|
2036
|
+
}
|
|
2037
|
+
const normalizedOptions = normalizeAtomicFindOneAndUpdateOptions(optionsArg);
|
|
2038
|
+
const policy = getOrdinaryPersistencePolicy(this);
|
|
2039
|
+
const declaredRoots = this.getDeclaredPersistedRoots();
|
|
2040
|
+
const declaredAtomicPaths = this.getDeclaredAtomicPaths();
|
|
2041
|
+
const identityValueTypes = this.getDeclaredIdentityValueTypes();
|
|
2042
|
+
const numericRoots = this.getDeclaredNumericRoots();
|
|
2043
|
+
const uniqueRoots = new Set(identityValueTypes.keys());
|
|
2044
|
+
const serializedRoots = this.getSerializedPersistedRoots();
|
|
2045
|
+
const normalizedFilter = normalizeStrictFilter(filterArg, declaredRoots, declaredAtomicPaths, identityValueTypes, numericRoots, serializedRoots, 'Atomic find-one-and-update');
|
|
2046
|
+
if (normalizedOptions.upsert && '$expr' in normalizedFilter) {
|
|
2047
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Atomic find-one-and-update does not support upsert when the filter contains $expr.');
|
|
2048
|
+
}
|
|
2049
|
+
const normalizedUpdate = normalizeAtomicUpdate(updateArg, declaredRoots, declaredAtomicPaths, uniqueRoots, serializedRoots);
|
|
2050
|
+
if (policy?.timestamps !== 'none') {
|
|
2051
|
+
const now = new Date().toISOString();
|
|
2052
|
+
normalizedUpdate.$set = { ...(normalizedUpdate.$set || {}), _updatedAt: now };
|
|
2053
|
+
if (normalizedOptions.upsert) {
|
|
2054
|
+
normalizedUpdate.$setOnInsert = { ...(normalizedUpdate.$setOnInsert || {}), _createdAt: now };
|
|
2055
|
+
}
|
|
2056
|
+
}
|
|
2057
|
+
const normalizedSort = normalizeSort(normalizedOptions.sort, declaredRoots, this.getDeclaredQueryPaths());
|
|
2058
|
+
const collection = this.collection;
|
|
2059
|
+
const result = await executeAtomicFindOneAndUpdate(collection, normalizedFilter, normalizedUpdate, {
|
|
2060
|
+
returnDocument: normalizedOptions.returnDocument,
|
|
2061
|
+
upsert: normalizedOptions.upsert,
|
|
2062
|
+
...(normalizedSort ? { sort: normalizedSort } : {}),
|
|
2063
|
+
...(normalizedOptions.session ? { session: normalizedOptions.session } : {}),
|
|
2064
|
+
});
|
|
2065
|
+
if (result.document === null) {
|
|
2066
|
+
return result;
|
|
2067
|
+
}
|
|
2068
|
+
return {
|
|
2069
|
+
status: result.status,
|
|
2070
|
+
document: this.createInstanceFromMongoDbNativeDoc(result.document),
|
|
2071
|
+
};
|
|
2072
|
+
}
|
|
2073
|
+
/**
|
|
2074
|
+
* Atomically deletes one ordinary model document using a strict selector.
|
|
2075
|
+
*
|
|
2076
|
+
* This static operation intentionally does not hydrate an instance or run
|
|
2077
|
+
* instance deletion hooks. Callers that require those hooks must use the
|
|
2078
|
+
* instance `delete()` method instead.
|
|
2079
|
+
*/
|
|
2080
|
+
static async atomicDelete(filterArg, opts) {
|
|
2081
|
+
if (this[exactPersistencePolicySymbol]) {
|
|
2082
|
+
throw new SmartdataPersistenceError('unsupported_operation', 'atomicDelete is unavailable for exact-persistence models.');
|
|
2083
|
+
}
|
|
2084
|
+
const declaredRoots = this.getDeclaredPersistedRoots();
|
|
2085
|
+
const declaredAtomicPaths = this.getDeclaredAtomicPaths();
|
|
2086
|
+
const identityValueTypes = this.getDeclaredIdentityValueTypes();
|
|
2087
|
+
const numericRoots = this.getDeclaredNumericRoots();
|
|
2088
|
+
const serializedRoots = this.getSerializedPersistedRoots();
|
|
2089
|
+
const normalizedFilter = normalizeStrictFilter(filterArg, declaredRoots, declaredAtomicPaths, identityValueTypes, numericRoots, serializedRoots, 'Atomic delete', this.getGloballyConstrainingKeySets());
|
|
2090
|
+
const collection = this.collection;
|
|
2091
|
+
const result = await executeAtomicDelete(collection, normalizedFilter, { session: opts?.session, timeoutMS: requireBoundedInteger(opts?.timeoutMS, 'Atomic delete timeoutMS', 120_000) });
|
|
2092
|
+
return {
|
|
2093
|
+
acknowledged: result.acknowledged,
|
|
2094
|
+
deletedCount: result.deletedCount,
|
|
2095
|
+
};
|
|
2096
|
+
}
|
|
2097
|
+
/**
|
|
2098
|
+
* Atomically deletes every ordinary model document matching a strict
|
|
2099
|
+
* selector. Each matched document is deleted atomically; the batch as a
|
|
2100
|
+
* whole is not isolated. Unlike `atomicDelete()`, the filter does not need
|
|
2101
|
+
* to pin a unique index — plural intent is explicit in this API — but it
|
|
2102
|
+
* still requires declared fields and at least one top-level equality
|
|
2103
|
+
* anchor.
|
|
2104
|
+
*/
|
|
2105
|
+
static async atomicDeleteMany(filterArg, opts) {
|
|
2106
|
+
if (this[exactPersistencePolicySymbol]) {
|
|
2107
|
+
throw new SmartdataPersistenceError('unsupported_operation', 'atomicDeleteMany is unavailable for exact-persistence models.');
|
|
2108
|
+
}
|
|
2109
|
+
const declaredRoots = this.getDeclaredPersistedRoots();
|
|
2110
|
+
const declaredAtomicPaths = this.getDeclaredAtomicPaths();
|
|
2111
|
+
const identityValueTypes = this.getDeclaredIdentityValueTypes();
|
|
2112
|
+
const numericRoots = this.getDeclaredNumericRoots();
|
|
2113
|
+
const serializedRoots = this.getSerializedPersistedRoots();
|
|
2114
|
+
const normalizedFilter = normalizeStrictFilter(filterArg, declaredRoots, declaredAtomicPaths, identityValueTypes, numericRoots, serializedRoots, 'Atomic delete-many');
|
|
2115
|
+
const collection = this.collection;
|
|
2116
|
+
const result = await executeAtomicDeleteMany(collection, normalizedFilter, { session: opts?.session, timeoutMS: requireBoundedInteger(opts?.timeoutMS, 'Atomic delete-many timeoutMS', 120_000) });
|
|
2117
|
+
return {
|
|
2118
|
+
acknowledged: result.acknowledged,
|
|
2119
|
+
deletedCount: result.deletedCount,
|
|
2120
|
+
};
|
|
2121
|
+
}
|
|
2122
|
+
/**
|
|
2123
|
+
* Atomically updates every ordinary model document matching a strict
|
|
2124
|
+
* selector. Each matched document is updated atomically; the batch as a
|
|
2125
|
+
* whole is not isolated. No upsert is possible, so `$setOnInsert` is
|
|
2126
|
+
* rejected.
|
|
2127
|
+
*/
|
|
2128
|
+
static async atomicUpdateMany(filterArg, updateArg, opts) {
|
|
2129
|
+
if (getOrdinaryPersistencePolicy(this)) {
|
|
2130
|
+
throw new SmartdataPersistenceError('unsupported_operation', 'Validated ordinary models require transactional postimage updates.');
|
|
2131
|
+
}
|
|
2132
|
+
if (this[exactPersistencePolicySymbol]) {
|
|
2133
|
+
throw new SmartdataPersistenceError('unsupported_operation', 'atomicUpdateMany is unavailable for exact-persistence models.');
|
|
2134
|
+
}
|
|
2135
|
+
if (typeof updateArg === 'object'
|
|
2136
|
+
&& updateArg !== null
|
|
2137
|
+
&& '$setOnInsert' in updateArg) {
|
|
2138
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Atomic update-many does not support $setOnInsert.');
|
|
2139
|
+
}
|
|
2140
|
+
const declaredRoots = this.getDeclaredPersistedRoots();
|
|
2141
|
+
const declaredAtomicPaths = this.getDeclaredAtomicPaths();
|
|
2142
|
+
const uniqueRoots = this.getDeclaredUniqueRoots();
|
|
2143
|
+
const identityValueTypes = this.getDeclaredIdentityValueTypes();
|
|
2144
|
+
const numericRoots = this.getDeclaredNumericRoots();
|
|
2145
|
+
const serializedRoots = this.getSerializedPersistedRoots();
|
|
2146
|
+
const normalizedFilter = normalizeStrictFilter(filterArg, declaredRoots, declaredAtomicPaths, identityValueTypes, numericRoots, serializedRoots, 'Atomic update-many');
|
|
2147
|
+
const normalizedUpdate = normalizeAtomicUpdate(updateArg, declaredRoots, declaredAtomicPaths, uniqueRoots, serializedRoots);
|
|
2148
|
+
const now = new Date().toISOString();
|
|
2149
|
+
normalizedUpdate.$set = {
|
|
2150
|
+
...(normalizedUpdate.$set || {}),
|
|
2151
|
+
_updatedAt: now,
|
|
2152
|
+
};
|
|
2153
|
+
const collection = this.collection;
|
|
2154
|
+
const result = await executeAtomicUpdateMany(collection, normalizedFilter, normalizedUpdate, opts);
|
|
2155
|
+
return {
|
|
2156
|
+
acknowledged: result.acknowledged,
|
|
2157
|
+
matchedCount: result.matchedCount,
|
|
2158
|
+
modifiedCount: result.modifiedCount,
|
|
2159
|
+
};
|
|
2160
|
+
}
|
|
2161
|
+
/**
|
|
2162
|
+
* Computes bounded grouped counts and optional numeric sums server-side.
|
|
2163
|
+
* Groups by one or two declared top-level fields, always returns a `count`
|
|
2164
|
+
* per group, and sums only declared numeric fields. The `$limit` follows
|
|
2165
|
+
* the group stage without a sort, so when more groups exist than the limit
|
|
2166
|
+
* the returned subset is arbitrary. Use `getGroupedTotalsPage()` when the
|
|
2167
|
+
* caller must detect overflow. The aggregation cursor never leaves SmartData.
|
|
2168
|
+
*/
|
|
2169
|
+
static async getGroupedTotals(optionsArg) {
|
|
2170
|
+
const page = await this.getGroupedTotalsPage(optionsArg);
|
|
2171
|
+
return page.rows;
|
|
2172
|
+
}
|
|
2173
|
+
/**
|
|
2174
|
+
* Computes the same bounded grouped totals as `getGroupedTotals()` and
|
|
2175
|
+
* reports whether at least one additional group exists beyond the requested
|
|
2176
|
+
* row limit.
|
|
2177
|
+
*/
|
|
2178
|
+
static async getGroupedTotalsPage(optionsArg) {
|
|
2179
|
+
if (this[exactPersistencePolicySymbol]) {
|
|
2180
|
+
throw new SmartdataPersistenceError('unsupported_operation', 'getGroupedTotals is unavailable for exact-persistence models.');
|
|
2181
|
+
}
|
|
2182
|
+
if (typeof optionsArg !== 'object'
|
|
2183
|
+
|| optionsArg === null
|
|
2184
|
+
|| plugins.nodeUtil.types.isProxy(optionsArg)
|
|
2185
|
+
|| !isPlainObject(optionsArg)) {
|
|
2186
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Grouped totals options must be an inert plain object.');
|
|
2187
|
+
}
|
|
2188
|
+
const allowedKeys = new Set([
|
|
2189
|
+
'groupBy',
|
|
2190
|
+
'sums',
|
|
2191
|
+
'filter',
|
|
2192
|
+
'limit',
|
|
2193
|
+
'maxTimeMS',
|
|
2194
|
+
'timeoutMS',
|
|
2195
|
+
'signal',
|
|
2196
|
+
'session',
|
|
2197
|
+
]);
|
|
2198
|
+
for (const key of Reflect.ownKeys(optionsArg)) {
|
|
2199
|
+
if (typeof key !== 'string' || !allowedKeys.has(key)) {
|
|
2200
|
+
throw new SmartdataPersistenceError('invalid_argument', `Grouped totals received unsupported option "${String(key)}".`);
|
|
2201
|
+
}
|
|
2202
|
+
const descriptor = Object.getOwnPropertyDescriptor(optionsArg, key);
|
|
2203
|
+
if (!descriptor
|
|
2204
|
+
|| !('value' in descriptor)
|
|
2205
|
+
|| descriptor.enumerable !== true) {
|
|
2206
|
+
throw new SmartdataPersistenceError('invalid_argument', `Grouped totals option "${key}" must be an inert enumerable data property.`);
|
|
2207
|
+
}
|
|
2208
|
+
}
|
|
2209
|
+
const groupByOption = optionsArg.groupBy;
|
|
2210
|
+
const sumsOption = optionsArg.sums;
|
|
2211
|
+
const filterOption = optionsArg.filter;
|
|
2212
|
+
const limitOption = optionsArg.limit;
|
|
2213
|
+
const maxTimeMSOption = optionsArg.maxTimeMS;
|
|
2214
|
+
const timeoutMSOption = optionsArg.timeoutMS;
|
|
2215
|
+
const signalOption = optionsArg.signal;
|
|
2216
|
+
if (signalOption !== undefined && !(signalOption instanceof AbortSignal)) {
|
|
2217
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Grouped totals signal must be an AbortSignal.');
|
|
2218
|
+
}
|
|
2219
|
+
signalOption?.throwIfAborted();
|
|
2220
|
+
const sessionOption = optionsArg.session;
|
|
2221
|
+
const declaredRoots = this.getDeclaredPersistedRoots();
|
|
2222
|
+
const serializedRoots = this.getSerializedPersistedRoots();
|
|
2223
|
+
const requireDeclaredGroupField = (fieldArg, labelArg) => {
|
|
2224
|
+
if (typeof fieldArg !== 'string') {
|
|
2225
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} must name a declared top-level field.`);
|
|
2226
|
+
}
|
|
2227
|
+
const root = requireDeclaredPath(fieldArg, declaredRoots, labelArg);
|
|
2228
|
+
if (root !== fieldArg) {
|
|
2229
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} must name a declared top-level field, not a nested path.`);
|
|
2230
|
+
}
|
|
2231
|
+
if (serializedRoots.has(root)) {
|
|
2232
|
+
throw new SmartdataPersistenceError('unsupported_operation', `${labelArg} cannot target serialized field "${root}".`);
|
|
2233
|
+
}
|
|
2234
|
+
return root;
|
|
2235
|
+
};
|
|
2236
|
+
if (!Array.isArray(groupByOption)
|
|
2237
|
+
|| groupByOption.length < 1
|
|
2238
|
+
|| groupByOption.length > 2) {
|
|
2239
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Grouped totals require one or two groupBy fields.');
|
|
2240
|
+
}
|
|
2241
|
+
const groupByFields = [...groupByOption].map((fieldArg) => requireDeclaredGroupField(fieldArg, 'Grouped totals groupBy field'));
|
|
2242
|
+
if (groupByFields.length < 1
|
|
2243
|
+
|| groupByFields.length > 2
|
|
2244
|
+
|| new Set(groupByFields).size !== groupByFields.length) {
|
|
2245
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Grouped totals groupBy fields must be one or two distinct fields.');
|
|
2246
|
+
}
|
|
2247
|
+
if (sumsOption !== undefined && !Array.isArray(sumsOption)) {
|
|
2248
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Grouped totals sums must be an array of declared numeric fields.');
|
|
2249
|
+
}
|
|
2250
|
+
const sumFields = [...(sumsOption ?? [])].map((fieldArg) => requireDeclaredGroupField(fieldArg, 'Grouped totals sum field'));
|
|
2251
|
+
if (new Set(sumFields).size !== sumFields.length) {
|
|
2252
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Grouped totals sum fields must be distinct.');
|
|
2253
|
+
}
|
|
2254
|
+
const limit = requireBoundedInteger(limitOption, 'Grouped totals limit', 10_000);
|
|
2255
|
+
if (limit === undefined) {
|
|
2256
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Grouped totals require an explicit limit.');
|
|
2257
|
+
}
|
|
2258
|
+
const maxTimeMS = requireBoundedInteger(maxTimeMSOption, 'Grouped totals maxTimeMS', 120_000);
|
|
2259
|
+
const timeoutMS = requireBoundedInteger(timeoutMSOption, 'Grouped totals timeoutMS', 120_000);
|
|
2260
|
+
const groupStage = {
|
|
2261
|
+
_id: groupByFields.length === 1
|
|
2262
|
+
? '$' + groupByFields[0]
|
|
2263
|
+
: Object.fromEntries(groupByFields.map((fieldArg) => [fieldArg, '$' + fieldArg])),
|
|
2264
|
+
__groupedTotalsCount: { $sum: 1 },
|
|
2265
|
+
};
|
|
2266
|
+
for (const [index, sumField] of sumFields.entries()) {
|
|
2267
|
+
groupStage['__groupedTotalsSum' + index] = { $sum: '$' + sumField };
|
|
2268
|
+
}
|
|
2269
|
+
const collection = this.collection;
|
|
2270
|
+
const rows = await collection.aggregateGroupedTotals(filterOption !== undefined
|
|
2271
|
+
? convertFilterForMongoDb(filterOption)
|
|
2272
|
+
: undefined, groupStage, limit + 1, {
|
|
2273
|
+
...(sessionOption ? { session: sessionOption } : {}),
|
|
2274
|
+
...(maxTimeMS !== undefined ? { maxTimeMS } : {}),
|
|
2275
|
+
...(timeoutMS !== undefined ? { timeoutMS } : {}),
|
|
2276
|
+
...(signalOption !== undefined ? { signal: signalOption } : {}),
|
|
2277
|
+
});
|
|
2278
|
+
const hasMore = rows.length > limit;
|
|
2279
|
+
const returnedRows = rows.slice(0, limit);
|
|
2280
|
+
const requireFiniteNumber = (valueArg, labelArg) => {
|
|
2281
|
+
if (typeof valueArg !== 'number' || !Number.isFinite(valueArg)) {
|
|
2282
|
+
throw new SmartdataPersistenceError('unsupported_operation', `${labelArg} produced a non-numeric total; store safe-integer values in summed fields.`);
|
|
2283
|
+
}
|
|
2284
|
+
return valueArg;
|
|
2285
|
+
};
|
|
2286
|
+
const mappedRows = returnedRows.map((rowArg) => {
|
|
2287
|
+
const group = {};
|
|
2288
|
+
if (groupByFields.length === 1) {
|
|
2289
|
+
group[groupByFields[0]] = rowArg._id ?? null;
|
|
2290
|
+
}
|
|
2291
|
+
else {
|
|
2292
|
+
const compoundKey = (rowArg._id ?? {});
|
|
2293
|
+
for (const fieldArg of groupByFields) {
|
|
2294
|
+
// Missing and explicit-null values merge into one group that is
|
|
2295
|
+
// reported as null in both the single-field and compound shapes.
|
|
2296
|
+
group[fieldArg] = compoundKey[fieldArg] ?? null;
|
|
2297
|
+
}
|
|
2298
|
+
}
|
|
2299
|
+
const sums = {};
|
|
2300
|
+
for (const [index, sumField] of sumFields.entries()) {
|
|
2301
|
+
sums[sumField] = requireFiniteNumber(rowArg['__groupedTotalsSum' + index], `Grouped totals sum field "${sumField}"`);
|
|
2302
|
+
}
|
|
2303
|
+
return {
|
|
2304
|
+
group,
|
|
2305
|
+
count: requireFiniteNumber(rowArg.__groupedTotalsCount, 'Grouped totals count'),
|
|
2306
|
+
sums,
|
|
2307
|
+
};
|
|
2308
|
+
});
|
|
2309
|
+
return {
|
|
2310
|
+
rows: mappedRows,
|
|
2311
|
+
hasMore,
|
|
2312
|
+
};
|
|
2313
|
+
}
|
|
2314
|
+
/**
|
|
2315
|
+
* gets all instances as array
|
|
2316
|
+
* @param this
|
|
2317
|
+
* @param filterArg - Type-safe MongoDB filter with nested object support and operators
|
|
2318
|
+
* @returns
|
|
2319
|
+
*/
|
|
2320
|
+
static async getInstances(filterArg, opts) {
|
|
2321
|
+
// Pass session through to findAll for transactional queries
|
|
2322
|
+
const foundDocs = await this.collection.findAll(convertFilterForMongoDb(filterArg), { session: opts?.session });
|
|
2323
|
+
const returnArray = [];
|
|
2324
|
+
for (const foundDoc of foundDocs) {
|
|
2325
|
+
const newInstance = this.createInstanceFromMongoDbNativeDoc(foundDoc);
|
|
2326
|
+
returnArray.push(newInstance);
|
|
2327
|
+
}
|
|
2328
|
+
return returnArray;
|
|
2329
|
+
}
|
|
2330
|
+
/**
|
|
2331
|
+
* Cursor-paged query with stable seek pagination — the org-standard way to
|
|
2332
|
+
* list unbounded collections. Orders by a comparable (ideally indexed)
|
|
2333
|
+
* sort field with a unique tiebreaker, returns one page plus the cursor
|
|
2334
|
+
* for the next, and never materializes the full result set.
|
|
2335
|
+
* Owned sessions require a prepared model and remain leased through optional
|
|
2336
|
+
* counting, model hydration and cursor cleanup.
|
|
2337
|
+
*/
|
|
2338
|
+
static async getPagedInstances(optionsArg) {
|
|
2339
|
+
const collection = this.collection;
|
|
2340
|
+
optionsArg = { ...optionsArg, cursor: optionsArg.cursor && { ...optionsArg.cursor } };
|
|
2341
|
+
const sortDirection = optionsArg.sortDirection === 'asc' ? 1 : -1;
|
|
2342
|
+
const uniqueField = optionsArg.uniqueField || 'id';
|
|
2343
|
+
const requestedLimit = Number.isSafeInteger(optionsArg.limit) && optionsArg.limit > 0
|
|
2344
|
+
? optionsArg.limit
|
|
2345
|
+
: 100;
|
|
2346
|
+
const limit = Math.min(requestedLimit, 1000);
|
|
2347
|
+
const baseSelector = convertFilterForMongoDb(optionsArg.filter || {});
|
|
2348
|
+
let selector = baseSelector;
|
|
2349
|
+
if (optionsArg.cursor) {
|
|
2350
|
+
const seekOperator = sortDirection === 1 ? '$gt' : '$lt';
|
|
2351
|
+
const seekSelector = {
|
|
2352
|
+
$or: [
|
|
2353
|
+
{ [optionsArg.sortField]: { [seekOperator]: optionsArg.cursor.sortValue } },
|
|
2354
|
+
{
|
|
2355
|
+
[optionsArg.sortField]: optionsArg.cursor.sortValue,
|
|
2356
|
+
[uniqueField]: { [seekOperator]: optionsArg.cursor.uniqueValue },
|
|
2357
|
+
},
|
|
2358
|
+
],
|
|
2359
|
+
};
|
|
2360
|
+
selector = Object.keys(baseSelector).length > 0
|
|
2361
|
+
? { $and: [baseSelector, seekSelector] }
|
|
2362
|
+
: seekSelector;
|
|
2363
|
+
}
|
|
2364
|
+
return runWithOrdinarySmartdataSession(optionsArg.session, collection.smartdataDb, {
|
|
2365
|
+
ordinaryWrite: false,
|
|
2366
|
+
prepared: collection.isInitializedForCurrentDatabase(),
|
|
2367
|
+
}, async (rawSessionArg) => {
|
|
2368
|
+
await collection.init();
|
|
2369
|
+
const rawCursor = collection.mongoDbCollection
|
|
2370
|
+
.find(selector, { session: rawSessionArg })
|
|
2371
|
+
.sort({ [optionsArg.sortField]: sortDirection, [uniqueField]: sortDirection })
|
|
2372
|
+
.limit(limit + 1);
|
|
2373
|
+
return runCursorOperation(rawCursor, async (cursorArg) => {
|
|
2374
|
+
const rawDocuments = await cursorArg.toArray();
|
|
2375
|
+
const hasMore = rawDocuments.length > limit;
|
|
2376
|
+
const pageRows = rawDocuments.slice(0, limit);
|
|
2377
|
+
const documents = pageRows.map((rawDocument) => this.createInstanceFromMongoDbNativeDoc(rawDocument));
|
|
2378
|
+
const lastRow = pageRows[pageRows.length - 1];
|
|
2379
|
+
const total = optionsArg.withTotal
|
|
2380
|
+
? await collection.mongoDbCollection.countDocuments(baseSelector, {
|
|
2381
|
+
session: rawSessionArg,
|
|
2382
|
+
})
|
|
2383
|
+
: undefined;
|
|
2384
|
+
return {
|
|
2385
|
+
documents,
|
|
2386
|
+
...(hasMore && lastRow
|
|
2387
|
+
? {
|
|
2388
|
+
nextCursor: {
|
|
2389
|
+
sortValue: lastRow[optionsArg.sortField],
|
|
2390
|
+
uniqueValue: lastRow[uniqueField],
|
|
2391
|
+
},
|
|
2392
|
+
}
|
|
2393
|
+
: {}),
|
|
2394
|
+
...(total !== undefined ? { total } : {}),
|
|
2395
|
+
};
|
|
2396
|
+
});
|
|
2397
|
+
});
|
|
2398
|
+
}
|
|
2399
|
+
/**
|
|
2400
|
+
* gets the first matching instance
|
|
2401
|
+
* @param this
|
|
2402
|
+
* @param filterArg
|
|
2403
|
+
* @returns
|
|
2404
|
+
*/
|
|
2405
|
+
static async getInstance(filterArg, opts) {
|
|
2406
|
+
this.assertHydratedProjection(opts?.projection);
|
|
2407
|
+
const declaredRoots = this.getDeclaredPersistedRoots();
|
|
2408
|
+
// Retrieve one document, with optional session for transactions
|
|
2409
|
+
const foundDoc = await this.collection.findOne(convertFilterForMongoDb(filterArg), {
|
|
2410
|
+
projection: normalizeProjection(opts?.projection, declaredRoots, this.getDeclaredQueryPaths()),
|
|
2411
|
+
maxTimeMS: requireBoundedInteger(opts?.maxTimeMS, 'maxTimeMS', 120_000),
|
|
2412
|
+
session: opts?.session,
|
|
2413
|
+
});
|
|
2414
|
+
if (foundDoc) {
|
|
2415
|
+
const newInstance = this.createInstanceFromMongoDbNativeDoc(foundDoc);
|
|
2416
|
+
return newInstance;
|
|
2417
|
+
}
|
|
2418
|
+
else {
|
|
2419
|
+
return null;
|
|
2420
|
+
}
|
|
2421
|
+
}
|
|
2422
|
+
static async exists(filterArg, opts) {
|
|
2423
|
+
const foundDoc = await this.collection.findOne(convertFilterForMongoDb(filterArg), {
|
|
2424
|
+
projection: { _id: 1 },
|
|
2425
|
+
maxTimeMS: requireBoundedInteger(opts?.maxTimeMS, 'maxTimeMS', 120_000),
|
|
2426
|
+
session: opts?.session,
|
|
2427
|
+
});
|
|
2428
|
+
return foundDoc !== null;
|
|
2429
|
+
}
|
|
2430
|
+
/**
|
|
2431
|
+
* get a unique id prefixed with the class name
|
|
2432
|
+
*/
|
|
2433
|
+
static async getNewId(lengthArg = 20) {
|
|
2434
|
+
return `${this.className}:${plugins.smartunique.shortId(lengthArg)}`;
|
|
2435
|
+
}
|
|
2436
|
+
/**
|
|
2437
|
+
* Stream results using model-declared projections, sorts and index hints.
|
|
2438
|
+
* Offset pages require an explicit sort and limit. Include a unique final
|
|
2439
|
+
* tiebreaker; concurrent writes can still move rows between offset pages.
|
|
2440
|
+
*/
|
|
2441
|
+
static async getCursor(filterArg, opts) {
|
|
2442
|
+
this.assertHydratedProjection(opts?.projection, opts?.modifier);
|
|
2443
|
+
const { session, modifier } = opts || {};
|
|
2444
|
+
const declaredRoots = this.getDeclaredPersistedRoots();
|
|
2445
|
+
const declaredQueryPaths = this.getDeclaredQueryPaths();
|
|
2446
|
+
const projection = normalizeProjection(opts?.projection, declaredRoots, declaredQueryPaths);
|
|
2447
|
+
const sort = normalizeSort(opts?.sort, declaredRoots, declaredQueryPaths);
|
|
2448
|
+
const hint = normalizeQueryHint(opts?.hint, this);
|
|
2449
|
+
const batchSize = requireBoundedInteger(opts?.batchSize, 'batchSize', 10_000);
|
|
2450
|
+
const limit = requireBoundedInteger(opts?.limit, 'limit', 10_000);
|
|
2451
|
+
const maxTimeMS = requireBoundedInteger(opts?.maxTimeMS, 'maxTimeMS', 120_000);
|
|
2452
|
+
const skip = opts?.skip;
|
|
2453
|
+
if (skip !== undefined && (!Number.isSafeInteger(skip) || skip < 0 || skip > 2_147_483_647 ||
|
|
2454
|
+
!sort || limit === undefined)) {
|
|
2455
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Cursor skip must be an integer from 0 through 2147483647 and requires sort and limit.');
|
|
2456
|
+
}
|
|
2457
|
+
const collection = this.collection;
|
|
2458
|
+
await collection.init();
|
|
2459
|
+
let rawCursor = collection.mongoDbCollection.find(convertFilterForMongoDb(filterArg), {
|
|
2460
|
+
projection,
|
|
2461
|
+
session,
|
|
2462
|
+
hint,
|
|
2463
|
+
skip,
|
|
2464
|
+
});
|
|
2465
|
+
if (sort) {
|
|
2466
|
+
rawCursor = rawCursor.sort(sort);
|
|
2467
|
+
}
|
|
2468
|
+
if (batchSize) {
|
|
2469
|
+
rawCursor = rawCursor.batchSize(batchSize);
|
|
2470
|
+
}
|
|
2471
|
+
if (limit) {
|
|
2472
|
+
rawCursor = rawCursor.limit(limit);
|
|
2473
|
+
}
|
|
2474
|
+
if (maxTimeMS) {
|
|
2475
|
+
rawCursor = rawCursor.maxTimeMS(maxTimeMS);
|
|
2476
|
+
}
|
|
2477
|
+
if (modifier) {
|
|
2478
|
+
const originalCursor = rawCursor;
|
|
2479
|
+
let modifiedCursor;
|
|
2480
|
+
try {
|
|
2481
|
+
modifiedCursor = modifier(originalCursor);
|
|
2482
|
+
}
|
|
2483
|
+
catch (modifierError) {
|
|
2484
|
+
try {
|
|
2485
|
+
await originalCursor.close();
|
|
2486
|
+
}
|
|
2487
|
+
catch {
|
|
2488
|
+
// Preserve the modifier error when best-effort cleanup also fails.
|
|
2489
|
+
}
|
|
2490
|
+
throw modifierError;
|
|
2491
|
+
}
|
|
2492
|
+
if (modifiedCursor !== originalCursor) {
|
|
2493
|
+
try {
|
|
2494
|
+
await originalCursor.close();
|
|
2495
|
+
}
|
|
2496
|
+
catch (originalCursorCloseError) {
|
|
2497
|
+
try {
|
|
2498
|
+
await modifiedCursor.close();
|
|
2499
|
+
}
|
|
2500
|
+
catch {
|
|
2501
|
+
// Preserve the original cursor's cleanup error.
|
|
2502
|
+
}
|
|
2503
|
+
throw originalCursorCloseError;
|
|
2504
|
+
}
|
|
2505
|
+
}
|
|
2506
|
+
rawCursor = modifiedCursor;
|
|
2507
|
+
}
|
|
2508
|
+
return new SmartdataDbCursor(rawCursor, this);
|
|
2509
|
+
}
|
|
2510
|
+
/**
|
|
2511
|
+
* Read a bounded offset page while retaining an owned session through cursor
|
|
2512
|
+
* cleanup. Initialize the model before calling; this operation never creates
|
|
2513
|
+
* collections or indexes. Count separately with the same filter and hint.
|
|
2514
|
+
*/
|
|
2515
|
+
static async getOffsetPage(filterArg, opts) {
|
|
2516
|
+
const declaredRoots = this.getDeclaredPersistedRoots();
|
|
2517
|
+
this.assertHydratedProjection(opts?.projection);
|
|
2518
|
+
const declaredQueryPaths = this.getDeclaredQueryPaths();
|
|
2519
|
+
const projection = normalizeProjection(opts?.projection, declaredRoots, declaredQueryPaths);
|
|
2520
|
+
const sort = normalizeSort(opts?.sort, declaredRoots, declaredQueryPaths);
|
|
2521
|
+
const hint = normalizeQueryHint(opts?.hint, this);
|
|
2522
|
+
const limit = requireBoundedInteger(opts?.limit, 'limit', 10_000);
|
|
2523
|
+
const skip = opts?.skip;
|
|
2524
|
+
if (!sort || limit === undefined || !Number.isSafeInteger(skip) || skip < 0 || skip > 2_147_483_647) {
|
|
2525
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Offset pages require sort, limit and an integer skip from 0 through 2147483647.');
|
|
2526
|
+
}
|
|
2527
|
+
const timeoutMS = requireBoundedInteger(opts?.timeoutMS === undefined ? 5_000 : opts.timeoutMS, 'timeoutMS', 120_000);
|
|
2528
|
+
const maxTimeMS = requireBoundedInteger(opts?.maxTimeMS, 'maxTimeMS', 120_000);
|
|
2529
|
+
const filter = convertFilterForMongoDb(filterArg);
|
|
2530
|
+
opts.signal?.throwIfAborted();
|
|
2531
|
+
const collection = this.collection;
|
|
2532
|
+
if (!collection.isInitializedForCurrentDatabase()) {
|
|
2533
|
+
throw new SmartdataPersistenceError('unsupported_operation', 'Initialize the model before reading an offset page.');
|
|
2534
|
+
}
|
|
2535
|
+
return runWithOrdinarySmartdataSession(opts.session, collection.smartdataDb, {
|
|
2536
|
+
ordinaryWrite: false,
|
|
2537
|
+
prepared: true,
|
|
2538
|
+
}, async (rawSessionArg) => {
|
|
2539
|
+
opts.signal?.throwIfAborted();
|
|
2540
|
+
const rawCursor = collection.mongoDbCollection.find(filter, {
|
|
2541
|
+
projection, sort, hint, skip, limit, maxTimeMS, timeoutMS,
|
|
2542
|
+
timeoutMode: 'cursorLifetime', session: rawSessionArg, signal: opts.signal,
|
|
2543
|
+
});
|
|
2544
|
+
return runCursorOperation(rawCursor, async (cursorArg) => {
|
|
2545
|
+
const documents = await cursorArg.toArray();
|
|
2546
|
+
return documents.map((documentArg) => this.createInstanceFromMongoDbNativeDoc(documentArg));
|
|
2547
|
+
}, opts.signal);
|
|
2548
|
+
});
|
|
2549
|
+
}
|
|
2550
|
+
/**
|
|
2551
|
+
* watch the collection
|
|
2552
|
+
* @param this
|
|
2553
|
+
* @param filterArg
|
|
2554
|
+
* @param forEachFunction
|
|
2555
|
+
*/
|
|
2556
|
+
/**
|
|
2557
|
+
* Watch the collection for changes, with optional buffering and change stream options.
|
|
2558
|
+
* @param filterArg MongoDB filter to select which changes to observe
|
|
2559
|
+
* @param opts optional ChangeStreamOptions plus bufferTimeMs
|
|
2560
|
+
*/
|
|
2561
|
+
static async watch(filterArg, opts) {
|
|
2562
|
+
const collection = this.collection;
|
|
2563
|
+
const watcher = await collection.watch(convertFilterForMongoDb(filterArg), opts || {}, this);
|
|
2564
|
+
return watcher;
|
|
2565
|
+
}
|
|
2566
|
+
/**
|
|
2567
|
+
* run a function for all instances
|
|
2568
|
+
* @returns
|
|
2569
|
+
*/
|
|
2570
|
+
static async forEach(filterArg, forEachFunction) {
|
|
2571
|
+
const cursor = await this.getCursor(filterArg);
|
|
2572
|
+
await cursor.forEach(forEachFunction);
|
|
2573
|
+
}
|
|
2574
|
+
/**
|
|
2575
|
+
* returns a count of the documents in the collection
|
|
2576
|
+
*/
|
|
2577
|
+
static async getCount(filterArg = {}, opts) {
|
|
2578
|
+
const hint = normalizeQueryHint(opts?.hint, this);
|
|
2579
|
+
const collection = this.collection;
|
|
2580
|
+
return await collection.getCount(convertFilterForMongoDb(filterArg), {
|
|
2581
|
+
hint,
|
|
2582
|
+
limit: requireBoundedInteger(opts?.limit, 'limit', 10_000),
|
|
2583
|
+
maxTimeMS: requireBoundedInteger(opts?.maxTimeMS, 'maxTimeMS', 120_000),
|
|
2584
|
+
timeoutMS: requireBoundedInteger(opts?.timeoutMS, 'timeoutMS', 120_000),
|
|
2585
|
+
signal: opts?.signal,
|
|
2586
|
+
session: opts?.session,
|
|
2587
|
+
});
|
|
2588
|
+
}
|
|
2589
|
+
/**
|
|
2590
|
+
* Runs an integrity check on this collection.
|
|
2591
|
+
* Returns a summary with estimated vs actual counts and any duplicate unique fields.
|
|
2592
|
+
*/
|
|
2593
|
+
static async checkCollectionIntegrity() {
|
|
2594
|
+
const collection = this.collection;
|
|
2595
|
+
return await collection.checkCollectionIntegrity();
|
|
2596
|
+
}
|
|
2597
|
+
/**
|
|
2598
|
+
* Create a MongoDB filter from a Lucene query string
|
|
2599
|
+
* @param luceneQuery Lucene query string
|
|
2600
|
+
* @returns MongoDB query object
|
|
2601
|
+
*/
|
|
2602
|
+
static createSearchFilter(luceneQuery) {
|
|
2603
|
+
const searchableFields = this.getSearchableFields();
|
|
2604
|
+
if (searchableFields.length === 0) {
|
|
2605
|
+
throw new Error(`No searchable fields defined for class ${this.name}`);
|
|
2606
|
+
}
|
|
2607
|
+
const adapter = new SmartdataLuceneAdapter(searchableFields);
|
|
2608
|
+
return adapter.convert(luceneQuery);
|
|
2609
|
+
}
|
|
2610
|
+
/**
|
|
2611
|
+
* List all searchable fields defined on this class
|
|
2612
|
+
*/
|
|
2613
|
+
static getSearchableFields() {
|
|
2614
|
+
const ctor = this;
|
|
2615
|
+
return Array.isArray(ctor.searchableFields) ? ctor.searchableFields : [];
|
|
2616
|
+
}
|
|
2617
|
+
/**
|
|
2618
|
+
* Execute a query with optional hard filter and post-fetch validation
|
|
2619
|
+
*/
|
|
2620
|
+
static async execQuery(baseFilter, opts) {
|
|
2621
|
+
let mongoFilter = baseFilter || {};
|
|
2622
|
+
if (opts?.filter) {
|
|
2623
|
+
mongoFilter = { $and: [mongoFilter, opts.filter] };
|
|
2624
|
+
}
|
|
2625
|
+
// Fetch with optional session for transactions
|
|
2626
|
+
// Fetch within optional session
|
|
2627
|
+
let docs = await this.getInstances(mongoFilter, { session: opts?.session });
|
|
2628
|
+
if (opts?.validate) {
|
|
2629
|
+
const out = [];
|
|
2630
|
+
for (const d of docs) {
|
|
2631
|
+
if (await opts.validate(d))
|
|
2632
|
+
out.push(d);
|
|
2633
|
+
}
|
|
2634
|
+
docs = out;
|
|
2635
|
+
}
|
|
2636
|
+
return docs;
|
|
2637
|
+
}
|
|
2638
|
+
/**
|
|
2639
|
+
* Search documents by text or field:value syntax, with safe regex fallback
|
|
2640
|
+
* Supports additional filtering and post-fetch validation via opts
|
|
2641
|
+
* @param query A search term or field:value expression
|
|
2642
|
+
* @param opts Optional filter and validate hooks
|
|
2643
|
+
* @returns Array of matching documents
|
|
2644
|
+
*/
|
|
2645
|
+
static async search(query, opts) {
|
|
2646
|
+
const searchableFields = this.getSearchableFields();
|
|
2647
|
+
if (searchableFields.length === 0) {
|
|
2648
|
+
throw new Error(`No searchable fields defined for class ${this.name}`);
|
|
2649
|
+
}
|
|
2650
|
+
// empty query -> return all
|
|
2651
|
+
const q = query.trim();
|
|
2652
|
+
if (!q) {
|
|
2653
|
+
// empty query: fetch all, apply opts
|
|
2654
|
+
return await this.execQuery({}, opts);
|
|
2655
|
+
}
|
|
2656
|
+
// simple exact field:value (no spaces, no wildcards, no quotes)
|
|
2657
|
+
// simple exact field:value (no spaces, wildcards, quotes)
|
|
2658
|
+
const simpleExact = q.match(/^(\w+):([^"'\*\?\s]+)$/);
|
|
2659
|
+
if (simpleExact) {
|
|
2660
|
+
const field = simpleExact[1];
|
|
2661
|
+
const value = simpleExact[2];
|
|
2662
|
+
if (!searchableFields.includes(field)) {
|
|
2663
|
+
throw new Error(`Field '${field}' is not searchable for class ${this.name}`);
|
|
2664
|
+
}
|
|
2665
|
+
// simple field:value search
|
|
2666
|
+
return await this.execQuery({ [field]: value }, opts);
|
|
2667
|
+
}
|
|
2668
|
+
// quoted phrase across all searchable fields: exact match of phrase
|
|
2669
|
+
const quoted = q.match(/^"(.+)"$|^'(.+)'$/);
|
|
2670
|
+
if (quoted) {
|
|
2671
|
+
const phrase = quoted[1] || quoted[2] || '';
|
|
2672
|
+
const parts = phrase.split(/\s+/).map((t) => escapeForRegex(t));
|
|
2673
|
+
const pattern = parts.join('\\s+');
|
|
2674
|
+
const orConds = searchableFields.map((f) => ({ [f]: { $regex: pattern, $options: 'i' } }));
|
|
2675
|
+
return await this.execQuery({ $or: orConds }, opts);
|
|
2676
|
+
}
|
|
2677
|
+
// wildcard field:value (supports * and ?) -> direct regex on that field
|
|
2678
|
+
const wildcardField = q.match(/^(\w+):(.+[*?].*)$/);
|
|
2679
|
+
if (wildcardField) {
|
|
2680
|
+
const field = wildcardField[1];
|
|
2681
|
+
// Support quoted wildcard patterns: strip surrounding quotes
|
|
2682
|
+
let pattern = wildcardField[2];
|
|
2683
|
+
if ((pattern.startsWith('"') && pattern.endsWith('"')) ||
|
|
2684
|
+
(pattern.startsWith("'") && pattern.endsWith("'"))) {
|
|
2685
|
+
pattern = pattern.slice(1, -1);
|
|
2686
|
+
}
|
|
2687
|
+
if (!searchableFields.includes(field)) {
|
|
2688
|
+
throw new Error(`Field '${field}' is not searchable for class ${this.name}`);
|
|
2689
|
+
}
|
|
2690
|
+
// escape regex special chars except * and ?, then convert wildcards
|
|
2691
|
+
const escaped = pattern.replace(/([.+^${}()|[\\]\\])/g, '\\$1');
|
|
2692
|
+
const regexPattern = escaped.replace(/\*/g, '.*').replace(/\?/g, '.');
|
|
2693
|
+
return await this.execQuery({ [field]: { $regex: regexPattern, $options: 'i' } }, opts);
|
|
2694
|
+
}
|
|
2695
|
+
// wildcard plain term across all fields (supports * and ?)
|
|
2696
|
+
if (!q.includes(':') && (q.includes('*') || q.includes('?'))) {
|
|
2697
|
+
// build wildcard regex pattern: escape all except * and ? then convert
|
|
2698
|
+
const escaped = q.replace(/([.+^${}()|[\\]\\])/g, '\\$1');
|
|
2699
|
+
const pattern = escaped.replace(/\*/g, '.*').replace(/\?/g, '.');
|
|
2700
|
+
const orConds = searchableFields.map((f) => ({ [f]: { $regex: pattern, $options: 'i' } }));
|
|
2701
|
+
return await this.execQuery({ $or: orConds }, opts);
|
|
2702
|
+
}
|
|
2703
|
+
// implicit AND for multiple tokens: free terms, quoted phrases, and field:values
|
|
2704
|
+
{
|
|
2705
|
+
// Split query into tokens, preserving quoted substrings
|
|
2706
|
+
const rawTokens = q.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g) || [];
|
|
2707
|
+
// Only apply when more than one token and no boolean operators or grouping
|
|
2708
|
+
if (rawTokens.length > 1 &&
|
|
2709
|
+
!/(\bAND\b|\bOR\b|\bNOT\b|\(|\))/i.test(q) &&
|
|
2710
|
+
!/\[|\]/.test(q)) {
|
|
2711
|
+
const andConds = [];
|
|
2712
|
+
for (let token of rawTokens) {
|
|
2713
|
+
// field:value token
|
|
2714
|
+
const fv = token.match(/^(\w+):(.+)$/);
|
|
2715
|
+
if (fv) {
|
|
2716
|
+
const field = fv[1];
|
|
2717
|
+
let value = fv[2];
|
|
2718
|
+
if (!searchableFields.includes(field)) {
|
|
2719
|
+
throw new Error(`Field '${field}' is not searchable for class ${this.name}`);
|
|
2720
|
+
}
|
|
2721
|
+
// Strip surrounding quotes if present
|
|
2722
|
+
if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
|
|
2723
|
+
value = value.slice(1, -1);
|
|
2724
|
+
}
|
|
2725
|
+
// Wildcard search?
|
|
2726
|
+
if (value.includes('*') || value.includes('?')) {
|
|
2727
|
+
const escaped = value.replace(/([.+^${}()|[\\]\\])/g, '\\$1');
|
|
2728
|
+
const pattern = escaped.replace(/\*/g, '.*').replace(/\?/g, '.');
|
|
2729
|
+
andConds.push({ [field]: { $regex: pattern, $options: 'i' } });
|
|
2730
|
+
}
|
|
2731
|
+
else {
|
|
2732
|
+
andConds.push({ [field]: value });
|
|
2733
|
+
}
|
|
2734
|
+
}
|
|
2735
|
+
else if ((token.startsWith('"') && token.endsWith('"')) || (token.startsWith("'") && token.endsWith("'"))) {
|
|
2736
|
+
// Quoted free phrase across all fields
|
|
2737
|
+
const phrase = token.slice(1, -1);
|
|
2738
|
+
const parts = phrase.split(/\s+/).map((t) => escapeForRegex(t));
|
|
2739
|
+
const pattern = parts.join('\\s+');
|
|
2740
|
+
andConds.push({ $or: searchableFields.map((f) => ({ [f]: { $regex: pattern, $options: 'i' } })) });
|
|
2741
|
+
}
|
|
2742
|
+
else {
|
|
2743
|
+
// Free term across all fields
|
|
2744
|
+
const esc = escapeForRegex(token);
|
|
2745
|
+
andConds.push({ $or: searchableFields.map((f) => ({ [f]: { $regex: esc, $options: 'i' } })) });
|
|
2746
|
+
}
|
|
2747
|
+
}
|
|
2748
|
+
return await this.execQuery({ $and: andConds }, opts);
|
|
2749
|
+
}
|
|
2750
|
+
}
|
|
2751
|
+
// detect advanced Lucene syntax: field:value, wildcards, boolean, grouping
|
|
2752
|
+
const luceneSyntax = /(\w+:[^\s]+)|\*|\?|\bAND\b|\bOR\b|\bNOT\b|\(|\)/;
|
|
2753
|
+
if (luceneSyntax.test(q)) {
|
|
2754
|
+
const filter = this.createSearchFilter(q);
|
|
2755
|
+
return await this.execQuery(filter, opts);
|
|
2756
|
+
}
|
|
2757
|
+
// multi-term unquoted -> AND of regex across fields for each term
|
|
2758
|
+
const terms = q.split(/\s+/);
|
|
2759
|
+
if (terms.length > 1) {
|
|
2760
|
+
const andConds = terms.map((term) => {
|
|
2761
|
+
const esc = escapeForRegex(term);
|
|
2762
|
+
const ors = searchableFields.map((f) => ({ [f]: { $regex: esc, $options: 'i' } }));
|
|
2763
|
+
return { $or: ors };
|
|
2764
|
+
});
|
|
2765
|
+
return await this.execQuery({ $and: andConds }, opts);
|
|
2766
|
+
}
|
|
2767
|
+
// single term -> regex across all searchable fields
|
|
2768
|
+
const esc = escapeForRegex(q);
|
|
2769
|
+
const orConds = searchableFields.map((f) => ({ [f]: { $regex: esc, $options: 'i' } }));
|
|
2770
|
+
return await this.execQuery({ $or: orConds }, opts);
|
|
2771
|
+
}
|
|
2772
|
+
// INSTANCE
|
|
2773
|
+
// INSTANCE
|
|
2774
|
+
/**
|
|
2775
|
+
* how the Doc in memory was created, may prove useful later.
|
|
2776
|
+
*/
|
|
2777
|
+
creationStatus = 'new';
|
|
2778
|
+
/**
|
|
2779
|
+
* updated from db in any case where doc comes from db
|
|
2780
|
+
*/
|
|
2781
|
+
_createdAt = __runInitializers(this, __createdAt_initializers, new Date().toISOString());
|
|
2782
|
+
/**
|
|
2783
|
+
* will be updated everytime the doc is saved
|
|
2784
|
+
*/
|
|
2785
|
+
_updatedAt = (__runInitializers(this, __createdAt_extraInitializers), __runInitializers(this, __updatedAt_initializers, new Date().toISOString()));
|
|
2786
|
+
/**
|
|
2787
|
+
* name
|
|
2788
|
+
*/
|
|
2789
|
+
name = __runInitializers(this, __updatedAt_extraInitializers);
|
|
2790
|
+
/**
|
|
2791
|
+
* primary id in the database
|
|
2792
|
+
*/
|
|
2793
|
+
dbDocUniqueId;
|
|
2794
|
+
/**
|
|
2795
|
+
* class constructor
|
|
2796
|
+
*/
|
|
2797
|
+
constructor() {
|
|
2798
|
+
if (getOrdinaryPersistencePolicy(this.constructor)?.timestamps === 'none') {
|
|
2799
|
+
delete this._createdAt;
|
|
2800
|
+
delete this._updatedAt;
|
|
2801
|
+
}
|
|
2802
|
+
}
|
|
2803
|
+
/**
|
|
2804
|
+
* saves this instance (optionally within a transaction)
|
|
2805
|
+
*/
|
|
2806
|
+
async save(opts) {
|
|
2807
|
+
if (getOrdinaryPersistencePolicy(this.constructor)) {
|
|
2808
|
+
throw new SmartdataPersistenceError('unsupported_operation', 'Validated ordinary models use insert() or transactional postimage updates.');
|
|
2809
|
+
}
|
|
2810
|
+
const exactPersistencePolicy = this.constructor[exactPersistencePolicySymbol];
|
|
2811
|
+
if (exactPersistencePolicy) {
|
|
2812
|
+
if (exactPersistencePolicy.unsupportedSave) {
|
|
2813
|
+
return exactPersistencePolicy.unsupportedSave();
|
|
2814
|
+
}
|
|
2815
|
+
throw new Error('save() is unavailable for exact-persistence models.');
|
|
2816
|
+
}
|
|
2817
|
+
// allow hook before saving
|
|
2818
|
+
if (typeof this.beforeSave === 'function') {
|
|
2819
|
+
await this.beforeSave();
|
|
2820
|
+
}
|
|
2821
|
+
assertUsableIdentityValues(this, this.uniqueIndexes || [], this.identityValueTypes);
|
|
2822
|
+
// tslint:disable-next-line: no-this-assignment
|
|
2823
|
+
const self = this;
|
|
2824
|
+
let dbResult;
|
|
2825
|
+
// update timestamp
|
|
2826
|
+
this._updatedAt = new Date().toISOString();
|
|
2827
|
+
// perform insert or update
|
|
2828
|
+
switch (this.creationStatus) {
|
|
2829
|
+
case 'db':
|
|
2830
|
+
dbResult = await this.getCollectionSafe().update(self, { session: opts?.session });
|
|
2831
|
+
break;
|
|
2832
|
+
case 'new':
|
|
2833
|
+
dbResult = await this.getCollectionSafe().insert(self, { session: opts?.session });
|
|
2834
|
+
this.creationStatus = 'db';
|
|
2835
|
+
break;
|
|
2836
|
+
default:
|
|
2837
|
+
logger.log('error', 'neither new nor in db?');
|
|
2838
|
+
}
|
|
2839
|
+
// allow hook after saving
|
|
2840
|
+
if (typeof this.afterSave === 'function') {
|
|
2841
|
+
await this.afterSave();
|
|
2842
|
+
}
|
|
2843
|
+
return dbResult;
|
|
2844
|
+
}
|
|
2845
|
+
/**
|
|
2846
|
+
* deletes a document from the database (optionally within a transaction)
|
|
2847
|
+
*/
|
|
2848
|
+
async delete(opts) {
|
|
2849
|
+
const exactPersistencePolicy = this.constructor[exactPersistencePolicySymbol];
|
|
2850
|
+
if (exactPersistencePolicy) {
|
|
2851
|
+
if (exactPersistencePolicy.forbiddenDelete) {
|
|
2852
|
+
return exactPersistencePolicy.forbiddenDelete();
|
|
2853
|
+
}
|
|
2854
|
+
throw new Error('delete() is forbidden for exact-persistence models.');
|
|
2855
|
+
}
|
|
2856
|
+
// allow hook before deleting
|
|
2857
|
+
if (typeof this.beforeDelete === 'function') {
|
|
2858
|
+
await this.beforeDelete();
|
|
2859
|
+
}
|
|
2860
|
+
// perform deletion
|
|
2861
|
+
const result = await this.getCollectionSafe().delete(this, { session: opts?.session });
|
|
2862
|
+
// allow hook after delete
|
|
2863
|
+
if (typeof this.afterDelete === 'function') {
|
|
2864
|
+
await this.afterDelete();
|
|
2865
|
+
}
|
|
2866
|
+
return result;
|
|
2867
|
+
}
|
|
2868
|
+
/**
|
|
2869
|
+
* also store any referenced objects to DB
|
|
2870
|
+
* better for data consistency
|
|
2871
|
+
*/
|
|
2872
|
+
saveDeep(savedMapArg) {
|
|
2873
|
+
if (!savedMapArg) {
|
|
2874
|
+
savedMapArg = new plugins.lik.ObjectMap();
|
|
2875
|
+
}
|
|
2876
|
+
savedMapArg.add(this);
|
|
2877
|
+
this.save();
|
|
2878
|
+
for (const propertyKey of Object.keys(this)) {
|
|
2879
|
+
const property = this[propertyKey];
|
|
2880
|
+
if (property instanceof SmartDataDbDoc && !savedMapArg.checkForObject(property)) {
|
|
2881
|
+
property.saveDeep(savedMapArg);
|
|
2882
|
+
}
|
|
2883
|
+
}
|
|
2884
|
+
}
|
|
2885
|
+
/**
|
|
2886
|
+
* updates an object from db
|
|
2887
|
+
*/
|
|
2888
|
+
async updateFromDb() {
|
|
2889
|
+
const identifiableObject = await this.createIdentifiableObject();
|
|
2890
|
+
if (Object.keys(identifiableObject).length === 0) {
|
|
2891
|
+
throw new SmartdataPersistenceError('invalid_configuration', 'updateFromDb() requires declared identity fields; without them the lookup would read an arbitrary document.');
|
|
2892
|
+
}
|
|
2893
|
+
const mongoDbNativeDoc = await this.getCollectionSafe().findOne(identifiableObject);
|
|
2894
|
+
if (!mongoDbNativeDoc) {
|
|
2895
|
+
return false; // Document not found in database
|
|
2896
|
+
}
|
|
2897
|
+
if (getOrdinaryPersistencePolicy(this.constructor)) {
|
|
2898
|
+
const hydrated = this.constructor.createInstanceFromMongoDbNativeDoc(mongoDbNativeDoc);
|
|
2899
|
+
for (const field of [...(this.saveableProperties || []), '_id', '_createdAt', '_updatedAt']) {
|
|
2900
|
+
if (!Object.prototype.hasOwnProperty.call(hydrated, field))
|
|
2901
|
+
delete this[field];
|
|
2902
|
+
}
|
|
2903
|
+
Object.assign(this, hydrated);
|
|
2904
|
+
return true;
|
|
2905
|
+
}
|
|
2906
|
+
for (const key of Object.keys(mongoDbNativeDoc)) {
|
|
2907
|
+
const rawValue = mongoDbNativeDoc[key];
|
|
2908
|
+
const optionsMap = this.constructor._svDbOptions || {};
|
|
2909
|
+
const opts = optionsMap[key];
|
|
2910
|
+
this[key] = opts && typeof opts.deserialize === 'function'
|
|
2911
|
+
? opts.deserialize(rawValue)
|
|
2912
|
+
: rawValue;
|
|
2913
|
+
}
|
|
2914
|
+
return true;
|
|
2915
|
+
}
|
|
2916
|
+
/**
|
|
2917
|
+
* creates a saveable object so the instance can be persisted as json in the database
|
|
2918
|
+
*
|
|
2919
|
+
* Properties whose value is `undefined` are omitted entirely rather than
|
|
2920
|
+
* written as BSON null, so "absent" stays representable. Explicit `null` is
|
|
2921
|
+
* untouched and remains storable wherever the field type allows it.
|
|
2922
|
+
*/
|
|
2923
|
+
async createSavableObject() {
|
|
2924
|
+
if (getOrdinaryPersistencePolicy(this.constructor)?.timestamps === 'none' &&
|
|
2925
|
+
(Object.prototype.hasOwnProperty.call(this, '_createdAt') ||
|
|
2926
|
+
Object.prototype.hasOwnProperty.call(this, '_updatedAt'))) {
|
|
2927
|
+
throw new SmartdataPersistenceError('invalid_document', 'This ordinary persistence policy forbids managed timestamps.');
|
|
2928
|
+
}
|
|
2929
|
+
assertUsableIdentityValues(this, this.uniqueIndexes || [], this.identityValueTypes);
|
|
2930
|
+
const saveableObject = {}; // is not exposed to outside, so any is ok here
|
|
2931
|
+
const globalProps = this.globalSaveableProperties || [];
|
|
2932
|
+
const specificProps = this.saveableProperties || [];
|
|
2933
|
+
const policy = getOrdinaryPersistencePolicy(this.constructor);
|
|
2934
|
+
const saveableProperties = [...new Set([
|
|
2935
|
+
...globalProps, ...specificProps, ...(policy ? ['_id'] : []),
|
|
2936
|
+
])].filter((fieldArg) => policy?.timestamps !== 'none' ||
|
|
2937
|
+
!['_createdAt', '_updatedAt'].includes(fieldArg));
|
|
2938
|
+
// apply custom serialization if configured
|
|
2939
|
+
const optionsMap = this.constructor._svDbOptions || {};
|
|
2940
|
+
for (const propertyNameString of saveableProperties) {
|
|
2941
|
+
const rawValue = this[propertyNameString];
|
|
2942
|
+
const opts = optionsMap[propertyNameString];
|
|
2943
|
+
const serializedValue = opts && typeof opts.serialize === 'function'
|
|
2944
|
+
? opts.serialize(rawValue)
|
|
2945
|
+
: rawValue;
|
|
2946
|
+
if (serializedValue === undefined) {
|
|
2947
|
+
// an undefined property means "absent" - skip it so the driver cannot
|
|
2948
|
+
// turn it into BSON null during serialization
|
|
2949
|
+
continue;
|
|
2950
|
+
}
|
|
2951
|
+
saveableObject[propertyNameString] = stripUndefinedValues(serializedValue);
|
|
2952
|
+
}
|
|
2953
|
+
return saveableObject;
|
|
2954
|
+
}
|
|
2955
|
+
/**
|
|
2956
|
+
* creates an identifiable object for operations that require filtering
|
|
2957
|
+
*/
|
|
2958
|
+
async createIdentifiableObject() {
|
|
2959
|
+
assertUsableIdentityValues(this, this.uniqueIndexes || [], this.identityValueTypes);
|
|
2960
|
+
const identifiableObject = {}; // is not exposed to outside, so any is ok here
|
|
2961
|
+
for (const propertyNameString of this.uniqueIndexes || []) {
|
|
2962
|
+
identifiableObject[propertyNameString] = this[propertyNameString];
|
|
2963
|
+
}
|
|
2964
|
+
if (getOrdinaryPersistencePolicy(this.constructor)?.idType === 'string') {
|
|
2965
|
+
const id = this._id;
|
|
2966
|
+
if (typeof id !== 'string' || id.trim().length === 0) {
|
|
2967
|
+
throw new SmartdataPersistenceError('invalid_argument', 'String primary ID is required.');
|
|
2968
|
+
}
|
|
2969
|
+
identifiableObject._id = id;
|
|
2970
|
+
}
|
|
2971
|
+
return identifiableObject;
|
|
2972
|
+
}
|
|
2973
|
+
};
|
|
2974
|
+
})();
|
|
2975
|
+
export { SmartDataDbDoc };
|
|
2976
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5kb2MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9ub3NxbGRiL2NsYXNzZXMuZG9jLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUV4QyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDOUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUN0QyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUNsRSxPQUFPLEVBQ0wscUJBQXFCLEdBQ3RCLE1BQU0sOEJBQThCLENBQUM7QUFDdEMsT0FBTyxFQUNMLG9DQUFvQyxHQUNyQyxNQUFNLG9DQUFvQyxDQUFDO0FBQzVDLE9BQU8sRUFBRSw0QkFBNEIsRUFBRSw4QkFBOEIsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ2hILE9BQU8sRUFDTCxzQkFBc0IsRUFBRSw2QkFBNkIsR0FHdEQsTUFBTSwrQkFBK0IsQ0FBQztBQUN2QyxPQUFPLEVBR0wsbUJBQW1CLEdBQ3BCLE1BQU0seUJBQXlCLENBQUM7QUFDakMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDMUQsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDckUsT0FBTyxFQUFFLG1CQUFtQixFQUFFLHVCQUF1QixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDekYsT0FBTyxFQUFFLDZCQUE2QixFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDcEYsT0FBTyxFQUFFLG1CQUFtQixFQUFFLHVCQUF1QixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDekYsT0FBTyxFQUNMLHlCQUF5QixHQUMxQixNQUFN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
|