@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,246 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { SmartdataPersistenceError, normalizeOrdinaryPersistenceError, } from './classes.persistence.js';
|
|
3
|
+
const bindings = new WeakMap();
|
|
4
|
+
const bindingsByOwner = new WeakMap();
|
|
5
|
+
const smartdataSessionInvalidationAggregateBrand = Symbol('smartdataSessionInvalidationAggregate');
|
|
6
|
+
class SmartdataSessionInvalidationAggregateError extends AggregateError {
|
|
7
|
+
[smartdataSessionInvalidationAggregateBrand] = true;
|
|
8
|
+
}
|
|
9
|
+
const transactionContext = new plugins.nodeAsyncHooks.AsyncLocalStorage();
|
|
10
|
+
const resolveBinding = (sessionArg, ownerArg) => {
|
|
11
|
+
const binding = bindings.get(sessionArg);
|
|
12
|
+
if (!binding || binding.invalidated || binding.rawSession.hasEnded) {
|
|
13
|
+
throw new SmartdataPersistenceError('unsupported_operation', 'The SmartData session has ended or is no longer valid.');
|
|
14
|
+
}
|
|
15
|
+
if (ownerArg && binding.owner !== ownerArg) {
|
|
16
|
+
throw new SmartdataPersistenceError('invalid_argument', 'The SmartData session belongs to another database.');
|
|
17
|
+
}
|
|
18
|
+
if (binding.owner.status !== 'connected'
|
|
19
|
+
|| binding.owner.mongoDbClient !== binding.client) {
|
|
20
|
+
throw new SmartdataPersistenceError('unsupported_operation', 'The SmartData session belongs to a stale database lifecycle.');
|
|
21
|
+
}
|
|
22
|
+
return binding;
|
|
23
|
+
};
|
|
24
|
+
const assertTransactionSucceeded = (bindingArg) => {
|
|
25
|
+
if (bindingArg.transactionFailure) {
|
|
26
|
+
throw bindingArg.transactionFailure.error;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
export class SmartdataSession {
|
|
30
|
+
async withTransaction(callbackArg) {
|
|
31
|
+
if (typeof callbackArg !== 'function') {
|
|
32
|
+
throw new SmartdataPersistenceError('invalid_argument', 'SmartData transaction callback must be a function.');
|
|
33
|
+
}
|
|
34
|
+
const binding = resolveBinding(this);
|
|
35
|
+
if (binding.operationActive || binding.transactionActive) {
|
|
36
|
+
throw new SmartdataPersistenceError('unsupported_operation', 'Parallel or nested SmartData session operations are not supported.');
|
|
37
|
+
}
|
|
38
|
+
binding.transactionActive = true;
|
|
39
|
+
let callbackError;
|
|
40
|
+
try {
|
|
41
|
+
return await binding.rawSession.withTransaction(async () => {
|
|
42
|
+
const attempt = Symbol('smartdataTransactionAttempt');
|
|
43
|
+
binding.transactionAttempt = attempt;
|
|
44
|
+
binding.transactionCallbackOpen = true;
|
|
45
|
+
binding.transactionUsesOrdinaryWrite = false;
|
|
46
|
+
binding.transactionFailure = undefined;
|
|
47
|
+
callbackError = undefined;
|
|
48
|
+
try {
|
|
49
|
+
let callbackReturned = false;
|
|
50
|
+
try {
|
|
51
|
+
const result = await transactionContext.run({ contextToken: binding.contextToken, attempt }, async () => callbackArg(this));
|
|
52
|
+
callbackReturned = true;
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
const activeOperation = binding.operationActive
|
|
57
|
+
? binding.operationSettled
|
|
58
|
+
: undefined;
|
|
59
|
+
binding.transactionCallbackOpen = false;
|
|
60
|
+
if (binding.transactionAttempt === attempt) {
|
|
61
|
+
binding.transactionAttempt = undefined;
|
|
62
|
+
}
|
|
63
|
+
if (activeOperation) {
|
|
64
|
+
await activeOperation;
|
|
65
|
+
}
|
|
66
|
+
assertTransactionSucceeded(binding);
|
|
67
|
+
if (callbackReturned && activeOperation) {
|
|
68
|
+
throw new SmartdataPersistenceError('unsupported_operation', 'A SmartData transaction callback returned with an operation still active.');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch (errorArg) {
|
|
73
|
+
callbackError = errorArg;
|
|
74
|
+
throw errorArg;
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
catch (errorArg) {
|
|
79
|
+
if (errorArg === callbackError) {
|
|
80
|
+
throw errorArg;
|
|
81
|
+
}
|
|
82
|
+
if (binding.transactionUsesOrdinaryWrite) {
|
|
83
|
+
return normalizeOrdinaryPersistenceError(errorArg, 'SmartData transaction conflicts with a unique index.');
|
|
84
|
+
}
|
|
85
|
+
throw errorArg;
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
binding.transactionActive = false;
|
|
89
|
+
binding.transactionUsesOrdinaryWrite = false;
|
|
90
|
+
binding.transactionFailure = undefined;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async close() {
|
|
94
|
+
const binding = bindings.get(this);
|
|
95
|
+
if (!binding) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (binding.operationActive || binding.transactionActive) {
|
|
99
|
+
throw new SmartdataPersistenceError('unsupported_operation', 'Cannot close a SmartData session while an operation is active.');
|
|
100
|
+
}
|
|
101
|
+
await closeSessionBinding(binding);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
export const createSmartdataSession = (ownerArg) => {
|
|
105
|
+
if (ownerArg.status !== 'connected' || !ownerArg.mongoDbClient) {
|
|
106
|
+
throw new SmartdataPersistenceError('unsupported_operation', 'Cannot create a SmartData session before the database is connected.');
|
|
107
|
+
}
|
|
108
|
+
const session = new SmartdataSession();
|
|
109
|
+
const binding = {
|
|
110
|
+
session,
|
|
111
|
+
contextToken: Symbol('smartdataSessionContext'),
|
|
112
|
+
owner: ownerArg,
|
|
113
|
+
client: ownerArg.mongoDbClient,
|
|
114
|
+
rawSession: ownerArg.mongoDbClient.startSession(),
|
|
115
|
+
operationActive: false,
|
|
116
|
+
transactionActive: false,
|
|
117
|
+
transactionCallbackOpen: false,
|
|
118
|
+
transactionUsesOrdinaryWrite: false,
|
|
119
|
+
invalidated: false,
|
|
120
|
+
};
|
|
121
|
+
bindings.set(session, binding);
|
|
122
|
+
let ownerBindings = bindingsByOwner.get(ownerArg);
|
|
123
|
+
if (!ownerBindings) {
|
|
124
|
+
ownerBindings = new Set();
|
|
125
|
+
bindingsByOwner.set(ownerArg, ownerBindings);
|
|
126
|
+
}
|
|
127
|
+
ownerBindings.add(binding);
|
|
128
|
+
return session;
|
|
129
|
+
};
|
|
130
|
+
export const acquireSmartdataSession = (sessionArg, ownerArg, optionsArg = {}) => {
|
|
131
|
+
const binding = resolveBinding(sessionArg, ownerArg);
|
|
132
|
+
if (binding.transactionFailure) {
|
|
133
|
+
throw new SmartdataPersistenceError('unsupported_operation', 'The SmartData transaction attempt has aborted and cannot accept further operations.');
|
|
134
|
+
}
|
|
135
|
+
const currentContext = transactionContext.getStore();
|
|
136
|
+
const isOwnedTransactionContext = currentContext?.contextToken === binding.contextToken;
|
|
137
|
+
if (binding.operationActive
|
|
138
|
+
|| (binding.transactionActive
|
|
139
|
+
&& (!binding.transactionCallbackOpen
|
|
140
|
+
|| !isOwnedTransactionContext
|
|
141
|
+
|| currentContext.attempt !== binding.transactionAttempt))
|
|
142
|
+
|| (!binding.transactionActive && isOwnedTransactionContext)) {
|
|
143
|
+
throw new SmartdataPersistenceError('unsupported_operation', 'Parallel SmartData session operations are not supported.');
|
|
144
|
+
}
|
|
145
|
+
if (optionsArg.ordinaryWrite && binding.transactionActive) {
|
|
146
|
+
binding.transactionUsesOrdinaryWrite = true;
|
|
147
|
+
}
|
|
148
|
+
binding.operationActive = true;
|
|
149
|
+
binding.operationSettled = new Promise((resolveArg) => {
|
|
150
|
+
binding.resolveOperationSettled = resolveArg;
|
|
151
|
+
});
|
|
152
|
+
let released = false;
|
|
153
|
+
return {
|
|
154
|
+
rawSession: binding.rawSession,
|
|
155
|
+
release: () => {
|
|
156
|
+
if (!released) {
|
|
157
|
+
released = true;
|
|
158
|
+
binding.operationActive = false;
|
|
159
|
+
binding.resolveOperationSettled?.();
|
|
160
|
+
binding.operationSettled = undefined;
|
|
161
|
+
binding.resolveOperationSettled = undefined;
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
};
|
|
166
|
+
/** Marks the current owned attempt for rollback by withTransaction. */
|
|
167
|
+
export const failSmartdataTransaction = (sessionArg, ownerArg, errorArg) => {
|
|
168
|
+
const binding = resolveBinding(sessionArg, ownerArg);
|
|
169
|
+
const context = transactionContext.getStore();
|
|
170
|
+
if (!binding.operationActive
|
|
171
|
+
|| !binding.transactionActive
|
|
172
|
+
|| context?.contextToken !== binding.contextToken
|
|
173
|
+
|| context.attempt !== binding.transactionAttempt) {
|
|
174
|
+
throw new SmartdataPersistenceError('unsupported_operation', 'Only the active owned operation can abort a SmartData transaction attempt.');
|
|
175
|
+
}
|
|
176
|
+
binding.transactionFailure ??= { error: errorArg };
|
|
177
|
+
throw binding.transactionFailure.error;
|
|
178
|
+
};
|
|
179
|
+
export const isSmartdataSession = (sessionArg) => sessionArg instanceof SmartdataSession;
|
|
180
|
+
export const isOrdinarySessionInTransaction = (sessionArg) => {
|
|
181
|
+
if (!sessionArg) {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
if (isSmartdataSession(sessionArg)) {
|
|
185
|
+
return resolveBinding(sessionArg).transactionActive;
|
|
186
|
+
}
|
|
187
|
+
return sessionArg.inTransaction();
|
|
188
|
+
};
|
|
189
|
+
export const runWithOrdinarySmartdataSession = async (sessionArg, ownerArg, optionsArg, operationArg) => {
|
|
190
|
+
if (!isSmartdataSession(sessionArg)) {
|
|
191
|
+
return operationArg(sessionArg);
|
|
192
|
+
}
|
|
193
|
+
if (!optionsArg.prepared) {
|
|
194
|
+
throw new SmartdataPersistenceError('unsupported_operation', optionsArg.preparationMessage ||
|
|
195
|
+
'Initialize every participating SmartData model before using an owned session.');
|
|
196
|
+
}
|
|
197
|
+
const lease = acquireSmartdataSession(sessionArg, ownerArg, {
|
|
198
|
+
ordinaryWrite: optionsArg.ordinaryWrite,
|
|
199
|
+
});
|
|
200
|
+
try {
|
|
201
|
+
return await operationArg(lease.rawSession);
|
|
202
|
+
}
|
|
203
|
+
finally {
|
|
204
|
+
lease.release();
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
export const invalidateSmartdataSessions = async (ownerArg) => {
|
|
208
|
+
const ownerBindings = bindingsByOwner.get(ownerArg);
|
|
209
|
+
if (!ownerBindings) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
const sessions = [...ownerBindings];
|
|
213
|
+
for (const bindingArg of sessions) {
|
|
214
|
+
bindingArg.invalidated = true;
|
|
215
|
+
}
|
|
216
|
+
const results = await Promise.allSettled(sessions.map((bindingArg) => closeSessionBinding(bindingArg)));
|
|
217
|
+
const errors = results.flatMap((resultArg) => resultArg.status === 'rejected' ? [resultArg.reason] : []);
|
|
218
|
+
if (errors.length === 1) {
|
|
219
|
+
throw errors[0];
|
|
220
|
+
}
|
|
221
|
+
if (errors.length > 1) {
|
|
222
|
+
throw new SmartdataSessionInvalidationAggregateError(errors, 'Multiple SmartData sessions failed to close.');
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
/** Failed cleanup remains owned and invalidated until an explicit retry succeeds. */
|
|
226
|
+
const closeSessionBinding = async (bindingArg) => {
|
|
227
|
+
if (bindingArg.closing)
|
|
228
|
+
return bindingArg.closing;
|
|
229
|
+
bindingArg.invalidated = true;
|
|
230
|
+
const closing = Promise.resolve().then(async () => {
|
|
231
|
+
await bindingArg.rawSession.endSession();
|
|
232
|
+
bindingsByOwner.get(bindingArg.owner)?.delete(bindingArg);
|
|
233
|
+
bindings.delete(bindingArg.session);
|
|
234
|
+
});
|
|
235
|
+
bindingArg.closing = closing;
|
|
236
|
+
try {
|
|
237
|
+
await closing;
|
|
238
|
+
}
|
|
239
|
+
finally {
|
|
240
|
+
bindingArg.closing = undefined;
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
export const unwrapSmartdataSessionInvalidationErrors = (errorArg) => errorArg instanceof SmartdataSessionInvalidationAggregateError
|
|
244
|
+
? errorArg.errors
|
|
245
|
+
: undefined;
|
|
246
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zZXNzaW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvbm9zcWxkYi9jbGFzc2VzLnNlc3Npb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFHeEMsT0FBTyxFQUNMLHlCQUF5QixFQUN6QixpQ0FBaUMsR0FDbEMsTUFBTSwwQkFBMEIsQ0FBQztBQW9CbEMsTUFBTSxRQUFRLEdBQUcsSUFBSSxPQUFPLEVBQThDLENBQUM7QUFDM0UsTUFBTSxlQUFlLEdBQUcsSUFBSSxPQUFPLEVBQThDLENBQUM7QUFDbEYsTUFBTSwwQ0FBMEMsR0FBRyxNQUFNLENBQ3ZELHVDQUF1QyxDQUN4QyxDQUFDO0FBRUYsTUFBTSwwQ0FBMkMsU0FBUSxjQUFjO0lBQ3JELENBQUMsMENBQTBDLENBQUMsR0FBRyxJQUFJLENBQUM7Q0FDckU7QUFnQkQsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLE9BQU8sQ0FBQyxjQUFjLENBQUMsaUJBQWlCLEVBRXBFLENBQUM7QUFFSixNQUFNLGNBQWMsR0FBRyxDQUNyQixVQUE0QixFQUM1QixRQUFzQixFQUNJLEVBQUU7SUFDNUIsTUFBTSxPQUFPLEdBQUcsUUFBUSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUN6QyxJQUFJLENBQUMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxXQUFXLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNuRSxNQUFNLElBQUkseUJBQXlCLENBQ2pDLHVCQUF1QixFQUN2Qix3REFBd0QsQ0FDekQsQ0FBQztJQUNKLENBQUM7SUFDRCxJQUFJLFFBQVEsSUFBSSxPQUFPLENBQUMsS0FBSyxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQzNDLE1BQU0sSUFBSSx5QkFBeUIsQ0FDakMsa0JBQWtCLEVBQ2xCLG9EQUFvRCxDQUNyRCxDQUFDO0lBQ0osQ0FBQztJQUNELElBQ0UsT0FBTyxD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
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { SmartdataDb } from './classes.db.js';
|
|
2
|
+
import { type SmartdataSession } from './classes.session.js';
|
|
3
|
+
export interface ISmartdataStoredInspectionOptions {
|
|
4
|
+
filter?: Record<string, unknown>;
|
|
5
|
+
/** Default 100, maximum 10000. Results are ordered by immutable _id. */
|
|
6
|
+
limit?: number;
|
|
7
|
+
skip?: number;
|
|
8
|
+
/** Default 4 MiB, maximum 64 MiB; overflow rejects the entire page. */
|
|
9
|
+
maxBytes?: number;
|
|
10
|
+
/** Default 5000ms, maximum 120000ms. */
|
|
11
|
+
timeoutMS?: number;
|
|
12
|
+
signal?: AbortSignal;
|
|
13
|
+
session?: SmartdataSession;
|
|
14
|
+
}
|
|
15
|
+
export interface ISmartdataStoredInspection {
|
|
16
|
+
readonly documents: readonly Readonly<Record<string, unknown>>[];
|
|
17
|
+
readonly hasMore: boolean;
|
|
18
|
+
}
|
|
19
|
+
export type TSmartdataOrdinaryDocumentEvidence = {
|
|
20
|
+
readonly status: 'valid';
|
|
21
|
+
} | {
|
|
22
|
+
readonly status: 'invalid';
|
|
23
|
+
readonly code: 'invalid_document';
|
|
24
|
+
} | {
|
|
25
|
+
readonly status: 'not_configured';
|
|
26
|
+
};
|
|
27
|
+
export interface ISmartdataStoredDocumentEvidence {
|
|
28
|
+
/** Untouched stored BSON for diagnosis, never an authorized application record. */
|
|
29
|
+
readonly document: Readonly<Record<string, unknown>>;
|
|
30
|
+
/** Reports only the model's ordinary persistence assertion, not exact/domain assertions. */
|
|
31
|
+
readonly ordinaryValidation: TSmartdataOrdinaryDocumentEvidence;
|
|
32
|
+
}
|
|
33
|
+
export interface ISmartdataStoredEvidenceInspection {
|
|
34
|
+
readonly evidence: readonly ISmartdataStoredDocumentEvidence[];
|
|
35
|
+
readonly hasMore: boolean;
|
|
36
|
+
}
|
|
37
|
+
/** @internal Strict inspection used by Model.inspectStoredDocuments. */
|
|
38
|
+
export declare const inspectStoredDocuments: (modelArg: any, dbArg: SmartdataDb, opts?: ISmartdataStoredInspectionOptions) => Promise<ISmartdataStoredInspection>;
|
|
39
|
+
/**
|
|
40
|
+
* @internal Diagnostic inspection preserves malformed evidence from the same
|
|
41
|
+
* model and bounds as strict inspection. Invalid records must never enter
|
|
42
|
+
* normal application flows. Exact and domain assertions remain caller-owned.
|
|
43
|
+
*/
|
|
44
|
+
export declare const inspectStoredDocumentEvidence: (modelArg: any, dbArg: SmartdataDb, opts?: ISmartdataStoredInspectionOptions) => Promise<ISmartdataStoredEvidenceInspection>;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { convertFilterForMongoDb } from './classes.doc.js';
|
|
3
|
+
import { SmartdataPersistenceError } from './classes.persistence.js';
|
|
4
|
+
import { runCursorOperation } from './classes.cursoroperation.js';
|
|
5
|
+
import { acquireSmartdataSession, isSmartdataSession } from './classes.session.js';
|
|
6
|
+
import { collectionTopologyDbInspectionSymbol, collectionModelSchemaResolverSymbol, } from './classes.collectiontopology.js';
|
|
7
|
+
import { validateOrdinaryStoredDocument } from './classes.ordinarypersistence.js';
|
|
8
|
+
/** No model binding, index initialization, hydration, or raw handle escapes. */
|
|
9
|
+
const readStoredDocuments = async (modelArg, dbArg, opts = {}) => {
|
|
10
|
+
if (!opts || Object.getPrototypeOf(opts) !== Object.prototype ||
|
|
11
|
+
Reflect.ownKeys(opts).some((keyArg) => typeof keyArg !== 'string' ||
|
|
12
|
+
!['filter', 'limit', 'skip', 'maxBytes', 'timeoutMS', 'signal', 'session'].includes(keyArg) ||
|
|
13
|
+
!('value' in Object.getOwnPropertyDescriptor(opts, keyArg)))) {
|
|
14
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Invalid stored inspection options.');
|
|
15
|
+
}
|
|
16
|
+
const limit = opts.limit === undefined ? 100 : opts.limit;
|
|
17
|
+
const skip = opts.skip === undefined ? 0 : opts.skip;
|
|
18
|
+
const maxBytes = opts.maxBytes === undefined ? 4 * 1024 * 1024 : opts.maxBytes;
|
|
19
|
+
const timeoutMS = opts.timeoutMS === undefined ? 5_000 : opts.timeoutMS;
|
|
20
|
+
if (!Number.isSafeInteger(limit) || limit < 1 || limit > 10_000 ||
|
|
21
|
+
!Number.isSafeInteger(skip) || skip < 0 || skip > 2_147_483_647 ||
|
|
22
|
+
!Number.isSafeInteger(maxBytes) || maxBytes < 1 || maxBytes > 64 * 1024 * 1024 ||
|
|
23
|
+
!Number.isSafeInteger(timeoutMS) || timeoutMS < 1 || timeoutMS > 120_000 ||
|
|
24
|
+
(opts.signal !== undefined && !(opts.signal instanceof AbortSignal)) ||
|
|
25
|
+
(opts.session !== undefined && !isSmartdataSession(opts.session))) {
|
|
26
|
+
throw new SmartdataPersistenceError('invalid_argument', 'Invalid stored inspection bounds or context.');
|
|
27
|
+
}
|
|
28
|
+
opts.signal?.throwIfAborted();
|
|
29
|
+
const schema = modelArg[collectionModelSchemaResolverSymbol]();
|
|
30
|
+
const filter = convertFilterForMongoDb(opts.filter || {});
|
|
31
|
+
const lease = opts.session ? acquireSmartdataSession(opts.session, dbArg) : undefined;
|
|
32
|
+
let page;
|
|
33
|
+
try {
|
|
34
|
+
page = await dbArg[collectionTopologyDbInspectionSymbol](async (mongoDbArg) => {
|
|
35
|
+
const cursor = mongoDbArg.collection(schema.collectionName).find(filter, {
|
|
36
|
+
sort: { _id: 1 }, skip, limit: limit + 1, batchSize: 1,
|
|
37
|
+
timeoutMS, timeoutMode: 'cursorLifetime', signal: opts.signal, session: lease?.rawSession,
|
|
38
|
+
});
|
|
39
|
+
return runCursorOperation(cursor, async (cursorArg) => {
|
|
40
|
+
const documents = [];
|
|
41
|
+
let bytes = 0;
|
|
42
|
+
while (true) {
|
|
43
|
+
const next = await cursorArg.next();
|
|
44
|
+
if (next === null)
|
|
45
|
+
return { documents, hasMore: false };
|
|
46
|
+
if (documents.length === limit)
|
|
47
|
+
return { documents, hasMore: true };
|
|
48
|
+
bytes += plugins.mongodb.BSON.calculateObjectSize(next);
|
|
49
|
+
if (bytes > maxBytes)
|
|
50
|
+
throw new SmartdataPersistenceError('unsupported_operation', 'Stored inspection exceeds its byte budget.');
|
|
51
|
+
documents.push(next);
|
|
52
|
+
}
|
|
53
|
+
}, opts.signal);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
catch (errorArg) {
|
|
57
|
+
opts.signal?.throwIfAborted();
|
|
58
|
+
throw errorArg;
|
|
59
|
+
}
|
|
60
|
+
finally {
|
|
61
|
+
lease?.release();
|
|
62
|
+
}
|
|
63
|
+
return { schema, page };
|
|
64
|
+
};
|
|
65
|
+
/** @internal Strict inspection used by Model.inspectStoredDocuments. */
|
|
66
|
+
export const inspectStoredDocuments = async (modelArg, dbArg, opts = {}) => {
|
|
67
|
+
const { schema, page } = await readStoredDocuments(modelArg, dbArg, opts);
|
|
68
|
+
// Full validation occurs on the untouched stored envelope, before any
|
|
69
|
+
// constructor/default/serializer can hide field-presence evidence.
|
|
70
|
+
const documents = schema.ordinaryPersistence
|
|
71
|
+
? page.documents.map((documentArg) => validateOrdinaryStoredDocument(documentArg, schema.ordinaryPersistence, schema.persistedFields))
|
|
72
|
+
: page.documents;
|
|
73
|
+
return Object.freeze({ documents: Object.freeze(documents), hasMore: page.hasMore });
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* @internal Diagnostic inspection preserves malformed evidence from the same
|
|
77
|
+
* model and bounds as strict inspection. Invalid records must never enter
|
|
78
|
+
* normal application flows. Exact and domain assertions remain caller-owned.
|
|
79
|
+
*/
|
|
80
|
+
export const inspectStoredDocumentEvidence = async (modelArg, dbArg, opts = {}) => {
|
|
81
|
+
const { schema, page } = await readStoredDocuments(modelArg, dbArg, opts);
|
|
82
|
+
const evidence = page.documents.map((documentArg) => {
|
|
83
|
+
let ordinaryValidation = { status: 'not_configured' };
|
|
84
|
+
if (schema.ordinaryPersistence) {
|
|
85
|
+
try {
|
|
86
|
+
validateOrdinaryStoredDocument(documentArg, schema.ordinaryPersistence, schema.persistedFields);
|
|
87
|
+
ordinaryValidation = { status: 'valid' };
|
|
88
|
+
}
|
|
89
|
+
catch (errorArg) {
|
|
90
|
+
if (!(errorArg instanceof SmartdataPersistenceError) || errorArg.code !== 'invalid_document') {
|
|
91
|
+
throw errorArg;
|
|
92
|
+
}
|
|
93
|
+
ordinaryValidation = { status: 'invalid', code: 'invalid_document' };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return Object.freeze({ document: documentArg, ordinaryValidation: Object.freeze(ordinaryValidation) });
|
|
97
|
+
});
|
|
98
|
+
return Object.freeze({ evidence: Object.freeze(evidence), hasMore: page.hasMore });
|
|
99
|
+
};
|
|
100
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zdG9yZWRpbnNwZWN0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvbm9zcWxkYi9jbGFzc2VzLnN0b3JlZGluc3BlY3Rpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFFeEMsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDM0QsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDckUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDbEUsT0FBTyxFQUFFLHVCQUF1QixFQUFFLGtCQUFrQixFQUF5QixNQUFNLHNCQUFzQixDQUFDO0FBQzFHLE9BQU8sRUFDTCxvQ0FBb0MsRUFBRSxtQ0FBbUMsR0FDMUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUV6QyxPQUFPLEVBQUUsOEJBQThCLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQXFDbEYsZ0ZBQWdGO0FBQ2hGLE1BQU0sbUJBQW1CLEdBQUcsS0FBSyxFQUMvQixRQUFhLEVBQ2IsS0FBa0IsRUFDbEIsT0FBMEMsRUFBRSxFQUkzQyxFQUFFO0lBQ0gsSUFBSSxDQUFDLElBQUksSUFBSSxNQUFNLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxLQUFLLE1BQU0sQ0FBQyxTQUFTO1FBQzNELE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxPQUFPLE1BQU0sS0FBSyxRQUFRO1lBQy9ELENBQUMsQ0FBQyxRQUFRLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsV0FBVyxFQUFFLFFBQVEsRUFBRSxTQUFTLENBQUMsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDO1lBQzNGLENBQUMsQ0FBQyxPQUFPLElBQUksTUFBTSxDQUFDLHdCQUF3QixDQUFD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
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { SmartdataDb } from './classes.db.js';
|
|
2
|
+
import { SmartDataDbDoc } from './classes.doc.js';
|
|
3
|
+
import { SmartdataPersistenceError } from './classes.persistence.js';
|
|
4
|
+
export interface ISmartdataTestConnection {
|
|
5
|
+
/** Literal loopback IPv4, ::1, or localhost (normalized to 127.0.0.1). */
|
|
6
|
+
host: string;
|
|
7
|
+
port: number;
|
|
8
|
+
/** Supply both credentials or neither. Authentication uses admin. */
|
|
9
|
+
username?: string;
|
|
10
|
+
password?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface ISmartdataTestDatabaseOptions {
|
|
13
|
+
connection: ISmartdataTestConnection;
|
|
14
|
+
/** Default 5000; maximum 120000 ms, shared by connection and ownership checks. */
|
|
15
|
+
timeoutMs?: number;
|
|
16
|
+
signal?: AbortSignal;
|
|
17
|
+
}
|
|
18
|
+
export interface ISmartdataStoredDocumentFaultOptions {
|
|
19
|
+
/** Default 64 KiB, maximum 1 MiB. */
|
|
20
|
+
maxBytes?: number;
|
|
21
|
+
/** Default 5000; maximum 120000 ms, including collection preparation. */
|
|
22
|
+
timeoutMs?: number;
|
|
23
|
+
signal?: AbortSignal;
|
|
24
|
+
}
|
|
25
|
+
export interface ISmartdataIndexFaultOptions {
|
|
26
|
+
/** Default 5000; maximum 120000 ms, shared by topology verification and removal. */
|
|
27
|
+
timeoutMs?: number;
|
|
28
|
+
signal?: AbortSignal;
|
|
29
|
+
}
|
|
30
|
+
export type TSmartdataTestModel = Pick<typeof SmartDataDbDoc, 'prototype' | 'collection' | 'getExpectedCollectionTopology' | 'prepareCollection'> & (abstract new (...args: never[]) => object);
|
|
31
|
+
/** Construction failed and cleanup also failed. Explicit close retries the retained owner. */
|
|
32
|
+
export declare class SmartdataTestDatabaseCreationError extends SmartdataPersistenceError {
|
|
33
|
+
#private;
|
|
34
|
+
constructor(cleanupArg: () => Promise<void>);
|
|
35
|
+
close(): Promise<void>;
|
|
36
|
+
}
|
|
37
|
+
/** Disposable fault injection is available only through the testsupport package subpath. */
|
|
38
|
+
export declare class SmartdataTestDatabase {
|
|
39
|
+
#private;
|
|
40
|
+
readonly db: SmartdataDb;
|
|
41
|
+
private constructor();
|
|
42
|
+
static create(optionsArg: ISmartdataTestDatabaseOptions): Promise<SmartdataTestDatabase>;
|
|
43
|
+
insertStoredDocumentFault(modelArg: TSmartdataTestModel, documentArg: unknown, optionsArg?: ISmartdataStoredDocumentFaultOptions): Promise<void>;
|
|
44
|
+
replaceStoredDocumentFault(modelArg: TSmartdataTestModel, expectedIdArg: unknown, documentArg: unknown, optionsArg?: ISmartdataStoredDocumentFaultOptions): Promise<void>;
|
|
45
|
+
/** Remove one declared secondary index from an exact, owned test collection. */
|
|
46
|
+
dropDeclaredIndexFault(modelArg: TSmartdataTestModel, indexNameArg: string, optionsArg?: ISmartdataIndexFaultOptions): Promise<void>;
|
|
47
|
+
private assertFaultAvailable;
|
|
48
|
+
private getFaultModelTopology;
|
|
49
|
+
private assertOwnedBinding;
|
|
50
|
+
private inject;
|
|
51
|
+
/** Idempotent after success. A failed close retains ownership for an explicit retry. */
|
|
52
|
+
close(optionsArg?: {
|
|
53
|
+
timeoutMs?: number;
|
|
54
|
+
}): Promise<void>;
|
|
55
|
+
private dispose;
|
|
56
|
+
}
|