@lossless.org/client 1.12.0 → 1.14.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.
@@ -1,7 +1,23 @@
1
1
  import * as plugins from './plugins.js';
2
2
  import { SmartdataOperationDeadline, requireOperationSignal, requireOperationTimeoutMS, } from './classes.operationdeadline.js';
3
3
  import { assertDataOptions } from './classes.operationbudget.js';
4
- import { SmartdataPersistenceError, createSmartdataTimeoutError, isMongoDeadlineError, normalizeDeadlineError, normalizeOrdinaryPersistenceError, } from './classes.persistence.js';
4
+ import { SmartdataPersistenceError, createSmartdataTimeoutError, isMongoDeadlineError, isMongoTransientTransactionError, normalizeDeadlineError, normalizeOrdinaryPersistenceError, } from './classes.persistence.js';
5
+ /** The commit outcome of every value a `withTransaction()` call rejected with. */
6
+ const transactionCommitOutcomes = new WeakMap();
7
+ /**
8
+ * Records what `errorArg`, the rejection of a `withTransaction()` call, means
9
+ * for the commit, and returns it for the throw. A value several transactions
10
+ * rejected with keeps `unknown` once any of them may have committed. A
11
+ * primitive cannot be recorded.
12
+ */
13
+ const rejectTransaction = (errorArg, outcomeArg) => {
14
+ if (((typeof errorArg === 'object' && errorArg !== null) || typeof errorArg === 'function')
15
+ && transactionCommitOutcomes.get(errorArg) !== 'unknown') {
16
+ transactionCommitOutcomes.set(errorArg, outcomeArg);
17
+ }
18
+ return errorArg;
19
+ };
20
+ const commitOutcomeOfTransactionEnd = (endArg) => endArg === 'during_commit' ? 'unknown' : 'not_committed';
5
21
  /**
6
22
  * The session of a transaction ended while it ran, for example through the
7
23
  * database's `close()`. The driver then returns the callback's result without
@@ -41,12 +57,43 @@ const normalizeTransactionOptions = (optionsArg) => {
41
57
  signal: requireOperationSignal(signal, 'SmartData transaction signal'),
42
58
  };
43
59
  };
60
+ /** Everything `withTransaction()` refuses before a transaction starts. */
61
+ const admitTransaction = (sessionArg, callbackArg, optionsArg) => {
62
+ if (typeof callbackArg !== 'function') {
63
+ throw new SmartdataPersistenceError('invalid_argument', 'SmartData transaction callback must be a function.');
64
+ }
65
+ const { timeoutMS, signal } = normalizeTransactionOptions(optionsArg);
66
+ const binding = resolveBinding(sessionArg);
67
+ if (binding.operationActive || binding.transactionActive) {
68
+ throw new SmartdataPersistenceError('unsupported_operation', 'Parallel or nested SmartData session operations are not supported.');
69
+ }
70
+ signal?.throwIfAborted();
71
+ return { binding, timeoutMS, signal };
72
+ };
44
73
  const assertTransactionSucceeded = (bindingArg) => {
45
74
  if (bindingArg.transactionFailure) {
46
75
  throw bindingArg.transactionFailure.error;
47
76
  }
48
77
  };
49
78
  export class SmartdataSession {
79
+ /**
80
+ * Whether the transaction whose `withTransaction()` call rejected with
81
+ * `errorArg` could have committed: `not_committed` when nothing of it was
82
+ * committed, `unknown` when a commit was sent and never confirmed, so it may
83
+ * have applied. Every rejection of `withTransaction()` carries one, whatever
84
+ * it is: the client's own errors, the callback's error, the abort reason or
85
+ * a driver error, which all keep their identity. A value several calls
86
+ * rejected with reads `unknown` once any of them may have committed.
87
+ *
88
+ * Returns `undefined` for any other value, and for a primitive rejection —
89
+ * a callback that throws a string, or a string abort reason — which cannot
90
+ * carry the outcome; treat `undefined` as `unknown`.
91
+ */
92
+ static getCommitOutcome(errorArg) {
93
+ return (typeof errorArg === 'object' && errorArg !== null) || typeof errorArg === 'function'
94
+ ? transactionCommitOutcomes.get(errorArg)
95
+ : undefined;
96
+ }
50
97
  /**
51
98
  * Runs `callbackArg` in a transaction, retrying it as the driver decides.
52
99
  *
@@ -78,17 +125,20 @@ export class SmartdataSession {
78
125
  * `unsupported_operation`: before the callback returned nothing was
79
126
  * committed, afterwards the commit outcome is unknown. The callback's
80
127
  * error, if it threw, is the `cause`.
128
+ *
129
+ * Every rejection states whether the transaction could have committed:
130
+ * `SmartdataSession.getCommitOutcome(error)` returns `not_committed` or
131
+ * `unknown` for the value the call rejected with.
81
132
  */
82
133
  async withTransaction(callbackArg, optionsArg) {
83
- if (typeof callbackArg !== 'function') {
84
- throw new SmartdataPersistenceError('invalid_argument', 'SmartData transaction callback must be a function.');
134
+ let admitted;
135
+ try {
136
+ admitted = admitTransaction(this, callbackArg, optionsArg);
85
137
  }
86
- const { timeoutMS, signal } = normalizeTransactionOptions(optionsArg);
87
- const binding = resolveBinding(this);
88
- if (binding.operationActive || binding.transactionActive) {
89
- throw new SmartdataPersistenceError('unsupported_operation', 'Parallel or nested SmartData session operations are not supported.');
138
+ catch (errorArg) {
139
+ throw rejectTransaction(errorArg, 'not_committed');
90
140
  }
91
- signal?.throwIfAborted();
141
+ const { binding, timeoutMS, signal } = admitted;
92
142
  binding.transactionActive = true;
93
143
  binding.transactionTimeoutMS = timeoutMS;
94
144
  binding.transactionSignal = signal;
@@ -96,7 +146,8 @@ export class SmartdataSession {
96
146
  let callbackError;
97
147
  /** The signal or deadline interruption that failed the last attempt. */
98
148
  let attemptInterruption;
99
- let sessionEndedError;
149
+ /** The session-ended rejection the last attempt failed with, and how far that transaction had got. */
150
+ let sessionEnded;
100
151
  const runAttempt = async () => {
101
152
  const attempt = Symbol('smartdataTransactionAttempt');
102
153
  binding.transactionAttempt = attempt;
@@ -136,8 +187,11 @@ export class SmartdataSession {
136
187
  if (binding.transactionEnded) {
137
188
  // The driver would commit or return the result on a session that is
138
189
  // being ended; the attempt fails instead, keeping the callback's error.
139
- sessionEndedError = createTransactionSessionEndedError(binding.transactionEnded, callbackThrown?.error);
140
- throw sessionEndedError;
190
+ sessionEnded = {
191
+ error: createTransactionSessionEndedError(binding.transactionEnded, callbackThrown?.error),
192
+ end: binding.transactionEnded,
193
+ };
194
+ throw sessionEnded.error;
141
195
  }
142
196
  if (callbackReturned && activeOperation) {
143
197
  throw new SmartdataPersistenceError('unsupported_operation', 'A SmartData transaction callback returned with an operation still active.');
@@ -158,42 +212,70 @@ export class SmartdataSession {
158
212
  throw errorArg;
159
213
  }
160
214
  };
161
- let result;
162
- let transactionEnded;
163
- try {
164
- result = timeoutMS === undefined
165
- ? await binding.rawSession.withTransaction(runAttempt)
166
- : await binding.rawSession.withTransaction(runAttempt, { timeoutMS });
167
- transactionEnded = binding.transactionEnded;
168
- }
169
- catch (errorArg) {
215
+ /**
216
+ * What the call rejects with when the driver's `withTransaction()` rejected
217
+ * with `errorArg`, and whether the transaction could have committed. Once
218
+ * the last attempt's callback returned, the driver was committing: every
219
+ * error from there on leaves the commit outcome unknown, unless it states
220
+ * that the transaction was aborted. The driver starts another attempt only
221
+ * after such an error, so an earlier attempt never committed.
222
+ */
223
+ const settleTransactionRejection = (errorArg) => {
170
224
  // The driver's closing abort replaces the attempt's error when it finds
171
225
  // the transaction already aborted, as a session that close() ended leaves
172
226
  // it; the interruption that failed the attempt keeps its rejection.
173
227
  if (attemptInterruption) {
174
- throw normalizeDeadlineError(attemptInterruption.error);
228
+ return { error: normalizeDeadlineError(attemptInterruption.error), outcome: 'not_committed' };
175
229
  }
176
- if (sessionEndedError) {
177
- throw sessionEndedError;
230
+ if (sessionEnded) {
231
+ return { error: sessionEnded.error, outcome: commitOutcomeOfTransactionEnd(sessionEnded.end) };
178
232
  }
179
233
  if (binding.transactionEnded
180
234
  && errorArg !== signal?.reason
181
235
  && !isMongoDeadlineError(errorArg)
182
236
  && !(errorArg instanceof SmartdataPersistenceError && errorArg.code === 'timeout')) {
183
- throw createTransactionSessionEndedError(binding.transactionEnded, errorArg);
237
+ return {
238
+ error: createTransactionSessionEndedError(binding.transactionEnded, errorArg),
239
+ outcome: commitOutcomeOfTransactionEnd(binding.transactionEnded),
240
+ };
184
241
  }
185
242
  if (errorArg === callbackError) {
186
- throw normalizeDeadlineError(errorArg);
243
+ return { error: normalizeDeadlineError(errorArg), outcome: 'not_committed' };
187
244
  }
245
+ const outcome = binding.transactionCommitReached && !isMongoTransientTransactionError(errorArg)
246
+ ? 'unknown'
247
+ : 'not_committed';
188
248
  if (isMongoDeadlineError(errorArg)) {
189
- throw createSmartdataTimeoutError(binding.transactionCommitReached
190
- ? 'SmartData transaction exceeded its client deadline during commit; the commit outcome is unknown.'
191
- : 'SmartData transaction exceeded its client deadline before commit; nothing was committed.', errorArg);
249
+ return {
250
+ error: createSmartdataTimeoutError(outcome === 'unknown'
251
+ ? 'SmartData transaction exceeded its client deadline during commit; the commit outcome is unknown.'
252
+ : binding.transactionCommitReached
253
+ ? 'SmartData transaction exceeded its client deadline after the database aborted its commit; nothing was committed.'
254
+ : 'SmartData transaction exceeded its client deadline before commit; nothing was committed.', errorArg),
255
+ outcome,
256
+ };
192
257
  }
193
258
  if (binding.transactionUsesOrdinaryWrite) {
194
- return normalizeOrdinaryPersistenceError(errorArg, 'SmartData transaction conflicts with a unique index.');
259
+ try {
260
+ normalizeOrdinaryPersistenceError(errorArg, 'SmartData transaction conflicts with a unique index.');
261
+ }
262
+ catch (normalizedArg) {
263
+ return { error: normalizedArg, outcome };
264
+ }
195
265
  }
196
- throw errorArg;
266
+ return { error: errorArg, outcome };
267
+ };
268
+ let result;
269
+ let transactionEnded;
270
+ try {
271
+ result = timeoutMS === undefined
272
+ ? await binding.rawSession.withTransaction(runAttempt)
273
+ : await binding.rawSession.withTransaction(runAttempt, { timeoutMS });
274
+ transactionEnded = binding.transactionEnded;
275
+ }
276
+ catch (errorArg) {
277
+ const { error, outcome } = settleTransactionRejection(errorArg);
278
+ throw rejectTransaction(error, outcome);
197
279
  }
198
280
  finally {
199
281
  binding.transactionActive = false;
@@ -205,7 +287,7 @@ export class SmartdataSession {
205
287
  binding.transactionEnded = undefined;
206
288
  }
207
289
  if (transactionEnded) {
208
- throw createTransactionSessionEndedError(transactionEnded);
290
+ throw rejectTransaction(createTransactionSessionEndedError(transactionEnded), commitOutcomeOfTransactionEnd(transactionEnded));
209
291
  }
210
292
  return result;
211
293
  }
@@ -469,4 +551,4 @@ const closeSessionBinding = async (bindingArg, endOptionsArg) => {
469
551
  export const unwrapSmartdataSessionInvalidationErrors = (errorArg) => errorArg instanceof SmartdataSessionInvalidationAggregateError
470
552
  ? errorArg.errors
471
553
  : undefined;
472
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zZXNzaW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvbm9zcWxkYi9jbGFzc2VzLnNlc3Npb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFHeEMsT0FBTyxFQUNMLDBCQUEwQixFQUMxQixzQkFBc0IsRUFDdEIseUJBQXlCLEdBQzFCLE1BQU0sZ0NBQWdDLENBQUM7QUFDeEMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDakUsT0FBTyxFQUNMLHlCQUF5QixFQUN6QiwyQkFBMkIsRUFDM0Isb0JBQW9CLEVBQ3BCLHNCQUFzQixFQUN0QixpQ0FBaUMsR0FDbEMsTUFBTSwwQkFBMEIsQ0FBQztBQStCbEM7Ozs7R0FJRztBQUNILE1BQU0sa0NBQWtDLEdBQUcsQ0FDekMsTUFBZ0MsRUFDaEMsUUFBa0IsRUFDUyxFQUFFLENBQzdCLElBQUkseUJBQXlCLENBQzNCLHVCQUF1QixFQUN2QixNQUFNLEtBQUssZUFBZTtJQUN4QixDQUFDLENBQUMsbUZBQW1GO0lBQ3JGLENBQUMsQ0FBQywyRUFBMkUsRUFDL0UsUUFBUSxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsQ0FDekQsQ0FBQztBQUVKLE1BQU0sUUFBUSxHQUFHLElBQUksT0FBTyxFQUE4QyxDQUFDO0FBQzNFLE1BQU0sZUFBZSxHQUFHLElBQUksT0FBTyxFQUE4QyxDQUFDO0FBQ2xGLE1BQU0sMENBQTBDLEdBQUcsTUFBTSxDQUN2RCx1Q0FBdUMsQ0FDeEMsQ0FBQztBQUVGLE1BQU0sMENBQTJDLFNBQVEsY0FBYztJQUNyRCxDQUFDLDBDQUEwQyxDQUFDLEdBQUcsSUFBSSxDQUFDO0NBQ3JFO0FBdUNELE1BQU0sa0JBQWtCLEdBQUcsSUFBSSxPQUFPLENBQUMsY0FBYyxDQUFDLGlCQUFp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
554
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zZXNzaW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvbm9zcWxkYi9jbGFzc2VzLnNlc3Npb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFHeEMsT0FBTyxFQUNMLDBCQUEwQixFQUMxQixzQkFBc0IsRUFDdEIseUJBQXlCLEdBQzFCLE1BQU0sZ0NBQWdDLENBQUM7QUFDeEMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDakUsT0FBTyxFQUNMLHlCQUF5QixFQUN6QiwyQkFBMkIsRUFDM0Isb0JBQW9CLEVBQ3BCLGdDQUFnQyxFQUNoQyxzQkFBc0IsRUFDdEIsaUNBQWlDLEdBQ2xDLE1BQU0sMEJBQTBCLENBQUM7QUEyQ2xDLGtGQUFrRjtBQUNsRixNQUFNLHlCQUF5QixHQUFHLElBQUksT0FBTyxFQUE4QyxDQUFDO0FBRTVGOzs7OztHQUtHO0FBQ0gsTUFBTSxpQkFBaUIsR0FBRyxDQUN4QixRQUFpQixFQUNqQixVQUE4QyxFQUNyQyxFQUFFO0lBQ1gsSUFDRSxDQUFDLENBQUMsT0FBTyxRQUFRLEtBQUssUUFBUSxJQUFJLFFBQVEsS0FBSyxJQUFJLENBQUMsSUFBSSxPQUFPLFFBQVEsS0FBSyxVQUFVLENBQUM7V0FDcEYseUJBQXlCLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxLQUFLLFNBQVMsRUFDeEQsQ0FBQztRQUNELHlCQUF5QixDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFDdEQsQ0FBQztJQUNELE9BQU8sUUFBUSxDQUFDO0FBQ2xCLENBQUMsQ0FBQztBQUVGLE1BQU0sNkJBQTZCLEdBQUcsQ0FDcEMsTUFBZ0MsRUFDSSxFQUFFLENBQ3RDLE1BQU0sS0FBSyxlQUFlLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsZUFBZSxDQUFDO0FBRTNEOzs7O0dBSUc7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
@@ -16,6 +16,7 @@ export * from './classes.doc.js';
16
16
  export { ordinaryPersistence } from './classes.ordinarypersistence.js';
17
17
  export type { IOrdinaryPersistenceOptions } from './classes.ordinarypersistence.js';
18
18
  export type { ISmartdataStoredInspectionOptions, ISmartdataStoredInspection, ISmartdataStoredDocumentEvidence, ISmartdataStoredEvidenceInspection, TSmartdataOrdinaryDocumentEvidence, } from './classes.storedinspection.js';
19
+ export type { ISmartdataQueryPlanOptions, ISmartdataQueryPlan, ISmartdataQueryPlanStage, } from './classes.queryplaninspection.js';
19
20
  export { SmartdataPersistenceError } from './classes.persistence.js';
20
21
  export type { TSmartdataPersistenceErrorCode } from './classes.persistence.js';
21
22
  export * from './classes.exactpersistence.js';
@@ -16,4 +16,4 @@ export * from './classes.distributedcoordinator.js';
16
16
  export * from './classes.cached-document.js';
17
17
  import * as convenience from './classes.convenience.js';
18
18
  export { convenience };
19
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9ub3NxbGRiL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLDhFQUE4RTtBQUM5RSxPQUFPLFdBQVcsQ0FBQztBQUVuQixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFhMUQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUc5QyxjQUFjLGlCQUFpQixDQUFDO0FBQ2hDLGNBQWMsa0NBQWtDLENBQUM7QUFPakQsY0FBYyx5QkFBeUIsQ0FBQztBQVl4QyxjQUFjLGtCQUFrQixDQUFDO0FBQ2pDLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBT3ZFLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBRXJFLGNBQWMsK0JBQStCLENBQUM7QUFDOUMsY0FBYyx3QkFBd0IsQ0FBQztBQUN2QyxjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMsc0JBQXNCLENBQUM7QUFDckMsY0FBYyxxQ0FBcUMsQ0FBQztBQUNwRCxjQUFjLDhCQUE4QixDQUFDO0FBRTdDLE9BQU8sS0FBSyxXQUFXLE1BQU0sMEJBQTBCLENBQUM7QUFFeEQsT0FBTyxFQUFFLFdBQVcsRUFBRSxDQUFDIn0=
19
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9ub3NxbGRiL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLDhFQUE4RTtBQUM5RSxPQUFPLFdBQVcsQ0FBQztBQUVuQixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFhMUQsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGNBQWMsQ0FBQztBQUc5QyxjQUFjLGlCQUFpQixDQUFDO0FBQ2hDLGNBQWMsa0NBQWtDLENBQUM7QUFPakQsY0FBYyx5QkFBeUIsQ0FBQztBQVl4QyxjQUFjLGtCQUFrQixDQUFDO0FBQ2pDLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBVXZFLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBRXJFLGNBQWMsK0JBQStCLENBQUM7QUFDOUMsY0FBYyx3QkFBd0IsQ0FBQztBQUN2QyxjQUFjLHFCQUFxQixDQUFDO0FBQ3BDLGNBQWMsc0JBQXNCLENBQUM7QUFDckMsY0FBYyxxQ0FBcUMsQ0FBQztBQUNwRCxjQUFjLDhCQUE4QixDQUFDO0FBRTdDLE9BQU8sS0FBSyxXQUFXLE1BQU0sMEJBQTBCLENBQUM7QUFFeEQsT0FBTyxFQUFFLFdBQVcsRUFBRSxDQUFDIn0=
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lossless.org/client",
3
- "version": "1.12.0",
3
+ "version": "1.14.0",
4
4
  "private": false,
5
5
  "description": "One typed client for NoSQLDB, MongoDB, SQLDB, MariaDB, ClickHouse and S3 object storage.",
6
6
  "exports": {
@@ -82,10 +82,10 @@
82
82
  "@aws-sdk/client-s3": "^3.1039.0",
83
83
  "@clickhouse/client": "1.23.1",
84
84
  "@git.zone/tsbuild": "5.0.0",
85
- "@git.zone/tsrun": "3.0.0",
86
- "@git.zone/tstest": "6.3.0",
85
+ "@git.zone/tsrun": "3.0.1",
86
+ "@git.zone/tstest": "6.3.2",
87
87
  "@lossless.org/nosqldb": "8.0.2",
88
- "@lossless.org/nosqldb-qualified": "npm:@lossless.org/nosqldb@10.7.1",
88
+ "@lossless.org/nosqldb-qualified": "npm:@lossless.org/nosqldb@10.7.2",
89
89
  "@lossless.org/objectstorage": "10.3.1",
90
90
  "@lossless.org/sqldb": "0.2.3",
91
91
  "@push.rocks/qenv": "^6.1.3",
package/readme.md CHANGED
@@ -106,7 +106,9 @@ Family imports preserve the established SmartData and SmartBucket names and cons
106
106
  | Client deadlines | `timeoutMS` (1..120000) on every ordinary model read and write, instance `save()`/`saveIf()`/`delete()` included, on every exact call, and `session.withTransaction(callback, { timeoutMS })` for a whole transaction, retries and commit included; expiry rejects with `SmartdataPersistenceError` code `timeout`, and an exact write interrupted in flight with `ambiguous_write` |
107
107
  | Bounded database close | `db.close({ timeoutMs })` bounds the whole close — session cleanup, the optional database removal and the driver client's close — and rejects at its deadline with `SmartdataPersistenceError` code `timeout`, leaving the database `close_failed`; the driver's close keeps running until it settles on its own, and the next `close()` joins it |
108
108
  | Transactions ended by close | a `session.withTransaction()` whose session `db.close()` ends while it runs rejects with `SmartdataPersistenceError` code `unsupported_operation` — "nothing was committed" before the commit, "the commit outcome is unknown" during it — instead of resolving with the callback's result |
109
+ | Transaction commit outcome | `SmartdataSession.getCommitOutcome(error)` states for every value a `session.withTransaction()` rejected with whether the transaction could have committed: `not_committed` (nothing was committed) or `unknown` (a commit was sent and never confirmed); the rejection itself keeps its identity |
109
110
  | Cancellation | `signal` on every exact call, `atomicDeleteMany()` and `session.withTransaction(callback, { signal })`, which interrupts the session's operation in flight, rolls the attempt back and never commits after an abort |
111
+ | Query-plan inspection | `Model.inspectQueryPlan(db, { filter, sort?, projection?, limit?, timeoutMS?, signal? })` — the winning plan's stages (`stage`, `depth`, `indexName`, `direction`) and `nReturned`/`totalKeysExamined`/`totalDocsExamined`, read-only and bounded, so a consumer proves a model query uses its intended index without raw driver access |
110
112
  | Disposable test databases on a unix socket | `SmartdataTestDatabase.create({ connection: { socketPath } })` from `@lossless.org/client/testsupport` reaches an engine that listens only on a unix-domain socket, fault helpers included; the loopback `host`/`port` form is unchanged |
111
113
 
112
114
  `docs/source/smartdata/readme.md` documents each one with its refusals.
@@ -122,7 +124,7 @@ A bucket lookup sends one HeadBucket for the named bucket, never ListBuckets, so
122
124
 
123
125
  ### Document APIs that need a MongoDB backend
124
126
 
125
- The document model runs on both NoSQLDB and MongoDB, but several APIs do not mean the same thing on both. The NoSQLDB engine is qualified at 8.0.2 and 10.7.1 (see [Verification](#verification)); the two releases part on the grouped-totals and guarded-`$expr` rows below — 10.7.1 groups composite keys exactly and evaluates the guard, 8.0.2 does neither — on whether a migration can create a partial index or a collection validator at all, on when a transaction learns of a write conflict, and on whether `$elemMatch` applies query operators to scalar array elements.
127
+ The document model runs on both NoSQLDB and MongoDB, but several APIs do not mean the same thing on both. The NoSQLDB engine is qualified at 8.0.2 and 10.7.2 (see [Verification](#verification)); the two releases part on the grouped-totals and guarded-`$expr` rows below — 10.7.2 groups composite keys exactly and evaluates the guard, 8.0.2 does neither — on whether a migration can create a partial index or a collection validator at all, on when a transaction learns of a write conflict, and on whether `$elemMatch` applies query operators to scalar array elements.
126
128
 
127
129
  `init()` asks the connected engine what it is with one `buildInfo` command and records the answer on the database as `engineIdentity` (`{ product, version }`). NoSQLDB answers with its own `nosqldb` identity document from 10.3.0 onward; a MongoDB server answers `buildInfo` without one; an engine that refuses the command — NoSQLDB 8.0.2 answers `CommandNotFound` — stays `{ product: 'unknown', version: null }`. The identity is what states `capabilities` on a plain `SmartdataDb`, and an unidentified engine states none at all, so every capability-gated call refuses. `NoSqlConnection` keeps stating the capabilities of its declared backend from construction on.
128
130
 
@@ -132,13 +134,14 @@ The document model runs on both NoSQLDB and MongoDB, but several APIs do not mea
132
134
  | the same with **two** `groupBy` fields | exact, `sums` included, on an engine that identifies itself as NoSQLDB 10.5.0 or newer: that release evaluates the composite group key per document. Below it the call is refused with `unsupported_operation` naming both fields and the single-field form, because the engine leaves the composite group key unresolved and answers with a single row whose group values are the literal field paths (`'$owner'`) and whose count is the whole filtered collection; the refusal is the guard against that wrong number, not a fix for it | exact |
133
135
  | guarded `$expr` atomic filters (`$add`, `$lte`, `$ifNull`) | exact on 10.6.0 and newer: the engine evaluates the client's fail-closed compilation (`$cond`, `$let`, `$isNumber`, `$type`), so the guard admits within the limit, refuses beyond it and never matches a stored value that is not a finite number. 8.0.2 rejects the compilation with `invalid argument: $cond` and leaves the document untouched | exact |
134
136
  | `watch()` change streams | unsupported. `NoSqlConnection` refuses with `unsupported_capability`, and so does a plain `SmartdataDb` whose engine identified itself; against an engine that answers no identity the refusal instead arrives from the engine as `CommandNotFound` once the change stream is read | supported on replica sets |
135
- | model-declared partial indexes (`partialFilterExpression`) | not expressible: the index-option type rejects it and the runtime refuses it with `invalid_configuration`. A client decision, not an engine limit on every release — 10.6.0 and newer create partial indexes, 8.0.2 refuses the option with `InvalidOptions` (72) — because one model declaration has to hold on every qualified backend. A migration may create one on 10.7.1; `toleratedIndexNames` accepts it and inspection reports its filter | not expressible, but a migration may own one; inspection reports its filter |
137
+ | model-declared partial indexes (`partialFilterExpression`) | not expressible: the index-option type rejects it and the runtime refuses it with `invalid_configuration`. A client decision, not an engine limit on every release — 10.6.0 and newer create partial indexes, 8.0.2 refuses the option with `InvalidOptions` (72) — because one model declaration has to hold on every qualified backend. A migration may create one on 10.7.2; `toleratedIndexNames` accepts it and inspection reports its filter | not expressible, but a migration may own one; inspection reports its filter |
136
138
  | collection validators (`validator`, `validationLevel`, `validationAction`) | no client API; a migration owns a validator through the driver. 10.7.0 and newer create the collection, list the options exactly as given and enforce them on every model write: a violating `insert()` or `atomicUpdate()` rejects with the engine's `DocumentValidationFailure` (121) and its `errInfo`, which the client passes through unchanged rather than mapping to a `SmartdataPersistenceError` code, and stores nothing. Models initialize on a validated collection like on any other. 8.0.2 refuses the option with `InvalidOptions` (72) and creates no collection, so a validator is never silently dropped | enforced; not exercised by the client's MongoDB suite |
137
- | write conflicts between transactions, and writes outside a transaction to a document a transaction holds | 10.7.1 (since 10.6.1) detects a conflict at the statement, as MongoDB does: the first writer wins, and the later transaction's statement rejects with the engine's `WriteConflict` (112) labelled `TransientTransactionError`, which the client passes through so `session.withTransaction()` re-runs that callback. A write outside a transaction waits until the transaction holding its document ends, then applies on top; the wait is bounded by the write's own `timeoutMS` and by the engine's fixed 60-second transaction lifetime, after which a waiting writer aborts the holder. Awaiting such a write inside the holding transaction's callback therefore stalls that transaction until one of the two expires. 8.0.2 detects the conflict at commit: the first transaction to commit wins, a write outside a transaction applies at once, and the transaction that wrote first re-runs. Both writes land on either engine; a callback must be safe to re-run and must not swallow the statement error | first writer wins at the statement and outside writes wait, MongoDB's documented rule; not exercised by the client's MongoDB suite |
138
- | value-form `$elemMatch` in read filters (`{ scores: { $elemMatch: { $gte: 80, $lt: 90 } } }`, `{ labels: { $not: { $elemMatch: { $nin: runnerLabels } } } }`) | exact on 10.7.1: the operators apply to each array element as a whole, so the range matches only a document with one score inside it and the claim selects a job only when every one of its labels is a runner label. 8.0.2 parses every operand as a query over embedded documents and refuses the value form with `TypeMismatch` (14). A non-document operand is refused on both, with MongoDB's `BadValue` (2) on 10.7.1 and 14 on 8.0.2. The client passes the operand through unchanged; the filter type admits the value form over scalar elements and the document form over embedded documents. Atomic filters (`atomicUpdate()` and the other atomic writes) accept no `$elemMatch` on any backend: the client refuses it with `invalid_argument` before any backend is contacted | exact |
139
+ | write conflicts between transactions, and writes outside a transaction to a document a transaction holds | 10.7.2 (since 10.6.1) detects a conflict at the statement, as MongoDB does: the first writer wins, and the later transaction's statement rejects with the engine's `WriteConflict` (112) labelled `TransientTransactionError`, which the client passes through so `session.withTransaction()` re-runs that callback. A write outside a transaction waits until the transaction holding its document ends, then applies on top; the wait is bounded by the write's own `timeoutMS` and by the engine's fixed 60-second transaction lifetime, after which a waiting writer aborts the holder. Awaiting such a write inside the holding transaction's callback therefore stalls that transaction until one of the two expires. 8.0.2 detects the conflict at commit: the first transaction to commit wins, a write outside a transaction applies at once, and the transaction that wrote first re-runs. Both writes land on either engine; a callback must be safe to re-run and must not swallow the statement error | first writer wins at the statement and outside writes wait, MongoDB's documented rule; not exercised by the client's MongoDB suite |
140
+ | value-form `$elemMatch` in read filters (`{ scores: { $elemMatch: { $gte: 80, $lt: 90 } } }`, `{ labels: { $not: { $elemMatch: { $nin: runnerLabels } } } }`) | exact on 10.7.1 and newer: the operators apply to each array element as a whole, so the range matches only a document with one score inside it and the claim selects a job only when every one of its labels is a runner label. 8.0.2 parses every operand as a query over embedded documents and refuses the value form with `TypeMismatch` (14). A non-document operand is refused on both, with MongoDB's `BadValue` (2) on 10.7.1 and newer and 14 on 8.0.2. The client passes the operand through unchanged; the filter type admits the value form over scalar elements and the document form over embedded documents. Atomic filters (`atomicUpdate()` and the other atomic writes) accept no `$elemMatch` on any backend: the client refuses it with `invalid_argument` before any backend is contacted | exact |
141
+ | `Model.inspectQueryPlan()` | explains on 10.7.2: the summary names the winning plan's stages and its execution totals. 8.0.2 answers `explain` with `CommandNotFound` (59), and the call rejects with `unsupported_operation` ("The connected engine does not explain queries.") rather than returning a plan it cannot know. Stage shapes are the engine's own: on 10.7.2 a limited sort on an unindexed field is `LIMIT` over `SORT` over `COLLSCAN`, an equality on a unique single-field index is `FETCH` over `IXSCAN`, and an `$or` whose branches each have an index is a `COLLSCAN` | explains: the same limited sort is `SORT` over `COLLSCAN`, the limit folded into the sort; the equality is `EXPRESS_IXSCAN` on the unique index; the `$or` is `SUBPLAN` over `FETCH` over `OR` over one `IXSCAN` per branch |
139
142
  | aggregation-pipeline (array) updates | refused by the client with `invalid_argument` before any backend is contacted. A client-owned refusal, not an engine limit: both qualified engines apply a pipeline update themselves | same client refusal |
140
143
 
141
- `test/nosqldb/smartdb/test.engine-capability-boundary.node.ts` asserts the identity, grouped-totals, guarded-`$expr`, partial-index, collection-validator, write-conflict, `$elemMatch` and pipeline-update rows against both qualified engines, so a boundary that moves shows up as a failing suite rather than as a changed number in a consumer. The two halves of the grouped-totals, guarded-`$expr`, write-conflict and `$elemMatch` rows are separate tests, each bound to the engine that answers it, and the engine's own composite-key answer stays under assertion through the raw `aggregateGroupedTotals()` boundary — one literal row on 8.0.2, the two exact pairs on 10.7.1. The same boundary pins the rest of the engine's `$group` stage: a non-document accumulator is refused with `TypeMismatch` (14) on 10.7.1 while 8.0.2 answers it, and a `$cond` inside a composite key is evaluated per document on 10.7.1 while 8.0.2 answers its single literal row. It also pins whether a migration can create a partial index — 10.7.1 creates it and lists the filter, 8.0.2 refuses with 72 — and a collection validator — 10.7.1 creates and enforces it against model inserts and updates, 8.0.2 refuses with 72 — which writer a conflict sends back: on 10.7.1 the later transaction fails at its statement and re-runs while a write outside a transaction waits for the holder's commit, on 8.0.2 the later transaction commits first and the holder re-runs — and what `$elemMatch` answers through `getInstances()`: 10.7.1 matches the documented range and the `$not`/`$elemMatch`/`$nin` claim exactly as the MongoDB filter suite asserts them, 8.0.2 refuses both with 14, and a non-document operand is refused with 2 on 10.7.1 and 14 on 8.0.2. The `watch()` row is the contract refusal `ts/nosqldb/classes.collection.ts` states; the engine suite opens no change stream.
144
+ `test/nosqldb/smartdb/test.engine-capability-boundary.node.ts` asserts the identity, grouped-totals, guarded-`$expr`, partial-index, collection-validator, write-conflict, `$elemMatch` and pipeline-update rows against both qualified engines, so a boundary that moves shows up as a failing suite rather than as a changed number in a consumer. The two halves of the grouped-totals, guarded-`$expr`, write-conflict and `$elemMatch` rows are separate tests, each bound to the engine that answers it, and the engine's own composite-key answer stays under assertion through the raw `aggregateGroupedTotals()` boundary — one literal row on 8.0.2, the two exact pairs on 10.7.2. The same boundary pins the rest of the engine's `$group` stage: a non-document accumulator is refused with `TypeMismatch` (14) on 10.7.2 while 8.0.2 answers it, and a `$cond` inside a composite key is evaluated per document on 10.7.2 while 8.0.2 answers its single literal row. It also pins whether a migration can create a partial index — 10.7.2 creates it and lists the filter, 8.0.2 refuses with 72 — and a collection validator — 10.7.2 creates and enforces it against model inserts and updates, 8.0.2 refuses with 72 — which writer a conflict sends back: on 10.7.2 the later transaction fails at its statement and re-runs while a write outside a transaction waits for the holder's commit, on 8.0.2 the later transaction commits first and the holder re-runs — and what `$elemMatch` answers through `getInstances()`: 10.7.2 matches the documented range and the `$not`/`$elemMatch`/`$nin` claim exactly as the MongoDB filter suite asserts them, 8.0.2 refuses both with 14, and a non-document operand is refused with 2 on 10.7.2 and 14 on 8.0.2. The `watch()` row is the contract refusal `ts/nosqldb/classes.collection.ts` states; the engine suite opens no change stream.
142
145
 
143
146
  ## Relational SQL
144
147
 
@@ -218,14 +221,14 @@ Qualified engines:
218
221
 
219
222
  | Component | Qualified versions |
220
223
  | --- | --- |
221
- | NoSQLDB engine | **8.0.2 and 10.7.1** — the same `test/nosqldb/smartdb/` suite runs against both, through the single engine seam in `test/nosqldb/helpers/smartdb.ts`; `NOSQLDB_ENGINE=qualified` selects 10.7.1 |
224
+ | NoSQLDB engine | **8.0.2 and 10.7.2** — the same `test/nosqldb/smartdb/` suite runs against both, through the single engine seam in `test/nosqldb/helpers/smartdb.ts`; `NOSQLDB_ENGINE=qualified` selects 10.7.2 |
222
225
  | MongoDB | 8.0.26 replica sets |
223
226
  | ObjectStorage | 10.3.1 |
224
227
  | SQLDB | 0.2.3 |
225
228
  | MariaDB | 11.8 |
226
229
  | ClickHouse | 25.8 |
227
230
 
228
- Both engine versions run the whole document suite. They part on asserted boundaries — 10.7.1 groups composite keys exactly and answers two-field grouped totals, evaluates guarded `$expr` filters, creates migration-owned partial indexes and collection validators, reports a transaction write conflict at the statement and matches value-form `$elemMatch`, 8.0.2 does none of these, reports the conflict at commit, and the client refuses the two-field form there — which [Document APIs that need a MongoDB backend](#document-apis-that-need-a-mongodb-backend) states row by row. Text search, the Lucene adapter and the broad read-filter surface are exercised against MongoDB only. `pnpm run test:minio` uses a digest-pinned MinIO image: `sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e`. That MinIO version enforces the tested conditional uploads but does not enforce conditional deletion; its exact-purge capability is correctly unavailable. ObjectStorage passes both live probes. AWS S3 has not been qualified against a live account in this migration; no universal S3 exact-operation guarantee is inferred from the SDK.
231
+ Both engine versions run the whole document suite. They part on asserted boundaries — 10.7.2 groups composite keys exactly and answers two-field grouped totals, evaluates guarded `$expr` filters, creates migration-owned partial indexes and collection validators, reports a transaction write conflict at the statement and matches value-form `$elemMatch`, 8.0.2 does none of these, reports the conflict at commit, and the client refuses the two-field form there — which [Document APIs that need a MongoDB backend](#document-apis-that-need-a-mongodb-backend) states row by row. Text search, the Lucene adapter and the broad read-filter surface are exercised against MongoDB only. `pnpm run test:minio` uses a digest-pinned MinIO image: `sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e`. That MinIO version enforces the tested conditional uploads but does not enforce conditional deletion; its exact-purge capability is correctly unavailable. ObjectStorage passes both live probes. AWS S3 has not been qualified against a live account in this migration; no universal S3 exact-operation guarantee is inferred from the SDK.
229
232
 
230
233
  ## License and Legal Information
231
234
 
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@lossless.org/client',
6
- version: '1.12.0',
6
+ version: '1.14.0',
7
7
  description: 'One typed client for NoSQLDB, MongoDB, SQLDB, MariaDB, ClickHouse and S3 object storage.'
8
8
  }
@@ -22,7 +22,11 @@ import {
22
22
  } from './classes.namespaceinspection.js';
23
23
 
24
24
  export { SmartdataSession } from './classes.session.js';
25
- export type { ISmartdataTransactionOptions, TSmartdataOrdinarySession } from './classes.session.js';
25
+ export type {
26
+ ISmartdataTransactionOptions,
27
+ TSmartdataOrdinarySession,
28
+ TSmartdataTransactionCommitOutcome,
29
+ } from './classes.session.js';
26
30
 
27
31
  import { logger } from './logging.js';
28
32
  import { assertDataOptions, SmartdataOperationBudget } from './classes.operationbudget.js';
@@ -16,6 +16,10 @@ import {
16
16
  type ISmartdataStoredInspectionOptions, type ISmartdataStoredInspection,
17
17
  type ISmartdataStoredEvidenceInspection,
18
18
  } from './classes.storedinspection.js';
19
+ import {
20
+ inspectQueryPlan, requireQueryPlanOptions,
21
+ type ISmartdataQueryPlan, type ISmartdataQueryPlanOptions,
22
+ } from './classes.queryplaninspection.js';
19
23
  import {
20
24
  getIdentityDocumentIdField,
21
25
  type IManager,
@@ -3727,6 +3731,32 @@ export class SmartDataDbDoc<T extends TImplements, TImplements, TManager extends
3727
3731
  return inspectStoredDocumentEvidence(this, dbArg, optionsArg);
3728
3732
  }
3729
3733
 
3734
+ /**
3735
+ * Explains one model query with `executionStats` on `dbArg` and returns the
3736
+ * winning plan's stages and execution totals, so a consumer can prove which
3737
+ * index serves the query. Read-only: nothing is created, bound or hydrated.
3738
+ */
3739
+ public static async inspectQueryPlan<T>(
3740
+ this: plugins.tsclass.typeFest.Class<T>,
3741
+ dbArg: SmartdataDb,
3742
+ optionsArg: ISmartdataQueryPlanOptions<T>,
3743
+ ): Promise<ISmartdataQueryPlan> {
3744
+ const model = this as unknown as typeof SmartDataDbDoc;
3745
+ const options = requireQueryPlanOptions(optionsArg);
3746
+ model.assertHydratedProjection(options.projection);
3747
+ const declaredRoots = model.getDeclaredPersistedRoots();
3748
+ const declaredQueryPaths = model.getDeclaredQueryPaths();
3749
+ return inspectQueryPlan(dbArg, {
3750
+ collectionName: getExpectedCollectionTopologyForModel(model).collectionName,
3751
+ filter: model.normalizeReadFilter(options.filter),
3752
+ sort: normalizeSort(options.sort, declaredRoots, declaredQueryPaths),
3753
+ projection: normalizeProjection(options.projection, declaredRoots, declaredQueryPaths),
3754
+ limit: options.limit,
3755
+ timeoutMS: options.timeoutMS,
3756
+ signal: options.signal,
3757
+ });
3758
+ }
3759
+
3730
3760
  public static createInstanceFromMongoDbNativeDoc<T>(
3731
3761
  this: plugins.tsclass.typeFest.Class<T>,
3732
3762
  mongoDbNativeDocArg: any,
@@ -69,6 +69,15 @@ export const isMongoTransactionRetryError = (errorArg: unknown): boolean =>
69
69
  errorArg.hasErrorLabel('UnknownTransactionCommitResult')
70
70
  );
71
71
 
72
+ /**
73
+ * The server or the driver stated that the transaction was aborted and may be
74
+ * run again from its start, so nothing of it was committed. A timeout the
75
+ * driver raises in place of such an error copies its labels.
76
+ */
77
+ export const isMongoTransientTransactionError = (errorArg: unknown): boolean =>
78
+ errorArg instanceof plugins.mongodb.MongoError
79
+ && errorArg.hasErrorLabel(plugins.mongodb.MongoErrorLabel.TransientTransactionError);
80
+
72
81
  export const isMongoDuplicateKeyError = (
73
82
  errorArg: unknown,
74
83
  ): errorArg is plugins.mongodb.MongoServerError => {