cry-db 2.5.1 → 2.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mongo.mjs CHANGED
@@ -7,13 +7,13 @@ var _a;
7
7
  // AI modified: 2026-05-09 (terminal bracket-id `arr[<id>]` z array vrednostjo → idempotent insert preko aggregation pipeline ($concatArrays + $filter); quoted bracket id `['p0']`/`["p0"]` zdaj enak unquoted `[p0]`)
8
8
  // AI modified: 2026-04-25 (GetNewerSpec.specId — disambiguate duplicate-collection specs in findNewerMany / findNewerManyStream)
9
9
  // AI modified: 2026-04-21
10
- import * as bcrypt from 'bcrypt';
11
- import { Formatter, FracturedJsonOptions } from 'fracturedjsonjs';
10
+ import * as bcrypt from "bcrypt";
11
+ import { Formatter, FracturedJsonOptions } from "fracturedjsonjs";
12
12
  import cloneDeep from "lodash.clonedeep";
13
- import { ObjectId, ReadConcern, ReadPreference, Timestamp, WriteConcern } from 'mongodb';
13
+ import { ObjectId, ReadConcern, ReadPreference, Timestamp, WriteConcern, } from "mongodb";
14
14
  import { TypedEmitter } from "tiny-typed-emitter";
15
- import { Db, log } from './db.mjs';
16
- import { FIELD_SEQUENCES_COLLECTION, SEQUENCES_COLLECTION } from './types.mjs';
15
+ import { Db, log } from "./db.mjs";
16
+ import { FIELD_SEQUENCES_COLLECTION, SEQUENCES_COLLECTION, } from "./types.mjs";
17
17
  import { Base } from "./base.mjs";
18
18
  const MONGO_DEBUG_UPDATE_COLLECTIONS = (_a = process.env.MONGO_DEBUG_UPDATE_COLLECTIONS) === null || _a === void 0 ? void 0 : _a.match(/yes|true|da|1/i);
19
19
  const assert = (cond, msg, calledFrom, payload) => {
@@ -29,20 +29,20 @@ const assert = (cond, msg, calledFrom, payload) => {
29
29
  parts.push(String(payload));
30
30
  }
31
31
  }
32
- const fullMsg = parts.join(' | ');
32
+ const fullMsg = parts.join(" | ");
33
33
  const err = new Error(fullMsg);
34
34
  console.error("assert failed:", fullMsg, "\n" + err.stack);
35
35
  throw err;
36
36
  }
37
37
  };
38
38
  const saltRounds = 10;
39
- const HASHED_PREFIX = '__hashed__';
40
- const parseFieldList = (fields) => (typeof fields === 'string' ? fields.split(',') : fields)
41
- .map(f => f.trim())
42
- .filter(f => f.length > 0);
39
+ const HASHED_PREFIX = "__hashed__";
40
+ const parseFieldList = (fields) => (typeof fields === "string" ? fields.split(",") : fields)
41
+ .map((f) => f.trim())
42
+ .filter((f) => f.length > 0);
43
43
  // String helper functions (faster than RegExp)
44
- const startsWithDollar = (s) => s.length > 0 && s[0] === '$';
45
- const startsWithDoubleUnderscore = (s) => s.length > 1 && s[0] === '_' && s[1] === '_';
44
+ const startsWithDollar = (s) => s.length > 0 && s[0] === "$";
45
+ const startsWithDoubleUnderscore = (s) => s.length > 1 && s[0] === "_" && s[1] === "_";
46
46
  const isServerReserved = (s) => s === "_rev" || s === "_ts";
47
47
  const startsWithHashedPrefix = (s) => s.length > 10 && s.startsWith(HASHED_PREFIX);
48
48
  const isHex24 = (s) => {
@@ -60,8 +60,8 @@ const TRANSACTION_OPTIONS = {
60
60
  defaultTransactionOptions: {
61
61
  readPreference: new ReadPreference("primary"),
62
62
  readConcern: new ReadConcern("local"),
63
- writeConcern: new WriteConcern("majority")
64
- }
63
+ writeConcern: new WriteConcern("majority"),
64
+ },
65
65
  };
66
66
  // FracturedJson formatter for readable object logging
67
67
  const fjOptions = new FracturedJsonOptions();
@@ -76,7 +76,9 @@ export const fj = (value) => {
76
76
  if (Array.isArray(value)) {
77
77
  return value.map(fj);
78
78
  }
79
- if (value && typeof value === 'object' && Object.getPrototypeOf(value) === Object.prototype) {
79
+ if (value &&
80
+ typeof value === "object" &&
81
+ Object.getPrototypeOf(value) === Object.prototype) {
80
82
  return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, fj(v)]));
81
83
  }
82
84
  return value;
@@ -86,26 +88,28 @@ export const fj = (value) => {
86
88
  // `key: undefined` entries (which cry-db routes to `$unset` / `$pull`) are
87
89
  // invisible in the log, making bug diagnosis impossible. Walk the structure
88
90
  // and replace `undefined` with a readable sentinel.
89
- const UNDEFINED_MARKER = '<undefined>';
91
+ const UNDEFINED_MARKER = "<undefined>";
90
92
  const markUndefined = (value) => {
91
93
  if (value === undefined)
92
94
  return UNDEFINED_MARKER;
93
95
  if (Array.isArray(value))
94
96
  return value.map(markUndefined);
95
- if (value && typeof value === 'object' && Object.getPrototypeOf(value) === Object.prototype) {
97
+ if (value &&
98
+ typeof value === "object" &&
99
+ Object.getPrototypeOf(value) === Object.prototype) {
96
100
  return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, markUndefined(v)]));
97
101
  }
98
102
  return value;
99
103
  };
100
104
  // Wrap log methods to auto-format objects with fracturedjson
101
- const fjArgs = (args) => args.map(a => {
105
+ const fjArgs = (args) => args.map((a) => {
102
106
  var _a;
103
107
  if (a === undefined)
104
108
  return UNDEFINED_MARKER;
105
- if (typeof a !== 'object' || a === null)
109
+ if (typeof a !== "object" || a === null)
106
110
  return a;
107
111
  const replaced = markUndefined(fj(a));
108
- if (typeof replaced !== 'object' || replaced === null)
112
+ if (typeof replaced !== "object" || replaced === null)
109
113
  return replaced;
110
114
  try {
111
115
  return (_a = fjFormatter.Serialize(replaced)) !== null && _a !== void 0 ? _a : JSON.stringify(replaced);
@@ -115,11 +119,21 @@ const fjArgs = (args) => args.map(a => {
115
119
  }
116
120
  });
117
121
  const fjLog = {
118
- debug: (...args) => { log.debug(...fjArgs(args)); },
119
- trace: (...args) => { log.trace(...fjArgs(args)); },
120
- info: (...args) => { log.info(...fjArgs(args)); },
121
- warn: (...args) => { log.warn(...fjArgs(args)); },
122
- error: (...args) => { log.error(...fjArgs(args)); },
122
+ debug: (...args) => {
123
+ log.debug(...fjArgs(args));
124
+ },
125
+ trace: (...args) => {
126
+ log.trace(...fjArgs(args));
127
+ },
128
+ info: (...args) => {
129
+ log.info(...fjArgs(args));
130
+ },
131
+ warn: (...args) => {
132
+ log.warn(...fjArgs(args));
133
+ },
134
+ error: (...args) => {
135
+ log.error(...fjArgs(args));
136
+ },
123
137
  };
124
138
  // export const DummyExportToFixTsCompilation = true;
125
139
  export class Mongo extends Db {
@@ -136,13 +150,13 @@ export class Mongo extends Db {
136
150
  this.auditCollectionName = "dblog";
137
151
  this.auditedCollectionsLower = [];
138
152
  this.auditedCollections = this.auditCollections(process.env.AUDIT_COLLECTIONS || []);
139
- this._findNewerRemoveFields = new Set(parseFieldList(process.env.REMOVE_FIELDS_FOR_FINDNEWER || ''));
140
- this._removeFieldsAlways = new Set(parseFieldList(process.env.REMOVE_FIELDS_ALWAYS || ''));
153
+ this._findNewerRemoveFields = new Set(parseFieldList(process.env.REMOVE_FIELDS_FOR_FINDNEWER || ""));
154
+ this._removeFieldsAlways = new Set(parseFieldList(process.env.REMOVE_FIELDS_ALWAYS || ""));
141
155
  this.emitter = new TypedEmitter();
142
156
  this.user = undefined;
143
157
  this.audit = undefined;
144
158
  this._sequencesIndexEnsured = false;
145
- fjLog.debug('new Mongo:', this.url, this.db);
159
+ fjLog.debug("new Mongo:", this.url, this.db);
146
160
  }
147
161
  on(evt, listener) {
148
162
  fjLog.debug("on", evt, listener);
@@ -157,19 +171,19 @@ export class Mongo extends Db {
157
171
  this.emitter.once(evt, listener);
158
172
  }
159
173
  setUser(username) {
160
- return this.user = username;
174
+ return (this.user = username);
161
175
  }
162
176
  setAudit(obj) {
163
- return this.audit = obj;
177
+ return (this.audit = obj);
164
178
  }
165
179
  useRevisions(enabled) {
166
- return this.revisions = !!enabled;
180
+ return (this.revisions = !!enabled);
167
181
  }
168
182
  usesRevisions() {
169
183
  return this.revisions;
170
184
  }
171
185
  useSoftDelete(enabled) {
172
- return this.softdelete = !!enabled;
186
+ return (this.softdelete = !!enabled);
173
187
  }
174
188
  usesSoftDelete() {
175
189
  return this.softdelete;
@@ -180,26 +194,26 @@ export class Mongo extends Db {
180
194
  * unless `returnArchived: true` is passed in opts.
181
195
  */
182
196
  useArchive(enabled) {
183
- return this.softarchive = !!enabled;
197
+ return (this.softarchive = !!enabled);
184
198
  }
185
199
  usesArchive() {
186
200
  return this.softarchive;
187
201
  }
188
202
  useAuditing(enabled) {
189
- return this.auditing = enabled;
203
+ return (this.auditing = enabled);
190
204
  }
191
205
  usesAuditing() {
192
206
  return this.auditing;
193
207
  }
194
208
  useSync(enabled) {
195
- return this.syncSupport = enabled;
209
+ return (this.syncSupport = enabled);
196
210
  }
197
211
  usesSync() {
198
212
  return this.syncSupport;
199
213
  }
200
214
  auditToCollection(c) {
201
215
  if (c)
202
- return this.auditCollectionName = c;
216
+ return (this.auditCollectionName = c);
203
217
  return this.auditCollectionName;
204
218
  }
205
219
  auditCollection(coll, enable = true) {
@@ -239,17 +253,23 @@ export class Mongo extends Db {
239
253
  if (arr === undefined)
240
254
  return this.auditedCollections;
241
255
  if (arr && typeof arr === "string")
242
- this.auditedCollections = arr.toString().split(',').map(a => a.trim().toLowerCase()).filter(a => !!a);
256
+ this.auditedCollections = arr
257
+ .toString()
258
+ .split(",")
259
+ .map((a) => a.trim().toLowerCase())
260
+ .filter((a) => !!a);
243
261
  if (arr instanceof Array)
244
- this.auditedCollections = arr.map(a => a.trim().toLowerCase()).filter(a => !!a);
245
- this.auditedCollectionsLower = this.auditedCollections.map(a => a.toLowerCase());
262
+ this.auditedCollections = arr
263
+ .map((a) => a.trim().toLowerCase())
264
+ .filter((a) => !!a);
265
+ this.auditedCollectionsLower = this.auditedCollections.map((a) => a.toLowerCase());
246
266
  return this.auditedCollections;
247
267
  }
248
268
  auditingCollection(coll, db = this.db) {
249
269
  return this._shouldAuditCollection(db, coll);
250
270
  }
251
271
  emitPublishEvents(enabled) {
252
- return this.emittingPublishEvents = enabled;
272
+ return (this.emittingPublishEvents = enabled);
253
273
  }
254
274
  emitsPublishEvents() {
255
275
  return this.emittingPublishEvents;
@@ -261,7 +281,7 @@ export class Mongo extends Db {
261
281
  }
262
282
  if (enabled)
263
283
  fjLog.debug("publishing rev events");
264
- return this.emittingPublishRevEvents = enabled;
284
+ return (this.emittingPublishRevEvents = enabled);
265
285
  }
266
286
  emitsPublishRevEvents() {
267
287
  return this.emittingPublishRevEvents;
@@ -273,13 +293,13 @@ export class Mongo extends Db {
273
293
  async distinct(collection, field, opts = {}) {
274
294
  assert(collection, "collection is required", "distinct");
275
295
  assert(field, "field is required", "distinct", { collection });
276
- fjLog.debug('distinct called', collection, field);
296
+ fjLog.debug("distinct called", collection, field);
277
297
  const dbName = this.db;
278
298
  let client = await this.connect();
279
299
  let conn = client.db(dbName).collection(collection);
280
300
  let ret = await conn.distinct(field, {}, opts);
281
301
  ret.sort();
282
- fjLog.debug('distinct returns', ret);
302
+ fjLog.debug("distinct returns", ret);
283
303
  return ret;
284
304
  }
285
305
  async count(collection, query = {}, opts = {}) {
@@ -292,11 +312,11 @@ export class Mongo extends Db {
292
312
  if (!query._archived)
293
313
  query._archived = { $exists: false };
294
314
  }
295
- fjLog.debug('count called', collection, query, opts);
315
+ fjLog.debug("count called", collection, query, opts);
296
316
  let ret = await this.executeTransactionally(collection, async (conn) => {
297
317
  return await conn.countDocuments(query, opts);
298
318
  }, false, { operation: "count", collection, query, opts });
299
- fjLog.debug('count returns', ret);
319
+ fjLog.debug("count returns", ret);
300
320
  return ret;
301
321
  }
302
322
  async find(collection, query = {}, opts = {}) {
@@ -310,12 +330,12 @@ export class Mongo extends Db {
310
330
  if (!query._archived)
311
331
  query._archived = { $exists: false };
312
332
  }
313
- fjLog.debug('find called', collection, query, opts);
333
+ fjLog.debug("find called", collection, query, opts);
314
334
  let ret = await this.executeTransactionally(collection, async (conn) => {
315
335
  let r = this._applyQueryOpts(conn.find(query, this._buildFindOptions(opts)), opts);
316
336
  return this._processReturnedObject(await r.toArray());
317
337
  }, false, { operation: "find", collection, query, opts });
318
- fjLog.debug('find returns', ret);
338
+ fjLog.debug("find returns", ret);
319
339
  return ret;
320
340
  }
321
341
  async findAll(collection, query = {}, opts = {}) {
@@ -325,7 +345,7 @@ export class Mongo extends Db {
325
345
  let r = this._applyQueryOpts(conn.find(query, this._buildFindOptions(opts)), opts);
326
346
  return this._processReturnedObject(await r.toArray());
327
347
  }, false, { operation: "findAll", collection, query, opts });
328
- fjLog.debug('findAll returns', ret);
348
+ fjLog.debug("findAll returns", ret);
329
349
  return ret;
330
350
  }
331
351
  async findNewer(collection, timestamp, query = {}, opts = {}) {
@@ -338,12 +358,12 @@ export class Mongo extends Db {
338
358
  if (!query._archived)
339
359
  query._archived = { $exists: false };
340
360
  }
341
- fjLog.debug('findNewer called', collection, timestamp, query, opts);
361
+ fjLog.debug("findNewer called", collection, timestamp, query, opts);
342
362
  let ret = await this.executeTransactionally(collection, async (conn) => {
343
363
  let r = this._applyQueryOpts(conn.find(query, this._buildFindOptions(opts)).sort({ _ts: 1 }), opts);
344
364
  return this._processReturnedObject(await r.toArray(), this._findNewerRemoveFields);
345
365
  }, false, { operation: "findNewer", collection, timestamp, query, opts });
346
- fjLog.debug('findNewer returns', ret);
366
+ fjLog.debug("findNewer returns", ret);
347
367
  return ret;
348
368
  }
349
369
  /**
@@ -357,7 +377,7 @@ export class Mongo extends Db {
357
377
  */
358
378
  async findNewerMany(spec = [], defaultOpts = {}) {
359
379
  var _a;
360
- fjLog.debug('findNewerMany called', spec);
380
+ fjLog.debug("findNewerMany called", spec);
361
381
  const dbName = this.db; // Capture db at operation start
362
382
  let conn = await this.connect();
363
383
  const getOneColl = async (coll) => {
@@ -375,7 +395,11 @@ export class Mongo extends Db {
375
395
  if (process.env.MONGO_DEBUG_FINDNEWERMANY) {
376
396
  fjLog.debug("findNewerMany <-", coll.collection, coll.specId, coll.timestamp, coll.query, " -> ", JSON.stringify(query));
377
397
  }
378
- let r = this._applyQueryOpts(conn.db(dbName).collection(coll.collection).find(query, {}).sort({ _ts: 1 }), opts);
398
+ let r = this._applyQueryOpts(conn
399
+ .db(dbName)
400
+ .collection(coll.collection)
401
+ .find(query, {})
402
+ .sort({ _ts: 1 }), opts);
379
403
  let data = await r.toArray();
380
404
  if (process.env.MONGO_DEBUG_FINDNEWERMANY) {
381
405
  fjLog.debug("findNewerMany ->", coll.collection, JSON.stringify(data, null, 2));
@@ -397,7 +421,9 @@ export class Mongo extends Db {
397
421
  for (let coll of spec)
398
422
  promises.push(getOneColl(coll));
399
423
  let out = {};
400
- (await Promise.all(promises)).filter(r => r.data.length).forEach(r => out[r.key] = r.data);
424
+ (await Promise.all(promises))
425
+ .filter((r) => r.data.length)
426
+ .forEach((r) => (out[r.key] = r.data));
401
427
  return out;
402
428
  }
403
429
  }
@@ -417,7 +443,7 @@ export class Mongo extends Db {
417
443
  * @param defaultOpts - Default query options applied to all collections
418
444
  */
419
445
  async findNewerManyStream(spec = [], onChunk, chunkSize = 200, defaultOpts = {}) {
420
- fjLog.debug('findNewerManyStream called', spec);
446
+ fjLog.debug("findNewerManyStream called", spec);
421
447
  const dbName = this.db;
422
448
  let conn = await this.connect();
423
449
  for (const coll of spec) {
@@ -431,7 +457,11 @@ export class Mongo extends Db {
431
457
  if (!query._archived)
432
458
  query._archived = { $exists: false };
433
459
  }
434
- let cursor = this._applyQueryOpts(conn.db(dbName).collection(coll.collection).find(query, {}).sort({ _ts: 1 }), opts);
460
+ let cursor = this._applyQueryOpts(conn
461
+ .db(dbName)
462
+ .collection(coll.collection)
463
+ .find(query, {})
464
+ .sort({ _ts: 1 }), opts);
435
465
  let chunk = [];
436
466
  for await (const doc of cursor) {
437
467
  this._processReturnedObject(doc, this._findNewerRemoveFields);
@@ -449,7 +479,7 @@ export class Mongo extends Db {
449
479
  async latestTimestamps(collections) {
450
480
  assert(collections, "collections is required", "latestTimestamps");
451
481
  assert(collections instanceof Array, "collections must be an Array", "latestTimestamps");
452
- fjLog.debug('latestTimestamps called', collections);
482
+ fjLog.debug("latestTimestamps called", collections);
453
483
  const dbName = this.db; // Capture db at operation start
454
484
  let conn = await this.connect();
455
485
  const getOne = async (collection) => {
@@ -469,15 +499,17 @@ export class Mongo extends Db {
469
499
  for (let c of collections)
470
500
  promises.push(getOne(c));
471
501
  let out = {};
472
- (await Promise.all(promises)).forEach(r => { if (r.ts)
473
- out[r.collection] = r.ts; });
474
- fjLog.debug('latestTimestamps returns', out);
502
+ (await Promise.all(promises)).forEach((r) => {
503
+ if (r.ts)
504
+ out[r.collection] = r.ts;
505
+ });
506
+ fjLog.debug("latestTimestamps returns", out);
475
507
  return out;
476
508
  }
477
509
  async latestTimestamp(collection) {
478
510
  var _a;
479
511
  assert(collection, "collection is required", "latestTimestamp");
480
- fjLog.debug('latestTimestamp called', collection);
512
+ fjLog.debug("latestTimestamp called", collection);
481
513
  const dbName = this.db; // Capture db at operation start
482
514
  let conn = await this.connect();
483
515
  let cursor = conn
@@ -489,11 +521,11 @@ export class Mongo extends Db {
489
521
  .limit(1);
490
522
  let res = await cursor.toArray();
491
523
  let ts = (_a = res === null || res === void 0 ? void 0 : res[0]) === null || _a === void 0 ? void 0 : _a._ts;
492
- fjLog.debug('latestTimestamp returns', ts);
524
+ fjLog.debug("latestTimestamp returns", ts);
493
525
  return ts;
494
526
  }
495
527
  _createQueryForNewer(timestamp, query) {
496
- let ts = (timestamp === 1 || timestamp === "1" || timestamp === "0" || !timestamp)
528
+ let ts = timestamp === 1 || timestamp === "1" || timestamp === "0" || !timestamp
497
529
  ? {}
498
530
  : { _ts: { $gt: Base.timestamp(timestamp) } };
499
531
  if (query) {
@@ -572,9 +604,12 @@ export class Mongo extends Db {
572
604
  query._archived = { $exists: false };
573
605
  }
574
606
  // if (!query._blocked) query._blocked = { $exists: false }; // intentionally - blocked records are returned
575
- fjLog.debug('findOne called', collection, query, projection);
576
- let ret = await this.executeTransactionally(collection, async (conn) => await conn.findOne(query, { ...(projection ? { projection } : {}), ...this._sessionOpt() }), false, { operation: "findOne", collection, query, projection });
577
- fjLog.debug('findOne returns', ret);
607
+ fjLog.debug("findOne called", collection, query, projection);
608
+ let ret = await this.executeTransactionally(collection, async (conn) => await conn.findOne(query, {
609
+ ...(projection ? { projection } : {}),
610
+ ...this._sessionOpt(),
611
+ }), false, { operation: "findOne", collection, query, projection });
612
+ fjLog.debug("findOne returns", ret);
578
613
  return this._processReturnedObject(ret);
579
614
  }
580
615
  async findById(collection, id, projection, opts = {}) {
@@ -592,27 +627,30 @@ export class Mongo extends Db {
592
627
  if (this.softarchive && !opts.returnArchived) {
593
628
  query._archived = { $exists: false };
594
629
  }
595
- fjLog.debug('findById called', dbName, collection, id, projection);
596
- fjLog.trace('findById executing with query', collection, query, projection);
630
+ fjLog.debug("findById called", dbName, collection, id, projection);
631
+ fjLog.trace("findById executing with query", collection, query, projection);
597
632
  let ret = await this.executeTransactionally(collection, async (conn) => {
598
- let r = await conn.findOne(query, { ...(projection ? { projection } : {}), ...this._sessionOpt() });
633
+ let r = await conn.findOne(query, {
634
+ ...(projection ? { projection } : {}),
635
+ ...this._sessionOpt(),
636
+ });
599
637
  return r;
600
638
  }, false, { operation: "findById", collection, id, projection });
601
- fjLog.debug('findById returns', ret);
639
+ fjLog.debug("findById returns", ret);
602
640
  return this._processReturnedObject(ret);
603
641
  }
604
642
  async findByIdsInManyCollections(request, opts = {}) {
605
643
  if (!request || request.length === 0)
606
644
  return {};
607
645
  const dbName = this.db;
608
- fjLog.debug('findByIdsInManyCollections called', dbName, request);
646
+ fjLog.debug("findByIdsInManyCollections called", dbName, request);
609
647
  // Process all collections in parallel
610
648
  const fetchOne = async (req) => {
611
649
  const { collection, ids, projection } = req;
612
650
  if (!collection || !ids || ids.length === 0) {
613
651
  return { collection, entities: [] };
614
652
  }
615
- const objectIds = ids.map(id => Mongo._toId(id));
653
+ const objectIds = ids.map((id) => Mongo._toId(id));
616
654
  const entities = await this.executeTransactionally(collection, async (conn) => {
617
655
  let query = { _id: { $in: objectIds } };
618
656
  if (this.softdelete && !opts.returnDeleted) {
@@ -621,17 +659,28 @@ export class Mongo extends Db {
621
659
  if (this.softarchive && !opts.returnArchived) {
622
660
  query._archived = { $exists: false };
623
661
  }
624
- let r = conn.find(query, { ...(projection ? { projection } : {}), ...this._sessionOpt() });
662
+ let r = conn.find(query, {
663
+ ...(projection ? { projection } : {}),
664
+ ...this._sessionOpt(),
665
+ });
625
666
  return await r.toArray();
626
- }, false, { operation: "findByIdsInManyCollections", collection, ids, projection });
627
- return { collection, entities: this._processReturnedObject(entities) };
667
+ }, false, {
668
+ operation: "findByIdsInManyCollections",
669
+ collection,
670
+ ids,
671
+ projection,
672
+ });
673
+ return {
674
+ collection,
675
+ entities: this._processReturnedObject(entities),
676
+ };
628
677
  };
629
678
  const results = await Promise.all(request.map(fetchOne));
630
679
  const result = {};
631
680
  for (const { collection, entities } of results) {
632
681
  result[collection] = entities;
633
682
  }
634
- fjLog.debug('findByIdsInManyCollections returns', result);
683
+ fjLog.debug("findByIdsInManyCollections returns", result);
635
684
  return result;
636
685
  }
637
686
  async findByIds(collection, ids, projection, opts = {}) {
@@ -640,8 +689,8 @@ export class Mongo extends Db {
640
689
  if (!ids || ids.length === 0)
641
690
  return [];
642
691
  const dbName = this.db;
643
- const objectIds = ids.map(id => Mongo._toId(id));
644
- fjLog.debug('findByIds called', dbName, collection, ids, projection);
692
+ const objectIds = ids.map((id) => Mongo._toId(id));
693
+ fjLog.debug("findByIds called", dbName, collection, ids, projection);
645
694
  let ret = await this.executeTransactionally(collection, async (conn) => {
646
695
  let query = { _id: { $in: objectIds } };
647
696
  if (this.softdelete && !opts.returnDeleted) {
@@ -650,10 +699,13 @@ export class Mongo extends Db {
650
699
  if (this.softarchive && !opts.returnArchived) {
651
700
  query._archived = { $exists: false };
652
701
  }
653
- let r = conn.find(query, { ...(projection ? { projection } : {}), ...this._sessionOpt() });
702
+ let r = conn.find(query, {
703
+ ...(projection ? { projection } : {}),
704
+ ...this._sessionOpt(),
705
+ });
654
706
  return await r.toArray();
655
707
  }, false, { operation: "findByIds", collection, ids, projection });
656
- fjLog.debug('findByIds returns', ret);
708
+ fjLog.debug("findByIds returns", ret);
657
709
  return this._processReturnedObject(ret);
658
710
  }
659
711
  async updateOne(collection, query, update, options = { returnFullObject: false }) {
@@ -666,7 +718,7 @@ export class Mongo extends Db {
666
718
  let opts = {
667
719
  upsert: false,
668
720
  returnDocument: "after",
669
- ...this._sessionOpt()
721
+ ...this._sessionOpt(),
670
722
  };
671
723
  if (this._hasHashedKeys(update))
672
724
  await this._processHashedKeys(update);
@@ -682,24 +734,33 @@ export class Mongo extends Db {
682
734
  const isPipeline = Array.isArray(processed.update);
683
735
  // For pipeline form, sequence-keys auto-injection cannot recurse into array of stages.
684
736
  // Skip the `update.$set` normalization and seqKeys path entirely when pipeline.
685
- let seqKeys = isPipeline ? undefined : this._findSequenceKeys(update.$set);
686
- fjLog.debug('updateOne called', collection, query, update);
737
+ let seqKeys = isPipeline
738
+ ? undefined
739
+ : this._findSequenceKeys(update.$set);
740
+ fjLog.debug("updateOne called", collection, query, update);
687
741
  let obj = await this.executeTransactionally(collection, async (conn, client) => {
688
742
  if (!isPipeline) {
689
743
  update.$set = update.$set || {};
690
744
  if (seqKeys)
691
745
  await this._processSequenceField(client, dbName, collection, update.$set, seqKeys);
692
- if (update.$set === undefined || Object.keys(update.$set).length === 0)
746
+ if (update.$set === undefined ||
747
+ Object.keys(update.$set).length === 0)
693
748
  delete update.$set;
694
749
  }
695
750
  let res = await conn.findOneAndUpdate(query, processed.update, opts);
696
751
  if (!res)
697
752
  return null;
698
753
  let resObj = this._buildPublishDelta(res, inputUpdate, !!(options === null || options === void 0 ? void 0 : options.returnFullObject));
699
- await this._publishAndAudit('update', dbName, collection, resObj, false, inputUpdate);
754
+ await this._publishAndAudit("update", dbName, collection, resObj, false, inputUpdate);
700
755
  return resObj;
701
- }, !!seqKeys, { operation: "updateOne", collection, query, update: processed.update, options });
702
- fjLog.debug('updateOne returns', obj);
756
+ }, !!seqKeys, {
757
+ operation: "updateOne",
758
+ collection,
759
+ query,
760
+ update: processed.update,
761
+ options,
762
+ });
763
+ fjLog.debug("updateOne returns", obj);
703
764
  return this._processReturnedObject(await obj);
704
765
  }
705
766
  async save(collection, update, id = undefined, options = { returnFullObject: false }) {
@@ -710,7 +771,7 @@ export class Mongo extends Db {
710
771
  let opts = {
711
772
  upsert: true,
712
773
  returnDocument: "after",
713
- ...this._sessionOpt()
774
+ ...this._sessionOpt(),
714
775
  };
715
776
  let _id = Mongo.toId(id || update._id) || Mongo.newid();
716
777
  if (this._hasHashedKeys(update))
@@ -721,24 +782,25 @@ export class Mongo extends Db {
721
782
  if (processed.arrayFilters)
722
783
  opts.arrayFilters = processed.arrayFilters;
723
784
  const isPipeline = Array.isArray(processed.update);
724
- fjLog.debug('save called', collection, id, update);
785
+ fjLog.debug("save called", collection, id, update);
725
786
  let seqKeys = isPipeline ? undefined : this._findSequenceKeys(update.$set);
726
787
  let obj = await this.executeTransactionally(collection, async (conn, client) => {
727
788
  if (!isPipeline) {
728
789
  update.$set = update.$set || {};
729
790
  if (seqKeys)
730
791
  await this._processSequenceField(client, dbName, collection, update.$set, seqKeys);
731
- if (update.$set === undefined || Object.keys(update.$set).length === 0)
792
+ if (update.$set === undefined ||
793
+ Object.keys(update.$set).length === 0)
732
794
  delete update.$set;
733
795
  }
734
796
  let res = await conn.findOneAndUpdate({ _id }, processed.update, opts);
735
797
  if (!res)
736
798
  return null;
737
799
  let resObj = this._buildPublishDelta(res, inputUpdate, !!(options === null || options === void 0 ? void 0 : options.returnFullObject));
738
- await this._publishAndAudit('update', dbName, collection, resObj, false, inputUpdate);
800
+ await this._publishAndAudit("update", dbName, collection, resObj, false, inputUpdate);
739
801
  return resObj;
740
802
  }, !!seqKeys, { operation: "save", collection, _id, update: processed.update, options });
741
- fjLog.debug('save returns', obj);
803
+ fjLog.debug("save returns", obj);
742
804
  return this._processReturnedObject(await obj);
743
805
  }
744
806
  async update(collection, query, update) {
@@ -754,7 +816,7 @@ export class Mongo extends Db {
754
816
  let opts = {
755
817
  upsert: false,
756
818
  returnDocument: "after",
757
- ...this._sessionOpt()
819
+ ...this._sessionOpt(),
758
820
  };
759
821
  if (this._hasHashedKeys(update))
760
822
  await this._processHashedKeys(update);
@@ -763,36 +825,39 @@ export class Mongo extends Db {
763
825
  if (processed.arrayFilters)
764
826
  opts.arrayFilters = processed.arrayFilters;
765
827
  const isPipeline = Array.isArray(processed.update);
766
- fjLog.debug('update called', collection, query, update);
828
+ fjLog.debug("update called", collection, query, update);
767
829
  let seqKeys = isPipeline ? undefined : this._findSequenceKeys(update.$set);
768
830
  let obj = await this.executeTransactionally(collection, async (conn, client) => {
769
831
  if (!isPipeline) {
770
832
  update.$set = update.$set || {};
771
833
  if (seqKeys)
772
834
  await this._processSequenceField(client, dbName, collection, update.$set, seqKeys);
773
- if (update.$set === undefined || Object.keys(update.$set).length === 0)
835
+ if (update.$set === undefined ||
836
+ Object.keys(update.$set).length === 0)
774
837
  delete update.$set;
775
838
  }
776
- fjLog.debug('update called', collection, query, update);
839
+ fjLog.debug("update called", collection, query, update);
777
840
  let res = await conn.updateMany(query, processed.update, opts);
778
841
  let resObj = {
779
842
  n: res.modifiedCount,
780
- ok: !!res.acknowledged
843
+ ok: !!res.acknowledged,
781
844
  };
782
845
  // No `rawUpdate` for `updateMany` — mongo doesn't return per-doc _id-s,
783
846
  // so the spec is not actionable on the consumer side. Subscribers see
784
847
  // `enquireLastTs: true` on the rev event and refetch via `findNewer*`.
785
- await this._publishAndAudit('updateMany', dbName, collection, resObj);
848
+ await this._publishAndAudit("updateMany", dbName, collection, resObj);
786
849
  return resObj;
787
850
  }, !!seqKeys, { operation: "update", collection, query, update: processed.update });
788
- fjLog.debug('update returns', obj);
851
+ fjLog.debug("update returns", obj);
789
852
  return await obj;
790
853
  }
791
854
  async upsert(collection, query, update, options = { returnFullObject: false }) {
792
855
  assert(collection, "collection is required", "upsert");
793
856
  assert(query, "query is required", "upsert", { collection });
794
857
  assert(update, "update is required", "upsert", { collection });
795
- assert(typeof update === 'object', "update must be an object", "upsert", { collection });
858
+ assert(typeof update === "object", "update must be an object", "upsert", {
859
+ collection,
860
+ });
796
861
  // if (!Object.keys(update).length) return null;
797
862
  const dbName = this.db; // Capture db at operation start
798
863
  query = this.replaceIds(query);
@@ -801,9 +866,9 @@ export class Mongo extends Db {
801
866
  ...options,
802
867
  upsert: true,
803
868
  returnDocument: "after",
804
- ...this._sessionOpt()
869
+ ...this._sessionOpt(),
805
870
  };
806
- fjLog.debug('upsert called', collection, query, update);
871
+ fjLog.debug("upsert called", collection, query, update);
807
872
  if (this._hasHashedKeys(update))
808
873
  await this._processHashedKeys(update);
809
874
  const inputUpdate = cloneDeep(update);
@@ -813,7 +878,7 @@ export class Mongo extends Db {
813
878
  opts.arrayFilters = processed.arrayFilters;
814
879
  const isPipeline = Array.isArray(processed.update);
815
880
  let seqKeys = isPipeline ? undefined : this._findSequenceKeys(update.$set);
816
- fjLog.debug('upsert processed', collection, query, update);
881
+ fjLog.debug("upsert processed", collection, query, update);
817
882
  if (Object.keys(query).length === 0)
818
883
  query._id = Mongo.newid();
819
884
  let ret = await this.executeTransactionally(collection, async (conn, client) => {
@@ -821,7 +886,8 @@ export class Mongo extends Db {
821
886
  update.$set = update.$set || {};
822
887
  if (seqKeys)
823
888
  await this._processSequenceField(client, dbName, collection, update.$set, seqKeys);
824
- if (update.$set === undefined || Object.keys(update.$set).length === 0)
889
+ if (update.$set === undefined ||
890
+ Object.keys(update.$set).length === 0)
825
891
  delete update.$set;
826
892
  }
827
893
  let ret = await conn.findOneAndUpdate(query, processed.update, opts);
@@ -832,21 +898,24 @@ export class Mongo extends Db {
832
898
  // For inserts, surface the full record (query fields like {a:4} need to land);
833
899
  // for updates, build the de-bracketed delta. rawUpdate is sent on update only —
834
900
  // an insert isn't a delta against a prior state, so the spec adds no signal there.
835
- let retObj = isInsert ? ret : this._buildPublishDelta(ret, inputUpdate, !!(options === null || options === void 0 ? void 0 : options.returnFullObject));
901
+ let retObj = isInsert
902
+ ? ret
903
+ : this._buildPublishDelta(ret, inputUpdate, !!(options === null || options === void 0 ? void 0 : options.returnFullObject));
836
904
  await this._publishAndAudit(oper, dbName, collection, retObj, false, isInsert ? undefined : inputUpdate);
837
905
  return this._buildPublishDelta(ret, inputUpdate, !!(options === null || options === void 0 ? void 0 : options.returnFullObject));
838
906
  }
839
- ;
840
907
  return ret;
841
908
  }, !!seqKeys, { operation: "upsert", query, update, options });
842
- fjLog.debug('upsert returns', ret);
909
+ fjLog.debug("upsert returns", ret);
843
910
  return this._processReturnedObject(await ret);
844
911
  }
845
912
  async insert(collection, insert) {
846
913
  assert(collection, "collection is required", "insert");
847
914
  assert(insert, "insert is required", "insert", { collection });
848
- assert(typeof insert === "object", "insert must be an object", "insert", { collection });
849
- fjLog.debug('insert called', collection, insert);
915
+ assert(typeof insert === "object", "insert must be an object", "insert", {
916
+ collection,
917
+ });
918
+ fjLog.debug("insert called", collection, insert);
850
919
  const dbName = this.db; // Capture db at operation start
851
920
  insert = this.replaceIds(insert);
852
921
  this._stripDoubleUnderscoreKeys(insert);
@@ -861,10 +930,10 @@ export class Mongo extends Db {
861
930
  insert = await this._processSequenceField(client, dbName, collection, insert, seqKeys);
862
931
  let obj = await conn.insertOne(insert, this._sessionOpt());
863
932
  let fullObj = { _id: obj.insertedId, ...insert };
864
- await this._publishAndAudit('insert', dbName, collection, fullObj);
933
+ await this._publishAndAudit("insert", dbName, collection, fullObj);
865
934
  return fullObj;
866
935
  }, !!seqKeys, { operation: "insert", collection, insert });
867
- fjLog.debug('insert returns', ret);
936
+ fjLog.debug("insert returns", ret);
868
937
  return this._processReturnedObject(await ret);
869
938
  }
870
939
  /**
@@ -880,7 +949,7 @@ export class Mongo extends Db {
880
949
  assert(collectionsBatches, "collectionsBatches is required", "updateCollections");
881
950
  assert(collectionsBatches instanceof Array, "collectionsBatches must be an Array", "updateCollections");
882
951
  const debugMethod = MONGO_DEBUG_UPDATE_COLLECTIONS ? "info" : "debug";
883
- (_a = fjLog === null || fjLog === void 0 ? void 0 : fjLog[debugMethod]) === null || _a === void 0 ? void 0 : _a.call(fjLog, 'updateCollections called', collectionsBatches.length, 'collections');
952
+ (_a = fjLog === null || fjLog === void 0 ? void 0 : fjLog[debugMethod]) === null || _a === void 0 ? void 0 : _a.call(fjLog, "updateCollections called", collectionsBatches.length, "collections");
884
953
  (_b = fjLog === null || fjLog === void 0 ? void 0 : fjLog[debugMethod]) === null || _b === void 0 ? void 0 : _b.call(fjLog, collectionsBatches);
885
954
  const dbName = this.db;
886
955
  const conn = await this.connect();
@@ -898,7 +967,7 @@ export class Mongo extends Db {
898
967
  updated: [],
899
968
  deleted: [],
900
969
  mustRefresh: [],
901
- }
970
+ },
902
971
  };
903
972
  const batchData = [];
904
973
  const errors = [];
@@ -907,12 +976,12 @@ export class Mongo extends Db {
907
976
  // server-side (SEQ_*/__hashed__)? Captured BEFORE the bulk sequence
908
977
  // resolution and per-update hashing mutate the updates in place, so
909
978
  // the placeholders are still observable here.
910
- const updateResolvedFlags = (updates !== null && updates !== void 0 ? updates : []).map(u => this._hasSequenceFields(u.update) || this._hasHashedKeys(u.update));
979
+ const updateResolvedFlags = (updates !== null && updates !== void 0 ? updates : []).map((u) => this._hasSequenceFields(u.update) || this._hasHashedKeys(u.update));
911
980
  // Handle sequences in updates before processing
912
981
  if (updates === null || updates === void 0 ? void 0 : updates.length) {
913
- const updatesWithSeq = updates.filter(u => this._hasSequenceFields(u.update));
982
+ const updatesWithSeq = updates.filter((u) => this._hasSequenceFields(u.update));
914
983
  if (updatesWithSeq.length > 0) {
915
- await this._processSequenceFieldForMany(conn, dbName, collection, updatesWithSeq.map(u => u.update));
984
+ await this._processSequenceFieldForMany(conn, dbName, collection, updatesWithSeq.map((u) => u.update));
916
985
  }
917
986
  }
918
987
  // Process updates (with upsert) in parallel
@@ -929,7 +998,7 @@ export class Mongo extends Db {
929
998
  const processed = this._applyBracketProcessing(processedBase);
930
999
  if (processed.warnings) {
931
1000
  for (const w of processed.warnings) {
932
- const msg = w.kind === 'overlap'
1001
+ const msg = w.kind === "overlap"
933
1002
  ? `same-id overlap at "${w.path}" — terminal-bracket value ${JSON.stringify(w.value)} sets the element base; sub-field overlay applies on top`
934
1003
  : `dropped nested-bracket ${w.op} path "${w.path}" = ${JSON.stringify(w.value)}`;
935
1004
  warnings.push({ _id: String(_id), error: msg });
@@ -939,8 +1008,10 @@ export class Mongo extends Db {
939
1008
  upsert: true,
940
1009
  returnDocument: "after",
941
1010
  includeResultMetadata: true,
942
- ...(processed.arrayFilters ? { arrayFilters: processed.arrayFilters } : {}),
943
- ...this._sessionOpt()
1011
+ ...(processed.arrayFilters
1012
+ ? { arrayFilters: processed.arrayFilters }
1013
+ : {}),
1014
+ ...this._sessionOpt(),
944
1015
  };
945
1016
  (_a = fjLog === null || fjLog === void 0 ? void 0 : fjLog[debugMethod]) === null || _a === void 0 ? void 0 : _a.call(fjLog, ` updateCollections findOneAndUpdate ${dbName}.${collection}`, { _id: objectId }, "UPDATE", processed.update, "opts", opts);
946
1017
  const res = await conn
@@ -950,7 +1021,9 @@ export class Mongo extends Db {
950
1021
  if (res === null || res === void 0 ? void 0 : res.value) {
951
1022
  // Determine if this was an insert or update based on lastErrorObject
952
1023
  const wasInsert = !((_b = res.lastErrorObject) === null || _b === void 0 ? void 0 : _b.updatedExisting);
953
- const operation = wasInsert ? 'insert' : 'update';
1024
+ const operation = wasInsert
1025
+ ? "insert"
1026
+ : "update";
954
1027
  // mustRefresh: the client must replace its local copy when cry-db
955
1028
  // resolved a field (SEQ_*/__hashed__) OR a concurrent external write
956
1029
  // advanced the stored `_rev` beyond this write (gap > the +1 this write
@@ -958,10 +1031,10 @@ export class Mongo extends Db {
958
1031
  // old-client fallback. Built from a sanitized clone (hash never leaks).
959
1032
  const writtenRev = res.value._rev;
960
1033
  const inc = this.revisions ? 1 : 0;
961
- const externallyModified = !wasInsert
962
- && typeof writtenRev === 'number'
963
- && (writtenRev - inc) > (clientRev !== null && clientRev !== void 0 ? clientRev : 0);
964
- const mustRefresh = (updateResolvedFlags[idx] || externallyModified)
1034
+ const externallyModified = !wasInsert &&
1035
+ typeof writtenRev === "number" &&
1036
+ writtenRev - inc > (clientRev !== null && clientRev !== void 0 ? clientRev : 0);
1037
+ const mustRefresh = updateResolvedFlags[idx] || externallyModified
965
1038
  ? this._buildMustRefreshRecord(res.value)
966
1039
  : undefined;
967
1040
  // Inserts surface the full doc (query fields must reach the client).
@@ -972,12 +1045,24 @@ export class Mongo extends Db {
972
1045
  ? res.value
973
1046
  : this._buildPublishDelta(res.value, inputUpdate, false);
974
1047
  this._processReturnedObject(retObj);
975
- return { success: true, _id, data: retObj, operation, wasInsert, rawUpdate: wasInsert ? undefined : inputUpdate, mustRefresh };
1048
+ return {
1049
+ success: true,
1050
+ _id,
1051
+ data: retObj,
1052
+ operation,
1053
+ wasInsert,
1054
+ rawUpdate: wasInsert ? undefined : inputUpdate,
1055
+ mustRefresh,
1056
+ };
976
1057
  }
977
- return { success: false, _id, error: 'Operation failed' };
1058
+ return { success: false, _id, error: "Operation failed" };
978
1059
  }
979
1060
  catch (err) {
980
- return { success: false, _id, error: err.message || String(err) };
1061
+ return {
1062
+ success: false,
1063
+ _id,
1064
+ error: err.message || String(err),
1065
+ };
981
1066
  }
982
1067
  });
983
1068
  const updateResults = await Promise.all(updatePromises);
@@ -1021,26 +1106,32 @@ export class Mongo extends Db {
1021
1106
  // Hard delete applies no `_rev` increment: the removed doc's `_rev`
1022
1107
  // exceeding the client's base means an external write landed first.
1023
1108
  // Omitted `_rev` (clientRev → 0) forces a refresh — old-client fallback.
1024
- const externallyModified = typeof res._rev === 'number'
1025
- && res._rev > (clientRev !== null && clientRev !== void 0 ? clientRev : 0);
1109
+ const externallyModified = typeof res._rev === "number" &&
1110
+ res._rev > (clientRev !== null && clientRev !== void 0 ? clientRev : 0);
1026
1111
  const mustRefresh = externallyModified
1027
1112
  ? this._buildMustRefreshRecord(res)
1028
1113
  : undefined;
1029
1114
  this._processReturnedObject(res);
1030
- return { success: true, _id, data: res, operation: 'delete', mustRefresh };
1115
+ return {
1116
+ success: true,
1117
+ _id,
1118
+ data: res,
1119
+ operation: "delete",
1120
+ mustRefresh,
1121
+ };
1031
1122
  }
1032
- return { success: false, _id, error: 'Document not found' };
1123
+ return { success: false, _id, error: "Document not found" };
1033
1124
  }
1034
1125
  else {
1035
1126
  const del = {
1036
1127
  $set: { _deleted: new Date() },
1037
1128
  $inc: { _rev: 1 },
1038
- $currentDate: { _ts: { $type: 'timestamp' } }
1129
+ $currentDate: { _ts: { $type: "timestamp" } },
1039
1130
  };
1040
1131
  const opts = {
1041
1132
  upsert: false,
1042
1133
  returnDocument: "after",
1043
- ...this._sessionOpt()
1134
+ ...this._sessionOpt(),
1044
1135
  };
1045
1136
  const res = await conn
1046
1137
  .db(dbName)
@@ -1050,19 +1141,29 @@ export class Mongo extends Db {
1050
1141
  // Soft delete applied a +1 `_rev` increment: a gap beyond that +1
1051
1142
  // means an external write modified the record before this delete.
1052
1143
  // Omitted `_rev` (clientRev → 0) forces a refresh — old-client fallback.
1053
- const externallyModified = typeof res._rev === 'number'
1054
- && (res._rev - 1) > (clientRev !== null && clientRev !== void 0 ? clientRev : 0);
1144
+ const externallyModified = typeof res._rev === "number" &&
1145
+ res._rev - 1 > (clientRev !== null && clientRev !== void 0 ? clientRev : 0);
1055
1146
  const mustRefresh = externallyModified
1056
1147
  ? this._buildMustRefreshRecord(res)
1057
1148
  : undefined;
1058
1149
  this._processReturnedObject(res);
1059
- return { success: true, _id, data: res, operation: 'delete', mustRefresh };
1150
+ return {
1151
+ success: true,
1152
+ _id,
1153
+ data: res,
1154
+ operation: "delete",
1155
+ mustRefresh,
1156
+ };
1060
1157
  }
1061
- return { success: false, _id, error: 'Document not found' };
1158
+ return { success: false, _id, error: "Document not found" };
1062
1159
  }
1063
1160
  }
1064
1161
  catch (err) {
1065
- return { success: false, _id, error: err.message || String(err) };
1162
+ return {
1163
+ success: false,
1164
+ _id,
1165
+ error: err.message || String(err),
1166
+ };
1066
1167
  }
1067
1168
  });
1068
1169
  const deleteResults = await Promise.all(deletePromises);
@@ -1099,8 +1200,8 @@ export class Mongo extends Db {
1099
1200
  operation: "batch",
1100
1201
  db: dbName,
1101
1202
  collection,
1102
- data: batchData
1103
- }
1203
+ data: batchData,
1204
+ },
1104
1205
  });
1105
1206
  }
1106
1207
  if (this.emittingPublishRevEvents) {
@@ -1108,11 +1209,11 @@ export class Mongo extends Db {
1108
1209
  operation: "batch",
1109
1210
  db: dbName,
1110
1211
  collection,
1111
- data: batchData.map(item => ({
1212
+ data: batchData.map((item) => ({
1112
1213
  operation: item.operation,
1113
1214
  _id: item.data._id,
1114
1215
  _ts: item.data._ts,
1115
- }))
1216
+ })),
1116
1217
  };
1117
1218
  this.emit("publishRev", {
1118
1219
  channel: `dbrev/${dbName}/${collection}`,
@@ -1128,22 +1229,24 @@ export class Mongo extends Db {
1128
1229
  results.push(result);
1129
1230
  }
1130
1231
  }
1131
- (_c = fjLog === null || fjLog === void 0 ? void 0 : fjLog[debugMethod]) === null || _c === void 0 ? void 0 : _c.call(fjLog, 'updateCollections returns', results);
1232
+ (_c = fjLog === null || fjLog === void 0 ? void 0 : fjLog[debugMethod]) === null || _c === void 0 ? void 0 : _c.call(fjLog, "updateCollections returns", results);
1132
1233
  return results;
1133
1234
  }
1134
1235
  async upsertBatch(collection, batch) {
1135
1236
  assert(collection, "collection is required", "upsertBatch");
1136
1237
  assert(batch, "batch is required", "upsertBatch", { collection });
1137
- assert(batch instanceof Array, "batch must be an Array", "upsertBatch", { collection });
1138
- fjLog.debug('upsertBatch called', collection, batch);
1238
+ assert(batch instanceof Array, "batch must be an Array", "upsertBatch", {
1239
+ collection,
1240
+ });
1241
+ fjLog.debug("upsertBatch called", collection, batch);
1139
1242
  const dbName = this.db; // Capture db at operation start
1140
1243
  batch = this.replaceIds(batch);
1141
- await Promise.all(batch.map(item => this._processHashedKeys(item === null || item === void 0 ? void 0 : item.update)));
1244
+ await Promise.all(batch.map((item) => this._processHashedKeys(item === null || item === void 0 ? void 0 : item.update)));
1142
1245
  let ret = await this.executeTransactionally(collection, async (conn, client) => {
1143
1246
  // Only process sequences if any batch item has SEQ_NEXT or SEQ_LAST
1144
- const updatesWithSeq = batch.filter(b => this._hasSequenceFields(b.update));
1247
+ const updatesWithSeq = batch.filter((b) => this._hasSequenceFields(b.update));
1145
1248
  if (updatesWithSeq.length > 0) {
1146
- await this._processSequenceFieldForMany(client, dbName, collection, updatesWithSeq.map(b => b.update));
1249
+ await this._processSequenceFieldForMany(client, dbName, collection, updatesWithSeq.map((b) => b.update));
1147
1250
  }
1148
1251
  // Process all updates in parallel
1149
1252
  const upsertPromises = batch.map(async (part) => {
@@ -1154,7 +1257,7 @@ export class Mongo extends Db {
1154
1257
  upsert: true,
1155
1258
  returnDocument: "after",
1156
1259
  includeResultMetadata: true,
1157
- ...this._sessionOpt()
1260
+ ...this._sessionOpt(),
1158
1261
  };
1159
1262
  if (this._hasHashedKeys(update))
1160
1263
  await this._processHashedKeys(update);
@@ -1182,7 +1285,11 @@ export class Mongo extends Db {
1182
1285
  ? ret
1183
1286
  : this._buildPublishDelta(ret, inputUpdate, !!(opts === null || opts === void 0 ? void 0 : opts.returnFullObject));
1184
1287
  this._processReturnedObject(retObj);
1185
- return { operation: oper, data: retObj, rawUpdate: oper === 'update' ? inputUpdate : undefined };
1288
+ return {
1289
+ operation: oper,
1290
+ data: retObj,
1291
+ rawUpdate: oper === "update" ? inputUpdate : undefined,
1292
+ };
1186
1293
  });
1187
1294
  const results = await Promise.all(upsertPromises);
1188
1295
  // Filter out nulls and separate batchData and changes
@@ -1205,8 +1312,8 @@ export class Mongo extends Db {
1205
1312
  operation: "batch",
1206
1313
  db: dbName,
1207
1314
  collection,
1208
- data: batchData
1209
- }
1315
+ data: batchData,
1316
+ },
1210
1317
  });
1211
1318
  }
1212
1319
  if (this.emittingPublishRevEvents) {
@@ -1214,11 +1321,11 @@ export class Mongo extends Db {
1214
1321
  operation: "batch",
1215
1322
  db: dbName,
1216
1323
  collection,
1217
- data: batchData.map(item => ({
1324
+ data: batchData.map((item) => ({
1218
1325
  operation: item.operation,
1219
1326
  _id: item.data._id,
1220
1327
  _ts: item.data._ts,
1221
- }))
1328
+ })),
1222
1329
  };
1223
1330
  this.emit("publishRev", {
1224
1331
  channel: `dbrev/${dbName}/${collection}`,
@@ -1227,23 +1334,28 @@ export class Mongo extends Db {
1227
1334
  }
1228
1335
  return changes;
1229
1336
  }, false, { operation: "upsertBatch", collection, batch });
1230
- fjLog.debug('upsertBatch returns', ret);
1337
+ fjLog.debug("upsertBatch returns", ret);
1231
1338
  return ret;
1232
1339
  }
1233
1340
  async insertMany(collection, insert) {
1234
1341
  assert(collection, "collection is required", "insertMany");
1235
1342
  assert(insert, "insert is required", "insertMany", { collection });
1236
- assert(insert instanceof Array, "insert must be an Array", "insertMany", { collection });
1237
- fjLog.debug('insertMany called', collection, insert);
1343
+ assert(insert instanceof Array, "insert must be an Array", "insertMany", {
1344
+ collection,
1345
+ });
1346
+ fjLog.debug("insertMany called", collection, insert);
1238
1347
  const dbName = this.db; // Capture db at operation start
1239
1348
  insert = this.replaceIds(insert);
1240
- insert.forEach(item => this._stripDoubleUnderscoreKeys(item));
1241
- await Promise.all(insert.map(item => this._processHashedKeys(item)));
1349
+ insert.forEach((item) => this._stripDoubleUnderscoreKeys(item));
1350
+ await Promise.all(insert.map((item) => this._processHashedKeys(item)));
1242
1351
  if (this.revisions)
1243
- insert.forEach(ins => { ins._rev = 1; ins._ts = Base.timestamp(); });
1352
+ insert.forEach((ins) => {
1353
+ ins._rev = 1;
1354
+ ins._ts = Base.timestamp();
1355
+ });
1244
1356
  let ret = await this.executeTransactionally(collection, async (conn, client) => {
1245
1357
  // Only process sequences if any insert has SEQ_NEXT or SEQ_LAST
1246
- const insertsWithSeq = insert.filter(item => this._hasSequenceFields(item));
1358
+ const insertsWithSeq = insert.filter((item) => this._hasSequenceFields(item));
1247
1359
  if (insertsWithSeq.length > 0) {
1248
1360
  await this._processSequenceFieldForMany(client, dbName, collection, insert);
1249
1361
  }
@@ -1253,16 +1365,20 @@ export class Mongo extends Db {
1253
1365
  let n = Number(ns);
1254
1366
  let rec = {
1255
1367
  _id: obj.insertedIds[n],
1256
- ...insert[n]
1368
+ ...insert[n],
1257
1369
  };
1258
1370
  ret.push(rec);
1259
1371
  }
1260
- if (this.emittingPublishEvents || this.emittingPublishRevEvents || this.auditing) {
1261
- await Promise.all(ret.filter(rec => rec).map(rec => this._publishAndAudit('insert', dbName, collection, rec)));
1372
+ if (this.emittingPublishEvents ||
1373
+ this.emittingPublishRevEvents ||
1374
+ this.auditing) {
1375
+ await Promise.all(ret
1376
+ .filter((rec) => rec)
1377
+ .map((rec) => this._publishAndAudit("insert", dbName, collection, rec)));
1262
1378
  }
1263
1379
  return ret;
1264
1380
  }, false, { operation: "insertMany", collection, insert });
1265
- fjLog.debug('insertMany returns', ret);
1381
+ fjLog.debug("insertMany returns", ret);
1266
1382
  return ret;
1267
1383
  }
1268
1384
  async deleteOne(collection, query) {
@@ -1272,36 +1388,46 @@ export class Mongo extends Db {
1272
1388
  query = this.replaceIds(query);
1273
1389
  if (!this.softdelete) {
1274
1390
  const opts = this._sessionOpt();
1275
- fjLog.debug('deleteOne called', this.softdelete, collection, query);
1391
+ fjLog.debug("deleteOne called", this.softdelete, collection, query);
1276
1392
  let ret = await this.executeTransactionally(collection, async (conn) => {
1277
1393
  let obj = await conn.findOneAndDelete(query, opts);
1278
1394
  if (obj)
1279
- await this._publishAndAudit('delete', dbName, collection, obj);
1395
+ await this._publishAndAudit("delete", dbName, collection, obj);
1280
1396
  return obj;
1281
- }, false, { operation: "deleteOne", collection, query, softdelete: this.softdelete });
1282
- fjLog.debug('deleteOne returns', ret);
1397
+ }, false, {
1398
+ operation: "deleteOne",
1399
+ collection,
1400
+ query,
1401
+ softdelete: this.softdelete,
1402
+ });
1403
+ fjLog.debug("deleteOne returns", ret);
1283
1404
  return ret;
1284
1405
  }
1285
1406
  else {
1286
1407
  let opts = {
1287
1408
  upsert: false,
1288
1409
  returnDocument: "after",
1289
- ...this._sessionOpt()
1410
+ ...this._sessionOpt(),
1290
1411
  };
1291
- fjLog.debug('deleteOne called', collection, query);
1412
+ fjLog.debug("deleteOne called", collection, query);
1292
1413
  let ret = await this.executeTransactionally(collection, async (conn /*, client*/) => {
1293
1414
  let del = {
1294
1415
  $set: { _deleted: new Date() },
1295
- $inc: { _rev: 1, },
1296
- $currentDate: { _ts: { $type: 'timestamp' } }
1416
+ $inc: { _rev: 1 },
1417
+ $currentDate: { _ts: { $type: "timestamp" } },
1297
1418
  };
1298
1419
  // if (this.syncSupport) del.$set._csq = await this._getNextCollectionUpdateSeqNo(collection, client)
1299
1420
  let obj = await conn.findOneAndUpdate(query, del, opts);
1300
1421
  if (obj)
1301
- await this._publishAndAudit('delete', dbName, collection, obj);
1422
+ await this._publishAndAudit("delete", dbName, collection, obj);
1302
1423
  return obj;
1303
- }, false, { operation: "deleteOne", collection, query, softdelete: this.softdelete });
1304
- fjLog.debug('deleteOne returns', ret);
1424
+ }, false, {
1425
+ operation: "deleteOne",
1426
+ collection,
1427
+ query,
1428
+ softdelete: this.softdelete,
1429
+ });
1430
+ fjLog.debug("deleteOne returns", ret);
1305
1431
  return ret;
1306
1432
  }
1307
1433
  }
@@ -1309,56 +1435,56 @@ export class Mongo extends Db {
1309
1435
  let opts = {
1310
1436
  upsert: false,
1311
1437
  returnDocument: "after",
1312
- ...this._sessionOpt()
1438
+ ...this._sessionOpt(),
1313
1439
  };
1314
1440
  const dbName = this.db; // Capture db at operation start
1315
1441
  query = this.replaceIds(query);
1316
- fjLog.debug('blockOne called', collection, query);
1442
+ fjLog.debug("blockOne called", collection, query);
1317
1443
  let ret = await this.executeTransactionally(collection, async (conn) => {
1318
1444
  query._blocked = { $exists: 0 };
1319
1445
  let update = {
1320
- $set: { _blocked: new Date(), },
1321
- $inc: { _rev: 1, },
1322
- $currentDate: { _ts: { $type: 'timestamp' } }
1446
+ $set: { _blocked: new Date() },
1447
+ $inc: { _rev: 1 },
1448
+ $currentDate: { _ts: { $type: "timestamp" } },
1323
1449
  };
1324
1450
  // if (this.syncSupport) update.$set._csq = await this._getNextCollectionUpdateSeqNo(collection, client)
1325
1451
  let obj = await conn.findOneAndUpdate(query, update, opts);
1326
1452
  if (!obj || !(obj === null || obj === void 0 ? void 0 : obj._id))
1327
1453
  return {
1328
- ok: false
1454
+ ok: false,
1329
1455
  };
1330
- await this._publishAndAudit('update', dbName, collection, obj);
1456
+ await this._publishAndAudit("update", dbName, collection, obj);
1331
1457
  return obj;
1332
1458
  }, false, { operation: "blockOne", collection, query });
1333
- fjLog.debug('blockOne returns', ret);
1459
+ fjLog.debug("blockOne returns", ret);
1334
1460
  return ret;
1335
1461
  }
1336
1462
  async unblockOne(collection, query) {
1337
1463
  let opts = {
1338
1464
  upsert: false,
1339
1465
  returnDocument: "after",
1340
- ...this._sessionOpt()
1466
+ ...this._sessionOpt(),
1341
1467
  };
1342
1468
  const dbName = this.db; // Capture db at operation start
1343
1469
  query = this.replaceIds(query);
1344
- fjLog.debug('unblockOne called', collection, query);
1470
+ fjLog.debug("unblockOne called", collection, query);
1345
1471
  let ret = await this.executeTransactionally(collection, async (conn) => {
1346
1472
  query._blocked = { $exists: 1 };
1347
1473
  let update = {
1348
1474
  $unset: { _blocked: 1 },
1349
- $inc: { _rev: 1, },
1350
- $currentDate: { _ts: { $type: 'timestamp' } }
1475
+ $inc: { _rev: 1 },
1476
+ $currentDate: { _ts: { $type: "timestamp" } },
1351
1477
  };
1352
1478
  // if (this.syncSupport) update.$set = { _csq: await this._getNextCollectionUpdateSeqNo(collection, client) };
1353
1479
  let obj = await conn.findOneAndUpdate(query, update, opts);
1354
1480
  if (!obj || !(obj === null || obj === void 0 ? void 0 : obj._id))
1355
1481
  return {
1356
- ok: false
1482
+ ok: false,
1357
1483
  };
1358
- await this._publishAndAudit('update', dbName, collection, obj);
1484
+ await this._publishAndAudit("update", dbName, collection, obj);
1359
1485
  return obj;
1360
1486
  }, false, { operation: "unblockOne", collection, query });
1361
- fjLog.debug('unblockOne returns', ret);
1487
+ fjLog.debug("unblockOne returns", ret);
1362
1488
  return ret;
1363
1489
  }
1364
1490
  /**
@@ -1369,27 +1495,27 @@ export class Mongo extends Db {
1369
1495
  let opts = {
1370
1496
  upsert: false,
1371
1497
  returnDocument: "after",
1372
- ...this._sessionOpt()
1498
+ ...this._sessionOpt(),
1373
1499
  };
1374
1500
  const dbName = this.db;
1375
1501
  query = this.replaceIds(query);
1376
- fjLog.debug('archiveOne called', collection, query);
1502
+ fjLog.debug("archiveOne called", collection, query);
1377
1503
  let ret = await this.executeTransactionally(collection, async (conn) => {
1378
1504
  query._archived = { $exists: false };
1379
1505
  let update = {
1380
- $set: { _archived: new Date(), },
1381
- $inc: { _rev: 1, },
1382
- $currentDate: { _ts: { $type: 'timestamp' } }
1506
+ $set: { _archived: new Date() },
1507
+ $inc: { _rev: 1 },
1508
+ $currentDate: { _ts: { $type: "timestamp" } },
1383
1509
  };
1384
1510
  let obj = await conn.findOneAndUpdate(query, update, opts);
1385
1511
  if (!obj || !(obj === null || obj === void 0 ? void 0 : obj._id))
1386
1512
  return {
1387
- ok: false
1513
+ ok: false,
1388
1514
  };
1389
- await this._publishAndAudit('update', dbName, collection, obj);
1515
+ await this._publishAndAudit("update", dbName, collection, obj);
1390
1516
  return obj;
1391
1517
  }, false, { operation: "archiveOne", collection, query });
1392
- fjLog.debug('archiveOne returns', ret);
1518
+ fjLog.debug("archiveOne returns", ret);
1393
1519
  return ret;
1394
1520
  }
1395
1521
  /**
@@ -1400,27 +1526,27 @@ export class Mongo extends Db {
1400
1526
  let opts = {
1401
1527
  upsert: false,
1402
1528
  returnDocument: "after",
1403
- ...this._sessionOpt()
1529
+ ...this._sessionOpt(),
1404
1530
  };
1405
1531
  const dbName = this.db;
1406
1532
  query = this.replaceIds(query);
1407
- fjLog.debug('unarchiveOne called', collection, query);
1533
+ fjLog.debug("unarchiveOne called", collection, query);
1408
1534
  let ret = await this.executeTransactionally(collection, async (conn) => {
1409
1535
  query._archived = { $exists: true };
1410
1536
  let update = {
1411
1537
  $unset: { _archived: 1 },
1412
- $inc: { _rev: 1, },
1413
- $currentDate: { _ts: { $type: 'timestamp' } }
1538
+ $inc: { _rev: 1 },
1539
+ $currentDate: { _ts: { $type: "timestamp" } },
1414
1540
  };
1415
1541
  let obj = await conn.findOneAndUpdate(query, update, opts);
1416
1542
  if (!obj || !(obj === null || obj === void 0 ? void 0 : obj._id))
1417
1543
  return {
1418
- ok: false
1544
+ ok: false,
1419
1545
  };
1420
- await this._publishAndAudit('update', dbName, collection, obj);
1546
+ await this._publishAndAudit("update", dbName, collection, obj);
1421
1547
  return obj;
1422
1548
  }, false, { operation: "unarchiveOne", collection, query });
1423
- fjLog.debug('unarchiveOne returns', ret);
1549
+ fjLog.debug("unarchiveOne returns", ret);
1424
1550
  return ret;
1425
1551
  }
1426
1552
  /**
@@ -1429,7 +1555,9 @@ export class Mongo extends Db {
1429
1555
  async archiveOneById(collection, id) {
1430
1556
  assert(collection, "collection is required", "archiveOneById");
1431
1557
  assert(id, "id is required", "archiveOneById", { collection });
1432
- return await this.archiveOne(collection, { _id: Mongo._toId(id) });
1558
+ return await this.archiveOne(collection, {
1559
+ _id: Mongo._toId(id),
1560
+ });
1433
1561
  }
1434
1562
  /**
1435
1563
  * Archives multiple documents found by their `_id`s.
@@ -1443,29 +1571,32 @@ export class Mongo extends Db {
1443
1571
  const opts = {
1444
1572
  upsert: false,
1445
1573
  returnDocument: "after",
1446
- ...this._sessionOpt()
1574
+ ...this._sessionOpt(),
1447
1575
  };
1448
1576
  const dbName = this.db;
1449
- fjLog.debug('archiveManyByIds called', collection, ids);
1577
+ fjLog.debug("archiveManyByIds called", collection, ids);
1450
1578
  let ret = [];
1451
1579
  for (const id of ids) {
1452
1580
  let r = await this.executeTransactionally(collection, async (conn) => {
1453
- let query = { _id: Mongo._toId(id), _archived: { $exists: false } };
1581
+ let query = {
1582
+ _id: Mongo._toId(id),
1583
+ _archived: { $exists: false },
1584
+ };
1454
1585
  let update = {
1455
1586
  $set: { _archived: new Date() },
1456
1587
  $inc: { _rev: 1 },
1457
- $currentDate: { _ts: { $type: 'timestamp' } }
1588
+ $currentDate: { _ts: { $type: "timestamp" } },
1458
1589
  };
1459
1590
  let obj = await conn.findOneAndUpdate(query, update, opts);
1460
1591
  if (obj === null || obj === void 0 ? void 0 : obj._id) {
1461
- await this._publishAndAudit('update', dbName, collection, obj);
1592
+ await this._publishAndAudit("update", dbName, collection, obj);
1462
1593
  }
1463
1594
  return obj;
1464
1595
  }, false, { operation: "archiveManyByIds", collection, id });
1465
1596
  if (r === null || r === void 0 ? void 0 : r._id)
1466
1597
  ret.push(r);
1467
1598
  }
1468
- fjLog.debug('archiveManyByIds returns', ret);
1599
+ fjLog.debug("archiveManyByIds returns", ret);
1469
1600
  return ret;
1470
1601
  }
1471
1602
  /**
@@ -1474,7 +1605,9 @@ export class Mongo extends Db {
1474
1605
  async unarchiveOneById(collection, id) {
1475
1606
  assert(collection, "collection is required", "unarchiveOneById");
1476
1607
  assert(id, "id is required", "unarchiveOneById", { collection });
1477
- return await this.unarchiveOne(collection, { _id: Mongo._toId(id) });
1608
+ return await this.unarchiveOne(collection, {
1609
+ _id: Mongo._toId(id),
1610
+ });
1478
1611
  }
1479
1612
  /**
1480
1613
  * Unarchives multiple documents found by their `_id`s.
@@ -1488,52 +1621,57 @@ export class Mongo extends Db {
1488
1621
  const opts = {
1489
1622
  upsert: false,
1490
1623
  returnDocument: "after",
1491
- ...this._sessionOpt()
1624
+ ...this._sessionOpt(),
1492
1625
  };
1493
1626
  const dbName = this.db;
1494
- fjLog.debug('unarchiveManyByIds called', collection, ids);
1627
+ fjLog.debug("unarchiveManyByIds called", collection, ids);
1495
1628
  let ret = [];
1496
1629
  for (const id of ids) {
1497
1630
  let r = await this.executeTransactionally(collection, async (conn) => {
1498
- let query = { _id: Mongo._toId(id), _archived: { $exists: true } };
1631
+ let query = {
1632
+ _id: Mongo._toId(id),
1633
+ _archived: { $exists: true },
1634
+ };
1499
1635
  let update = {
1500
1636
  $unset: { _archived: 1 },
1501
1637
  $inc: { _rev: 1 },
1502
- $currentDate: { _ts: { $type: 'timestamp' } }
1638
+ $currentDate: { _ts: { $type: "timestamp" } },
1503
1639
  };
1504
1640
  let obj = await conn.findOneAndUpdate(query, update, opts);
1505
1641
  if (obj === null || obj === void 0 ? void 0 : obj._id) {
1506
- await this._publishAndAudit('update', dbName, collection, obj);
1642
+ await this._publishAndAudit("update", dbName, collection, obj);
1507
1643
  }
1508
1644
  return obj;
1509
1645
  }, false, { operation: "unarchiveManyByIds", collection, id });
1510
1646
  if (r === null || r === void 0 ? void 0 : r._id)
1511
1647
  ret.push(r);
1512
1648
  }
1513
- fjLog.debug('unarchiveManyByIds returns', ret);
1649
+ fjLog.debug("unarchiveManyByIds returns", ret);
1514
1650
  return ret;
1515
1651
  }
1516
1652
  async hardDeleteOne(collection, query) {
1517
1653
  assert(collection, "collection is required", "hardDeleteOne");
1518
1654
  assert(query, "query is required", "hardDeleteOne", { collection });
1519
1655
  const dbName = this.db; // Capture db at operation start
1520
- if (typeof query === "string" || typeof query === "number" || query instanceof ObjectId) {
1656
+ if (typeof query === "string" ||
1657
+ typeof query === "number" ||
1658
+ query instanceof ObjectId) {
1521
1659
  query = { _id: query };
1522
1660
  }
1523
1661
  query = this.replaceIds(query);
1524
1662
  let opts = {
1525
1663
  returnDocument: "after",
1526
- ...this._sessionOpt()
1664
+ ...this._sessionOpt(),
1527
1665
  };
1528
- fjLog.debug('hardDeleteOne called', collection, query);
1666
+ fjLog.debug("hardDeleteOne called", collection, query);
1529
1667
  let ret = await this.executeTransactionally(collection, async (conn) => {
1530
1668
  let obj = await conn.findOneAndDelete(query, opts);
1531
1669
  if (obj) {
1532
- await this._publishAndAudit('delete', dbName, collection, obj);
1670
+ await this._publishAndAudit("delete", dbName, collection, obj);
1533
1671
  }
1534
1672
  return obj;
1535
1673
  }, false, { operation: "hardDeleteOne", collection, query });
1536
- fjLog.debug('hardDeleteOne returns', ret);
1674
+ fjLog.debug("hardDeleteOne returns", ret);
1537
1675
  return ret;
1538
1676
  }
1539
1677
  async delete(collection, query) {
@@ -1544,42 +1682,42 @@ export class Mongo extends Db {
1544
1682
  query = this.replaceIds(query);
1545
1683
  if (!this.softdelete) {
1546
1684
  const opts = this._sessionOpt();
1547
- fjLog.debug('delete called', collection, query);
1685
+ fjLog.debug("delete called", collection, query);
1548
1686
  let ret = await this.executeTransactionally(collection, async (conn) => {
1549
1687
  let obj = await conn.deleteMany(query, opts);
1550
1688
  let resObj = {
1551
1689
  n: obj.deletedCount,
1552
- ok: !!obj.acknowledged
1690
+ ok: !!obj.acknowledged,
1553
1691
  };
1554
- await this._publishAndAudit('deleteMany', dbName, collection, resObj);
1692
+ await this._publishAndAudit("deleteMany", dbName, collection, resObj);
1555
1693
  return resObj;
1556
1694
  }, false, { operation: "delete", collection, query, softdelete: this.softdelete });
1557
- fjLog.debug('delete returns', ret);
1695
+ fjLog.debug("delete returns", ret);
1558
1696
  return ret;
1559
1697
  }
1560
1698
  else {
1561
1699
  let opts = {
1562
1700
  upsert: false,
1563
1701
  returnDocument: "after",
1564
- ...this._sessionOpt()
1702
+ ...this._sessionOpt(),
1565
1703
  };
1566
1704
  let date = new Date();
1567
- fjLog.debug('delete called', collection, query);
1705
+ fjLog.debug("delete called", collection, query);
1568
1706
  let ret = await this.executeTransactionally(collection, async (conn) => {
1569
1707
  let upd = {
1570
1708
  $set: { _deleted: date },
1571
1709
  $inc: { _rev: 1 },
1572
- $currentDate: { _ts: { $type: 'timestamp' } }
1710
+ $currentDate: { _ts: { $type: "timestamp" } },
1573
1711
  };
1574
1712
  let obj = await conn.updateMany(query, upd, opts);
1575
1713
  let resObj = {
1576
1714
  n: obj.modifiedCount,
1577
- ok: !!obj.acknowledged
1715
+ ok: !!obj.acknowledged,
1578
1716
  };
1579
- await this._publishAndAudit('deleteMany', dbName, collection, resObj);
1717
+ await this._publishAndAudit("deleteMany", dbName, collection, resObj);
1580
1718
  return resObj;
1581
1719
  }, false, { operation: "delete", collection, query, softdelete: this.softdelete });
1582
- fjLog.debug('delete returns', ret);
1720
+ fjLog.debug("delete returns", ret);
1583
1721
  return ret;
1584
1722
  }
1585
1723
  }
@@ -1590,22 +1728,27 @@ export class Mongo extends Db {
1590
1728
  const dbName = this.db; // Capture db at operation start
1591
1729
  query = this.replaceIds(query);
1592
1730
  const opts = this._sessionOpt();
1593
- fjLog.debug('hardDelete called', collection, query);
1731
+ fjLog.debug("hardDelete called", collection, query);
1594
1732
  let ret = await this.executeTransactionally(collection, async (conn) => {
1595
1733
  let obj = await conn.deleteMany(query, opts);
1596
1734
  let resObj = {
1597
1735
  n: obj.deletedCount,
1598
- ok: !!obj.acknowledged
1736
+ ok: !!obj.acknowledged,
1599
1737
  };
1600
- await this._publishAndAudit('deleteMany', dbName, collection, resObj);
1738
+ await this._publishAndAudit("deleteMany", dbName, collection, resObj);
1601
1739
  return resObj;
1602
- }, false, { operation: "hardDelete", collection, query, softdelete: this.softdelete });
1603
- fjLog.debug('hardDelete returns', ret);
1740
+ }, false, {
1741
+ operation: "hardDelete",
1742
+ collection,
1743
+ query,
1744
+ softdelete: this.softdelete,
1745
+ });
1746
+ fjLog.debug("hardDelete returns", ret);
1604
1747
  return ret;
1605
1748
  }
1606
1749
  async testHash(collection, query, field, unhashedValue) {
1607
1750
  let _field;
1608
- fjLog.debug('testHash called', collection, query, field, unhashedValue);
1751
+ fjLog.debug("testHash called", collection, query, field, unhashedValue);
1609
1752
  if (typeof field === "object") {
1610
1753
  if (Object.keys(field).length === 1)
1611
1754
  [_field, unhashedValue] = Object.entries(field)[0];
@@ -1618,13 +1761,16 @@ export class Mongo extends Db {
1618
1761
  _field = HASHED_PREFIX + _field;
1619
1762
  const dbName = this.db; // Capture db at operation start
1620
1763
  let conn = await this.connect();
1621
- let obj = await conn.db(dbName).collection(collection).findOne(query, { projection: { [_field]: 1 }, ...this._sessionOpt() });
1764
+ let obj = await conn
1765
+ .db(dbName)
1766
+ .collection(collection)
1767
+ .findOne(query, { projection: { [_field]: 1 }, ...this._sessionOpt() });
1622
1768
  if (!obj || !obj[_field]) {
1623
- fjLog.debug('testHash returns false', obj);
1769
+ fjLog.debug("testHash returns false", obj);
1624
1770
  return false;
1625
1771
  }
1626
1772
  let res = await bcrypt.compare(unhashedValue, obj[_field].hash);
1627
- fjLog.debug('testHash returns', res);
1773
+ fjLog.debug("testHash returns", res);
1628
1774
  return res;
1629
1775
  }
1630
1776
  async aggregate(collection, pipeline, opts = {
@@ -1632,7 +1778,7 @@ export class Mongo extends Db {
1632
1778
  }) {
1633
1779
  assert(collection, "collection is required", "aggregate");
1634
1780
  assert(pipeline instanceof Array, "pipeline must be an Array", "aggregate", { collection });
1635
- fjLog.debug('aggregate called', collection, pipeline);
1781
+ fjLog.debug("aggregate called", collection, pipeline);
1636
1782
  pipeline = this.replaceIds(pipeline);
1637
1783
  if (this.session)
1638
1784
  opts.session = this.session;
@@ -1640,7 +1786,7 @@ export class Mongo extends Db {
1640
1786
  let res = await conn.aggregate(pipeline, opts).toArray();
1641
1787
  return res;
1642
1788
  }, false, { operation: "aggregate", collection, pipeline, opts });
1643
- fjLog.debug('aggregare returns', ret);
1789
+ fjLog.debug("aggregare returns", ret);
1644
1790
  return ret;
1645
1791
  }
1646
1792
  async isUnique(collection, field, value, id) {
@@ -1648,7 +1794,7 @@ export class Mongo extends Db {
1648
1794
  assert(field, "field is required", "isUnique", { collection });
1649
1795
  if (!value)
1650
1796
  return false;
1651
- fjLog.debug('isUnique called', collection, field, value, id);
1797
+ fjLog.debug("isUnique called", collection, field, value, id);
1652
1798
  let _id = id === null || id === void 0 ? void 0 : id.toString();
1653
1799
  let query = typeof value === "object" ? value : { [field]: value };
1654
1800
  query = this.replaceIds(query);
@@ -1666,12 +1812,12 @@ export class Mongo extends Db {
1666
1812
  return false;
1667
1813
  }
1668
1814
  }
1669
- fjLog.debug('isUnique returns', ret);
1815
+ fjLog.debug("isUnique returns", ret);
1670
1816
  return ret;
1671
1817
  }
1672
1818
  async dropCollection(collection) {
1673
1819
  assert(collection, "collection is required", "dropCollection");
1674
- fjLog.debug('dropCollection called', this.auditCollections);
1820
+ fjLog.debug("dropCollection called", this.auditCollections);
1675
1821
  const dbName = this.db; // Capture db at operation start
1676
1822
  let client = await this.connect();
1677
1823
  let existing = await client.db(dbName).collections();
@@ -1679,14 +1825,15 @@ export class Mongo extends Db {
1679
1825
  if (existingNames.has(collection)) {
1680
1826
  await client.db(dbName).dropCollection(collection);
1681
1827
  }
1682
- fjLog.debug('dropCollection returns');
1828
+ fjLog.debug("dropCollection returns");
1683
1829
  }
1684
1830
  async resetCollectionSync(collection) {
1685
1831
  assert(collection, "collection is required", "resetCollectionSync");
1686
- fjLog.debug('resetCollectionSync called for', collection);
1832
+ fjLog.debug("resetCollectionSync called for", collection);
1687
1833
  const dbName = this.db; // Capture db at operation start
1688
1834
  let client = await this.connect();
1689
- await client.db(dbName)
1835
+ await client
1836
+ .db(dbName)
1690
1837
  .collection(SEQUENCES_COLLECTION)
1691
1838
  .findOneAndDelete({ collection });
1692
1839
  fjLog.debug(`resetCollectionSync for ${collection} returns`);
@@ -1694,7 +1841,7 @@ export class Mongo extends Db {
1694
1841
  async dropCollections(collections) {
1695
1842
  assert(collections, "collections is required", "dropCollections");
1696
1843
  assert(collections instanceof Array, "collections must be an Array", "dropCollections");
1697
- fjLog.debug('dropCollections called', this.auditCollections);
1844
+ fjLog.debug("dropCollections called", this.auditCollections);
1698
1845
  const dbName = this.db; // Capture db at operation start
1699
1846
  let client = await this.connect();
1700
1847
  let existing = await client.db(dbName).collections();
@@ -1704,12 +1851,12 @@ export class Mongo extends Db {
1704
1851
  await client.db(dbName).dropCollection(collection);
1705
1852
  }
1706
1853
  }
1707
- fjLog.debug('dropCollections returns');
1854
+ fjLog.debug("dropCollections returns");
1708
1855
  }
1709
1856
  async createCollections(collections) {
1710
1857
  assert(collections, "collections is required", "createCollections");
1711
1858
  assert(collections instanceof Array, "collections must be an Array", "createCollections");
1712
- fjLog.debug('createCollections called', this.auditCollections);
1859
+ fjLog.debug("createCollections called", this.auditCollections);
1713
1860
  const dbName = this.db; // Capture db at operation start
1714
1861
  let client = await this.connect();
1715
1862
  let existing = await this.getCollections();
@@ -1719,25 +1866,25 @@ export class Mongo extends Db {
1719
1866
  await client.db(dbName).createCollection(collection);
1720
1867
  }
1721
1868
  }
1722
- fjLog.debug('createCollections returns');
1869
+ fjLog.debug("createCollections returns");
1723
1870
  }
1724
1871
  async createCollection(collection) {
1725
1872
  assert(collection, "collection is required", "createCollection");
1726
- fjLog.debug('createCollection called', collection);
1873
+ fjLog.debug("createCollection called", collection);
1727
1874
  const dbName = this.db; // Capture db at operation start
1728
1875
  let client = await this.connect();
1729
1876
  let existing = await this.getCollections();
1730
1877
  if (!existing.includes(collection)) {
1731
1878
  await client.db(dbName).createCollection(collection);
1732
1879
  }
1733
- fjLog.debug('createCollection returns');
1880
+ fjLog.debug("createCollection returns");
1734
1881
  }
1735
1882
  async dbLogPurge(collection, _id) {
1736
1883
  assert(collection, "collection is required", "dbLogPurge");
1737
- fjLog.debug('dblogPurge called', collection, _id);
1884
+ fjLog.debug("dblogPurge called", collection, _id);
1738
1885
  const dbName = this.db; // Capture db at operation start
1739
1886
  let ret = await this.executeTransactionally(collection, async () => {
1740
- let cond = { db: dbName, collection, };
1887
+ let cond = { db: dbName, collection };
1741
1888
  if (_id !== undefined)
1742
1889
  cond._id = Mongo._toId(_id);
1743
1890
  let client = await this.connect();
@@ -1747,15 +1894,15 @@ export class Mongo extends Db {
1747
1894
  .deleteMany(cond, this._sessionOpt());
1748
1895
  return {
1749
1896
  ok: !!ret.acknowledged,
1750
- n: ret.deletedCount
1897
+ n: ret.deletedCount,
1751
1898
  };
1752
1899
  }, false, { operation: "dbLogPurge", collection, _id });
1753
- fjLog.debug('dblogPurge returns', ret);
1900
+ fjLog.debug("dblogPurge returns", ret);
1754
1901
  return ret;
1755
1902
  }
1756
1903
  async dbLogGet(collection, _id) {
1757
1904
  assert(collection, "collection is required", "dbLogGet");
1758
- fjLog.debug('dblogGet called', collection, _id);
1905
+ fjLog.debug("dblogGet called", collection, _id);
1759
1906
  const dbName = this.db; // Capture db at operation start
1760
1907
  let ret = await this.executeTransactionally(collection, async () => {
1761
1908
  let cond = { db: dbName, collection };
@@ -1770,7 +1917,7 @@ export class Mongo extends Db {
1770
1917
  .toArray();
1771
1918
  return ret;
1772
1919
  }, false, { operation: "dbLogGet", collection, _id });
1773
- fjLog.debug('dblogGet returns', ret);
1920
+ fjLog.debug("dblogGet returns", ret);
1774
1921
  return ret;
1775
1922
  }
1776
1923
  // HELPER FUNCTIONS
@@ -1805,13 +1952,13 @@ export class Mongo extends Db {
1805
1952
  if (typeof data === "string")
1806
1953
  return data;
1807
1954
  if (data instanceof Array) {
1808
- return data.map(d => this.replaceIds(d));
1955
+ return data.map((d) => this.replaceIds(d));
1809
1956
  }
1810
- if (typeof data == 'object' && (data === null || data === void 0 ? void 0 : data.t) && (data === null || data === void 0 ? void 0 : data.i) !== undefined)
1957
+ if (typeof data == "object" && (data === null || data === void 0 ? void 0 : data.t) && (data === null || data === void 0 ? void 0 : data.i) !== undefined)
1811
1958
  return Base.timestamp(data);
1812
- if (typeof data == 'object' && (data === null || data === void 0 ? void 0 : data.high) && (data === null || data === void 0 ? void 0 : data.low) !== undefined)
1959
+ if (typeof data == "object" && (data === null || data === void 0 ? void 0 : data.high) && (data === null || data === void 0 ? void 0 : data.low) !== undefined)
1813
1960
  return Base.timestamp(data);
1814
- if (typeof data == 'object') {
1961
+ if (typeof data == "object") {
1815
1962
  for (let key in data) {
1816
1963
  data[key] = this.replaceIds(data[key]);
1817
1964
  }
@@ -1820,7 +1967,7 @@ export class Mongo extends Db {
1820
1967
  throw new Error(`ObjectId test failed for ${data}`);
1821
1968
  }
1822
1969
  catch (err) {
1823
- console.error('error in replaceIds', err, data);
1970
+ console.error("error in replaceIds", err, data);
1824
1971
  throw err;
1825
1972
  }
1826
1973
  }
@@ -1868,14 +2015,14 @@ export class Mongo extends Db {
1868
2015
  this._sequencesIndexEnsured = false;
1869
2016
  }
1870
2017
  async inTransaction() {
1871
- if (!await this.isOnReplicaSet())
2018
+ if (!(await this.isOnReplicaSet()))
1872
2019
  return false;
1873
2020
  if (!this.session)
1874
2021
  return false;
1875
2022
  return this.session.inTransaction();
1876
2023
  }
1877
2024
  async withTransaction(funct) {
1878
- if (!await this.isOnReplicaSet())
2025
+ if (!(await this.isOnReplicaSet()))
1879
2026
  return await funct(await this.connect(), null);
1880
2027
  const hadSession = !!this.session;
1881
2028
  try {
@@ -1899,14 +2046,16 @@ export class Mongo extends Db {
1899
2046
  await this.session.endSession();
1900
2047
  fjLog.info("session ended after error");
1901
2048
  }
1902
- catch { /* ignore cleanup errors */ }
2049
+ catch {
2050
+ /* ignore cleanup errors */
2051
+ }
1903
2052
  this.session = undefined;
1904
2053
  }
1905
2054
  throw err;
1906
2055
  }
1907
2056
  }
1908
2057
  async startTransaction() {
1909
- if (!await this.isOnReplicaSet())
2058
+ if (!(await this.isOnReplicaSet()))
1910
2059
  return;
1911
2060
  let client = await this.connect();
1912
2061
  try {
@@ -1914,13 +2063,13 @@ export class Mongo extends Db {
1914
2063
  this.session = client.startSession(TRANSACTION_OPTIONS);
1915
2064
  fjLog.info("session started");
1916
2065
  }
1917
- if (!await this.inTransaction()) {
2066
+ if (!(await this.inTransaction())) {
1918
2067
  await this.session.startTransaction();
1919
2068
  fjLog.info("transaction started");
1920
2069
  }
1921
2070
  }
1922
2071
  catch (err) {
1923
- fjLog.error('startTransaction error', err);
2072
+ fjLog.error("startTransaction error", err);
1924
2073
  try {
1925
2074
  if (this.session) {
1926
2075
  await this.session.endSession();
@@ -1935,10 +2084,10 @@ export class Mongo extends Db {
1935
2084
  }
1936
2085
  }
1937
2086
  async commitTransaction() {
1938
- if (!await this.isOnReplicaSet())
2087
+ if (!(await this.isOnReplicaSet()))
1939
2088
  return;
1940
2089
  try {
1941
- if (!await this.inTransaction())
2090
+ if (!(await this.inTransaction()))
1942
2091
  return;
1943
2092
  let session = this.session;
1944
2093
  await session.commitTransaction();
@@ -1952,10 +2101,10 @@ export class Mongo extends Db {
1952
2101
  }
1953
2102
  }
1954
2103
  async abortTransaction() {
1955
- if (!await this.isOnReplicaSet())
2104
+ if (!(await this.isOnReplicaSet()))
1956
2105
  return;
1957
2106
  try {
1958
- if (!await this.inTransaction())
2107
+ if (!(await this.inTransaction()))
1959
2108
  return;
1960
2109
  let session = this.session;
1961
2110
  await session.abortTransaction();
@@ -2009,22 +2158,24 @@ export class Mongo extends Db {
2009
2158
  // E11000 duplicate key — log concise one-liner (avoid dumping full batch)
2010
2159
  if (x.match(/E11000/i)) {
2011
2160
  const dupMatch = x.match(/dup key:\s*(\{[^}]+\})/);
2012
- const count = Array.isArray(debugObject.insert) ? debugObject.insert.length : 1;
2161
+ const count = Array.isArray(debugObject.insert)
2162
+ ? debugObject.insert.length
2163
+ : 1;
2013
2164
  const rollback = this.session ? "ROLLBACK - " : "";
2014
2165
  fjLog.error(`${rollback}Mongo ${debugObject.operation} E11000 on ${dbName}.${collection} (batch=${count}${dupMatch ? `, ${dupMatch[1].trim()}` : ""}) — ignoring`);
2015
2166
  if (debugObject.operation === "insert")
2016
2167
  return debugObject.insert;
2017
2168
  throw err;
2018
2169
  }
2019
- fjLog.error(`Mongo command has failed for ${dbName}.${collection} - ${(this.session ? "ROLLBACK - " : "")} ${err.message || err}`);
2170
+ fjLog.error(`Mongo command has failed for ${dbName}.${collection} - ${this.session ? "ROLLBACK - " : ""} ${err.message || err}`);
2020
2171
  fjLog.error(debugObject);
2021
2172
  fjLog.debug(err);
2022
- let isRepeatable = x.match(/Topology is closed, please connect/i)
2023
- || x.match(/connection timed out/i)
2024
- || x.match(/not master/i)
2025
- || x.match(/Topology closed/i)
2026
- || x.match(/Topology is closed/i)
2027
- || x.match(/Connection pool closed/i);
2173
+ let isRepeatable = x.match(/Topology is closed, please connect/i) ||
2174
+ x.match(/connection timed out/i) ||
2175
+ x.match(/not master/i) ||
2176
+ x.match(/Topology closed/i) ||
2177
+ x.match(/Topology is closed/i) ||
2178
+ x.match(/Connection pool closed/i);
2028
2179
  if (isRepeatable) {
2029
2180
  try {
2030
2181
  fjLog.error("Trying to reopen connection and repeat as");
@@ -2049,11 +2200,11 @@ export class Mongo extends Db {
2049
2200
  }
2050
2201
  async _findLastSequenceForKey(connection, key) {
2051
2202
  var _a;
2052
- let maxfld = await (connection
2203
+ let maxfld = await connection
2053
2204
  .find({}, this._sessionOpt())
2054
2205
  .sort({ [key]: -1 })
2055
2206
  .limit(1)
2056
- .toArray());
2207
+ .toArray();
2057
2208
  if (maxfld.length === 0)
2058
2209
  return undefined;
2059
2210
  return parseInt((_a = maxfld === null || maxfld === void 0 ? void 0 : maxfld[0]) === null || _a === void 0 ? void 0 : _a[key]) || 0;
@@ -2095,19 +2246,19 @@ export class Mongo extends Db {
2095
2246
  if (!existingSeq) {
2096
2247
  // First time for this collection/field - ensure index exists
2097
2248
  await this._ensureSequencesIndex(dbConnection);
2098
- const seedValue = (existingMax !== undefined && existingMax >= 1) ? existingMax : 0;
2249
+ const seedValue = existingMax !== undefined && existingMax >= 1 ? existingMax : 0;
2099
2250
  // Use $max to handle concurrent seeding - only sets if greater than current value
2100
2251
  // This ensures the highest seed value wins in case of concurrent operations
2101
2252
  await dbConnection
2102
2253
  .collection(FIELD_SEQUENCES_COLLECTION)
2103
2254
  .findOneAndUpdate({ collection, field }, {
2104
2255
  $max: { lastSeqNum: seedValue },
2105
- $setOnInsert: { collection, field }
2106
- }, { upsert: true, returnDocument: 'after', ...this._sessionOpt() });
2256
+ $setOnInsert: { collection, field },
2257
+ }, { upsert: true, returnDocument: "after", ...this._sessionOpt() });
2107
2258
  // Now increment atomically to get next value
2108
2259
  const updated = await dbConnection
2109
2260
  .collection(FIELD_SEQUENCES_COLLECTION)
2110
- .findOneAndUpdate({ collection, field }, { $inc: { lastSeqNum: 1 } }, { returnDocument: 'after', ...this._sessionOpt() });
2261
+ .findOneAndUpdate({ collection, field }, { $inc: { lastSeqNum: 1 } }, { returnDocument: "after", ...this._sessionOpt() });
2111
2262
  return updated.lastSeqNum;
2112
2263
  }
2113
2264
  // Sequence exists - check if collection was cleared (reset scenario)
@@ -2120,7 +2271,7 @@ export class Mongo extends Db {
2120
2271
  // Increment and return
2121
2272
  const result = await dbConnection
2122
2273
  .collection(FIELD_SEQUENCES_COLLECTION)
2123
- .findOneAndUpdate({ collection, field }, { $inc: { lastSeqNum: 1 } }, { returnDocument: 'after', ...this._sessionOpt() });
2274
+ .findOneAndUpdate({ collection, field }, { $inc: { lastSeqNum: 1 } }, { returnDocument: "after", ...this._sessionOpt() });
2124
2275
  return result.lastSeqNum;
2125
2276
  }
2126
2277
  /**
@@ -2169,14 +2320,14 @@ export class Mongo extends Db {
2169
2320
  if (!existingSeq) {
2170
2321
  // First time for this collection/field - ensure index exists
2171
2322
  await this._ensureSequencesIndex(dbConnection);
2172
- const seedValue = (existingMax !== undefined && existingMax >= 1) ? existingMax : 0;
2323
+ const seedValue = existingMax !== undefined && existingMax >= 1 ? existingMax : 0;
2173
2324
  // Use $max to handle concurrent seeding
2174
2325
  await dbConnection
2175
2326
  .collection(FIELD_SEQUENCES_COLLECTION)
2176
2327
  .findOneAndUpdate({ collection, field }, {
2177
2328
  $max: { lastSeqNum: seedValue },
2178
- $setOnInsert: { collection, field }
2179
- }, { upsert: true, returnDocument: 'after', ...this._sessionOpt() });
2329
+ $setOnInsert: { collection, field },
2330
+ }, { upsert: true, returnDocument: "after", ...this._sessionOpt() });
2180
2331
  }
2181
2332
  else if (existingMax === undefined && existingSeq.lastSeqNum > 0) {
2182
2333
  // Collection is empty but we have a non-zero sequence - reset to 0
@@ -2187,7 +2338,7 @@ export class Mongo extends Db {
2187
2338
  // Now atomically reserve the range
2188
2339
  const result = await dbConnection
2189
2340
  .collection(FIELD_SEQUENCES_COLLECTION)
2190
- .findOneAndUpdate({ collection, field }, { $inc: { lastSeqNum: count } }, { returnDocument: 'after', ...this._sessionOpt() });
2341
+ .findOneAndUpdate({ collection, field }, { $inc: { lastSeqNum: count } }, { returnDocument: "after", ...this._sessionOpt() });
2191
2342
  const end = result.lastSeqNum;
2192
2343
  return { start: end - count + 1, end };
2193
2344
  }
@@ -2212,17 +2363,20 @@ export class Mongo extends Db {
2212
2363
  return;
2213
2364
  if (!this._hasSequenceFields(object) && !this.syncSupport)
2214
2365
  return;
2215
- const seqKeys = Object.keys(object).filter(key => object[key] === 'SEQ_NEXT' || object[key] === 'SEQ_LAST');
2366
+ const seqKeys = Object.keys(object).filter((key) => object[key] === "SEQ_NEXT" ||
2367
+ object[key] === "SEQ_LAST");
2216
2368
  return { seqKeys };
2217
2369
  }
2218
2370
  async _processSequenceField(client, dbName, collection, insert, seqKeys) {
2219
- assert(this.client, "client is required", "_processSequenceField", { collection });
2371
+ assert(this.client, "client is required", "_processSequenceField", {
2372
+ collection,
2373
+ });
2220
2374
  // if (this.syncSupport) {
2221
2375
  // insert._csq = (await this._getNextCollectionUpdateSeqNo(collection, client));
2222
2376
  // }
2223
2377
  const db = client.db(dbName);
2224
2378
  for (const seqKey of (seqKeys === null || seqKeys === void 0 ? void 0 : seqKeys.seqKeys) || []) {
2225
- if (insert[seqKey] === 'SEQ_LAST') {
2379
+ if (insert[seqKey] === "SEQ_LAST") {
2226
2380
  insert[seqKey] = await this._getLastSequenceValue(db, collection, seqKey);
2227
2381
  }
2228
2382
  else {
@@ -2232,7 +2386,9 @@ export class Mongo extends Db {
2232
2386
  return insert;
2233
2387
  }
2234
2388
  async _processSequenceFieldForMany(connection, dbName, collection, inserts) {
2235
- assert(this.client, "client is required", "_processSequenceFieldForMany", { collection });
2389
+ assert(this.client, "client is required", "_processSequenceFieldForMany", {
2390
+ collection,
2391
+ });
2236
2392
  assert(connection, "connection is required", "_processSequenceFieldForMany", { collection });
2237
2393
  if (!(inserts === null || inserts === void 0 ? void 0 : inserts.length))
2238
2394
  return;
@@ -2240,7 +2396,7 @@ export class Mongo extends Db {
2240
2396
  let seqKeysSet = new Set();
2241
2397
  for (let insert of inserts) {
2242
2398
  let spec = this._findSequenceKeys(insert);
2243
- spec === null || spec === void 0 ? void 0 : spec.seqKeys.forEach(key => seqKeysSet.add(key));
2399
+ spec === null || spec === void 0 ? void 0 : spec.seqKeys.forEach((key) => seqKeysSet.add(key));
2244
2400
  }
2245
2401
  let seqKeys = Array.from(seqKeysSet);
2246
2402
  if (!seqKeys.length)
@@ -2251,7 +2407,7 @@ export class Mongo extends Db {
2251
2407
  // Count SEQ_NEXT occurrences to reserve the range
2252
2408
  let seqNextCount = 0;
2253
2409
  for (const insert of inserts) {
2254
- if (insert[seqKey] === 'SEQ_NEXT')
2410
+ if (insert[seqKey] === "SEQ_NEXT")
2255
2411
  seqNextCount++;
2256
2412
  }
2257
2413
  // Get current value and reserve range for SEQ_NEXT if needed
@@ -2268,10 +2424,10 @@ export class Mongo extends Db {
2268
2424
  // Process inserts in order - SEQ_LAST gets current, SEQ_NEXT increments and gets new value
2269
2425
  for (const insert of inserts) {
2270
2426
  const val = insert[seqKey];
2271
- if (val === 'SEQ_LAST') {
2427
+ if (val === "SEQ_LAST") {
2272
2428
  insert[seqKey] = currentValue;
2273
2429
  }
2274
- else if (val === 'SEQ_NEXT') {
2430
+ else if (val === "SEQ_NEXT") {
2275
2431
  currentValue++;
2276
2432
  insert[seqKey] = currentValue;
2277
2433
  }
@@ -2282,9 +2438,13 @@ export class Mongo extends Db {
2282
2438
  _getFieldsRecursively(obj, into = []) {
2283
2439
  for (let key in obj) {
2284
2440
  const isDollarKey = startsWithDollar(key);
2285
- if (isDollarKey && typeof obj[key] === "object" && !Array.isArray(obj[key]))
2441
+ if (isDollarKey &&
2442
+ typeof obj[key] === "object" &&
2443
+ !Array.isArray(obj[key]))
2286
2444
  this._getFieldsRecursively(obj[key], into);
2287
- else if (!isDollarKey && typeof obj[key] === "object" && !Array.isArray(obj[key]))
2445
+ else if (!isDollarKey &&
2446
+ typeof obj[key] === "object" &&
2447
+ !Array.isArray(obj[key]))
2288
2448
  into.push(key);
2289
2449
  else if (!isDollarKey)
2290
2450
  into.push(key);
@@ -2314,7 +2474,7 @@ export class Mongo extends Db {
2314
2474
  const out = {};
2315
2475
  const keys = this._getFieldsRecursively(inputUpdate);
2316
2476
  for (const k of keys) {
2317
- const bracketIdx = k.indexOf('[');
2477
+ const bracketIdx = k.indexOf("[");
2318
2478
  if (bracketIdx < 0) {
2319
2479
  out[k] = wholerecord[k];
2320
2480
  continue;
@@ -2322,7 +2482,7 @@ export class Mongo extends Db {
2322
2482
  // Bracket path: publish the top-level parent field as a whole,
2323
2483
  // sliced from the post-update document. The "top-level parent" is
2324
2484
  // everything before the FIRST `.` or `[` separator.
2325
- const dotIdx = k.indexOf('.');
2485
+ const dotIdx = k.indexOf(".");
2326
2486
  const cutAt = dotIdx >= 0 && dotIdx < bracketIdx ? dotIdx : bracketIdx;
2327
2487
  const topField = k.substring(0, cutAt);
2328
2488
  if (topField && !(topField in out))
@@ -2351,7 +2511,7 @@ export class Mongo extends Db {
2351
2511
  if (!this.auditing)
2352
2512
  return false;
2353
2513
  const fullName = ((db ? db + "." : "") + (col || "")).toLowerCase();
2354
- return this.auditedCollectionsLower.some(m => fullName.includes(m));
2514
+ return this.auditedCollectionsLower.some((m) => fullName.includes(m));
2355
2515
  }
2356
2516
  async _publishAndAudit(operation, db, collection, dataToPublish, noEmit, rawUpdate) {
2357
2517
  if (!dataToPublish._id && !["deleteMany", "updateMany"].includes(operation))
@@ -2383,7 +2543,7 @@ export class Mongo extends Db {
2383
2543
  }
2384
2544
  }
2385
2545
  if (this._shouldAuditCollection(db, collection)) {
2386
- if (['insert', 'update', 'delete'].includes(operation))
2546
+ if (["insert", "update", "delete"].includes(operation))
2387
2547
  await this._writeAuditRecord(db, collection, operation, data);
2388
2548
  }
2389
2549
  return toPublishAll;
@@ -2411,11 +2571,11 @@ export class Mongo extends Db {
2411
2571
  const user = (_a = data === null || data === void 0 ? void 0 : data._auth) === null || _a === void 0 ? void 0 : _a.username;
2412
2572
  let toPublish;
2413
2573
  switch (operation) {
2414
- case 'insert':
2574
+ case "insert":
2415
2575
  toPublish = {
2416
2576
  channel,
2417
2577
  payload: {
2418
- operation: 'insert',
2578
+ operation: "insert",
2419
2579
  db,
2420
2580
  collection,
2421
2581
  _id: data._id,
@@ -2425,11 +2585,11 @@ export class Mongo extends Db {
2425
2585
  },
2426
2586
  };
2427
2587
  break;
2428
- case 'update':
2588
+ case "update":
2429
2589
  toPublish = {
2430
2590
  channel,
2431
2591
  payload: {
2432
- operation: 'update',
2592
+ operation: "update",
2433
2593
  db,
2434
2594
  collection,
2435
2595
  _id: data._id,
@@ -2439,11 +2599,11 @@ export class Mongo extends Db {
2439
2599
  },
2440
2600
  };
2441
2601
  break;
2442
- case 'delete':
2602
+ case "delete":
2443
2603
  toPublish = {
2444
2604
  channel,
2445
2605
  payload: {
2446
- operation: 'delete',
2606
+ operation: "delete",
2447
2607
  db,
2448
2608
  collection,
2449
2609
  _id: data._id,
@@ -2453,30 +2613,30 @@ export class Mongo extends Db {
2453
2613
  },
2454
2614
  };
2455
2615
  break;
2456
- case 'updateMany':
2616
+ case "updateMany":
2457
2617
  toPublish = {
2458
2618
  channel,
2459
2619
  payload: {
2460
- operation: 'updateMany',
2620
+ operation: "updateMany",
2461
2621
  db,
2462
2622
  collection,
2463
2623
  enquireLastTs: true,
2464
2624
  },
2465
2625
  };
2466
2626
  break;
2467
- case 'deleteMany':
2627
+ case "deleteMany":
2468
2628
  toPublish = {
2469
2629
  channel,
2470
2630
  payload: {
2471
- operation: 'deleteMany',
2631
+ operation: "deleteMany",
2472
2632
  db,
2473
2633
  collection,
2474
2634
  enquireLastTs: true,
2475
2635
  },
2476
2636
  };
2477
2637
  break;
2478
- case 'batch':
2479
- throw new Error('batch operation should use direct emit, not _makeRevPublication');
2638
+ case "batch":
2639
+ throw new Error("batch operation should use direct emit, not _makeRevPublication");
2480
2640
  }
2481
2641
  if (user)
2482
2642
  toPublish.user = user;
@@ -2493,12 +2653,17 @@ export class Mongo extends Db {
2493
2653
  if (!this.auditing)
2494
2654
  return;
2495
2655
  let client = await this.connect();
2496
- let previousAuditRecords = await (await client.db(db).collection(this.auditCollectionName).aggregate([
2656
+ let previousAuditRecords = await (await client
2657
+ .db(db)
2658
+ .collection(this.auditCollectionName)
2659
+ .aggregate([
2497
2660
  { $match: { entityid: Mongo._toId(data._id) } },
2498
2661
  { $sort: { rev: -1 } },
2499
- { $limit: 1 }
2662
+ { $limit: 1 },
2500
2663
  ], this.session ? { session: this.session } : {})).toArray();
2501
- let previousAuditRecord = previousAuditRecords.length ? previousAuditRecords[0] : { rev: 0, changes: {} };
2664
+ let previousAuditRecord = previousAuditRecords.length
2665
+ ? previousAuditRecords[0]
2666
+ : { rev: 0, changes: {} };
2502
2667
  if (previousAuditRecords.length === 0)
2503
2668
  await this.createCollection(this.auditCollectionName);
2504
2669
  let dataNoId = { ...data };
@@ -2517,11 +2682,12 @@ export class Mongo extends Db {
2517
2682
  auditRecord.user = user;
2518
2683
  if (audit)
2519
2684
  auditRecord.audit = audit;
2520
- fjLog.trace('AUDITING', auditRecord);
2521
- let ret = await client.db(db)
2685
+ fjLog.trace("AUDITING", auditRecord);
2686
+ let ret = await client
2687
+ .db(db)
2522
2688
  .collection(this.auditCollectionName)
2523
2689
  .insertOne(auditRecord, this._sessionOpt());
2524
- fjLog.debug('AUDITED', auditRecord, ret.insertedId);
2690
+ fjLog.debug("AUDITED", auditRecord, ret.insertedId);
2525
2691
  }
2526
2692
  _sessionOpt() {
2527
2693
  return this.session ? { session: this.session } : {};
@@ -2552,7 +2718,7 @@ export class Mongo extends Db {
2552
2718
  return Object.keys(obj).some(startsWithHashedPrefix);
2553
2719
  }
2554
2720
  _hasSequenceFields(obj) {
2555
- return Object.values(obj).some(v => v === 'SEQ_NEXT' || v === 'SEQ_LAST');
2721
+ return Object.values(obj).some((v) => v === "SEQ_NEXT" || v === "SEQ_LAST");
2556
2722
  }
2557
2723
  _processUpdateObject(update) {
2558
2724
  for (let k in update) {
@@ -2560,7 +2726,8 @@ export class Mongo extends Db {
2560
2726
  const keyStr = String(key);
2561
2727
  if (keyStr[0] === "$")
2562
2728
  continue;
2563
- if (startsWithDoubleUnderscore(keyStr) && !keyStr.startsWith(HASHED_PREFIX)) {
2729
+ if (startsWithDoubleUnderscore(keyStr) &&
2730
+ !keyStr.startsWith(HASHED_PREFIX)) {
2564
2731
  delete update[key];
2565
2732
  continue;
2566
2733
  }
@@ -2568,7 +2735,7 @@ export class Mongo extends Db {
2568
2735
  delete update[key];
2569
2736
  continue;
2570
2737
  }
2571
- if (key === '' || key === null || key === undefined) {
2738
+ if (key === "" || key === null || key === undefined) {
2572
2739
  delete update[key];
2573
2740
  continue;
2574
2741
  }
@@ -2586,12 +2753,14 @@ export class Mongo extends Db {
2586
2753
  if (this.revisions) {
2587
2754
  update.$inc = update.$inc || {};
2588
2755
  update.$inc._rev = 1;
2589
- const currentDate = update.$currentDate && typeof update.$currentDate === 'object' && !Array.isArray(update.$currentDate)
2756
+ const currentDate = update.$currentDate &&
2757
+ typeof update.$currentDate === "object" &&
2758
+ !Array.isArray(update.$currentDate)
2590
2759
  ? update.$currentDate
2591
2760
  : undefined;
2592
2761
  update.$currentDate = {
2593
2762
  ...(currentDate || {}),
2594
- _ts: { $type: 'timestamp' }
2763
+ _ts: { $type: "timestamp" },
2595
2764
  };
2596
2765
  }
2597
2766
  if (update.$set) {
@@ -2631,35 +2800,41 @@ export class Mongo extends Db {
2631
2800
  const translatePath = (path) => {
2632
2801
  const tokens = Mongo._tokenizePath(path);
2633
2802
  const out = [];
2634
- let parentKey = '';
2803
+ let parentKey = "";
2635
2804
  for (const t of tokens) {
2636
- if (t.length >= 2 && t.charCodeAt(0) === 91 /* [ */ && t.charCodeAt(t.length - 1) === 93 /* ] */) {
2805
+ if (t.length >= 2 &&
2806
+ t.charCodeAt(0) === 91 /* [ */ &&
2807
+ t.charCodeAt(t.length - 1) === 93 /* ] */) {
2637
2808
  const idStr = Mongo._unquoteBracketId(t, path);
2638
2809
  const memoKey = `${parentKey}|${idStr}`;
2639
2810
  let filterName = memo.get(memoKey);
2640
2811
  if (filterName === undefined) {
2641
2812
  filterName = `f${counter++}`;
2642
2813
  memo.set(memoKey, filterName);
2643
- filters.push({ [`${filterName}._id`]: Mongo._normalizeBracketId(idStr) });
2814
+ filters.push({
2815
+ [`${filterName}._id`]: Mongo._normalizeBracketId(idStr),
2816
+ });
2644
2817
  }
2645
2818
  out.push(`$[${filterName}]`);
2646
- parentKey = parentKey ? `${parentKey}.$[${filterName}]` : `$[${filterName}]`;
2819
+ parentKey = parentKey
2820
+ ? `${parentKey}.$[${filterName}]`
2821
+ : `$[${filterName}]`;
2647
2822
  }
2648
2823
  else {
2649
2824
  out.push(t);
2650
2825
  parentKey = parentKey ? `${parentKey}.${t}` : t;
2651
2826
  }
2652
2827
  }
2653
- return out.join('.');
2828
+ return out.join(".");
2654
2829
  };
2655
2830
  const translateOp = (opName) => {
2656
2831
  const op = update[opName];
2657
- if (!op || typeof op !== 'object')
2832
+ if (!op || typeof op !== "object")
2658
2833
  return;
2659
2834
  // Fast path: skip rebuild if no bracket present.
2660
2835
  let hasBracket = false;
2661
2836
  for (const k of Object.keys(op)) {
2662
- if (k.indexOf('[') >= 0) {
2837
+ if (k.indexOf("[") >= 0) {
2663
2838
  hasBracket = true;
2664
2839
  break;
2665
2840
  }
@@ -2672,8 +2847,8 @@ export class Mongo extends Db {
2672
2847
  }
2673
2848
  update[opName] = translated;
2674
2849
  };
2675
- translateOp('$set');
2676
- translateOp('$unset');
2850
+ translateOp("$set");
2851
+ translateOp("$unset");
2677
2852
  return filters.length > 0 ? filters : undefined;
2678
2853
  }
2679
2854
  /**
@@ -2723,38 +2898,38 @@ export class Mongo extends Db {
2723
2898
  var _a;
2724
2899
  if (value === null || value === undefined)
2725
2900
  return false;
2726
- if (typeof value !== 'object')
2901
+ if (typeof value !== "object")
2727
2902
  return false;
2728
2903
  if (value instanceof Date)
2729
2904
  return false;
2730
2905
  const ctorName = (_a = value.constructor) === null || _a === void 0 ? void 0 : _a.name;
2731
- if (ctorName === 'ObjectId' ||
2732
- ctorName === 'Timestamp' ||
2733
- ctorName === 'Decimal128' ||
2734
- ctorName === 'Binary' ||
2735
- ctorName === 'Long' ||
2736
- ctorName === 'Double' ||
2737
- ctorName === 'Int32')
2906
+ if (ctorName === "ObjectId" ||
2907
+ ctorName === "Timestamp" ||
2908
+ ctorName === "Decimal128" ||
2909
+ ctorName === "Binary" ||
2910
+ ctorName === "Long" ||
2911
+ ctorName === "Double" ||
2912
+ ctorName === "Int32")
2738
2913
  return false;
2739
2914
  return true;
2740
2915
  }
2741
2916
  static _tokenizePath(path) {
2742
2917
  const out = [];
2743
- let buf = '';
2918
+ let buf = "";
2744
2919
  for (let i = 0; i < path.length; i++) {
2745
2920
  const ch = path[i];
2746
- if (ch === '.') {
2921
+ if (ch === ".") {
2747
2922
  if (buf) {
2748
2923
  out.push(buf);
2749
- buf = '';
2924
+ buf = "";
2750
2925
  }
2751
2926
  }
2752
- else if (ch === '[') {
2927
+ else if (ch === "[") {
2753
2928
  if (buf) {
2754
2929
  out.push(buf);
2755
- buf = '';
2930
+ buf = "";
2756
2931
  }
2757
- const close = path.indexOf(']', i);
2932
+ const close = path.indexOf("]", i);
2758
2933
  if (close < 0) {
2759
2934
  buf += ch;
2760
2935
  continue;
@@ -2786,7 +2961,8 @@ export class Mongo extends Db {
2786
2961
  if (len >= 2) {
2787
2962
  const first = id.charCodeAt(0);
2788
2963
  const last = id.charCodeAt(len - 1);
2789
- if ((first === 39 /* ' */ && last === 39) || (first === 34 /* " */ && last === 34)) {
2964
+ if ((first === 39 /* ' */ && last === 39) ||
2965
+ (first === 34 /* " */ && last === 34)) {
2790
2966
  id = id.slice(1, -1);
2791
2967
  }
2792
2968
  }
@@ -2818,11 +2994,11 @@ export class Mongo extends Db {
2818
2994
  */
2819
2995
  _validateAndAutoFillTerminalBracketValues(update) {
2820
2996
  const $set = update.$set;
2821
- if (!$set || typeof $set !== 'object')
2997
+ if (!$set || typeof $set !== "object")
2822
2998
  return;
2823
2999
  let hasBracket = false;
2824
3000
  for (const k of Object.keys($set)) {
2825
- if (k.indexOf('[') >= 0) {
3001
+ if (k.indexOf("[") >= 0) {
2826
3002
  hasBracket = true;
2827
3003
  break;
2828
3004
  }
@@ -2832,17 +3008,17 @@ export class Mongo extends Db {
2832
3008
  for (const path of Object.keys($set)) {
2833
3009
  const tokens = Mongo._tokenizePath(path);
2834
3010
  const lastToken = tokens[tokens.length - 1];
2835
- const isTerminalBracket = !!(lastToken
2836
- && lastToken.length >= 2
2837
- && lastToken.charCodeAt(0) === 91 /* [ */
2838
- && lastToken.charCodeAt(lastToken.length - 1) === 93 /* ] */);
3011
+ const isTerminalBracket = !!((lastToken &&
3012
+ lastToken.length >= 2 &&
3013
+ lastToken.charCodeAt(0) === 91 /* [ */ &&
3014
+ lastToken.charCodeAt(lastToken.length - 1) === 93) /* ] */);
2839
3015
  if (!isTerminalBracket)
2840
3016
  continue;
2841
3017
  const bracketId = Mongo._unquoteBracketId(lastToken, path); // throws on empty
2842
3018
  const value = $set[path];
2843
3019
  const validateElement = (el, locator) => {
2844
- if (el == null || typeof el !== 'object') {
2845
- throw new Error(`cry-db: bracket-id terminal at "${path}"${locator} — value must be an object with _id matching bracket id "${bracketId}" (got ${el === null ? 'null' : typeof el}).`);
3020
+ if (el == null || typeof el !== "object") {
3021
+ throw new Error(`cry-db: bracket-id terminal at "${path}"${locator} — value must be an object with _id matching bracket id "${bracketId}" (got ${el === null ? "null" : typeof el}).`);
2846
3022
  }
2847
3023
  if (el._id == null) {
2848
3024
  throw new Error(`cry-db: bracket-id terminal at "${path}"${locator} — element is missing _id. Set it explicitly to "${bracketId}" (auto-fill is no longer supported).`);
@@ -2855,8 +3031,10 @@ export class Mongo extends Db {
2855
3031
  for (let i = 0; i < value.length; i++)
2856
3032
  validateElement(value[i], ` [${i}]`);
2857
3033
  }
2858
- else if (value !== null && value !== undefined && typeof value === 'object') {
2859
- validateElement(value, '');
3034
+ else if (value !== null &&
3035
+ value !== undefined &&
3036
+ typeof value === "object") {
3037
+ validateElement(value, "");
2860
3038
  }
2861
3039
  // Primitives (string/number/boolean) — pass through to existing arrayFilters
2862
3040
  // path. Mongo would set the array element to the primitive, which is unusual
@@ -2887,12 +3065,12 @@ export class Mongo extends Db {
2887
3065
  */
2888
3066
  _extractArrayInserts(update) {
2889
3067
  const $set = update.$set;
2890
- if (!$set || typeof $set !== 'object')
3068
+ if (!$set || typeof $set !== "object")
2891
3069
  return undefined;
2892
3070
  // Fast path: no bracket present in any key.
2893
3071
  let hasBracket = false;
2894
3072
  for (const k of Object.keys($set)) {
2895
- if (k.indexOf('[') >= 0) {
3073
+ if (k.indexOf("[") >= 0) {
2896
3074
  hasBracket = true;
2897
3075
  break;
2898
3076
  }
@@ -2905,19 +3083,19 @@ export class Mongo extends Db {
2905
3083
  const value = $set[path];
2906
3084
  const tokens = Mongo._tokenizePath(path);
2907
3085
  const lastToken = tokens[tokens.length - 1];
2908
- const isTerminalBracket = !!(lastToken
2909
- && lastToken.length >= 2
2910
- && lastToken.charCodeAt(0) === 91 /* [ */
2911
- && lastToken.charCodeAt(lastToken.length - 1) === 93 /* ] */);
3086
+ const isTerminalBracket = !!((lastToken &&
3087
+ lastToken.length >= 2 &&
3088
+ lastToken.charCodeAt(0) === 91 /* [ */ &&
3089
+ lastToken.charCodeAt(lastToken.length - 1) === 93) /* ] */);
2912
3090
  if (isTerminalBracket && Array.isArray(value)) {
2913
3091
  const parentTokens = tokens.slice(0, -1);
2914
3092
  // Reject nested-bracket parent paths — combining $push semantics with
2915
3093
  // arrayFilters-targeted parent is not cleanly expressible in mongo.
2916
3094
  const parentHasBracket = parentTokens.some((t) => t.length > 0 && t.charCodeAt(0) === 91);
2917
3095
  // Every element must have `_id` (required so we can dedupe before push).
2918
- const allElementsHaveId = value.every((e) => e && typeof e === 'object' && e._id != null);
3096
+ const allElementsHaveId = value.every((e) => e && typeof e === "object" && e._id != null);
2919
3097
  if (!parentHasBracket && allElementsHaveId && parentTokens.length > 0) {
2920
- const fieldPath = parentTokens.join('.');
3098
+ const fieldPath = parentTokens.join(".");
2921
3099
  const ids = value.map((e) => String(e._id));
2922
3100
  inserts.push({ field: fieldPath, ids, elements: value });
2923
3101
  continue;
@@ -2954,11 +3132,11 @@ export class Mongo extends Db {
2954
3132
  */
2955
3133
  _extractArrayRemoves(update) {
2956
3134
  const $unset = update.$unset;
2957
- if (!$unset || typeof $unset !== 'object')
3135
+ if (!$unset || typeof $unset !== "object")
2958
3136
  return undefined;
2959
3137
  let hasBracket = false;
2960
3138
  for (const k of Object.keys($unset)) {
2961
- if (k.indexOf('[') >= 0) {
3139
+ if (k.indexOf("[") >= 0) {
2962
3140
  hasBracket = true;
2963
3141
  break;
2964
3142
  }
@@ -2970,15 +3148,15 @@ export class Mongo extends Db {
2970
3148
  for (const path of Object.keys($unset)) {
2971
3149
  const tokens = Mongo._tokenizePath(path);
2972
3150
  const lastToken = tokens[tokens.length - 1];
2973
- const isTerminalBracket = !!(lastToken
2974
- && lastToken.length >= 2
2975
- && lastToken.charCodeAt(0) === 91 /* [ */
2976
- && lastToken.charCodeAt(lastToken.length - 1) === 93 /* ] */);
3151
+ const isTerminalBracket = !!((lastToken &&
3152
+ lastToken.length >= 2 &&
3153
+ lastToken.charCodeAt(0) === 91 /* [ */ &&
3154
+ lastToken.charCodeAt(lastToken.length - 1) === 93) /* ] */);
2977
3155
  if (isTerminalBracket) {
2978
3156
  const parentTokens = tokens.slice(0, -1);
2979
3157
  const parentHasBracket = parentTokens.some((t) => t.length > 0 && t.charCodeAt(0) === 91);
2980
3158
  if (!parentHasBracket && parentTokens.length > 0) {
2981
- const fieldPath = parentTokens.join('.');
3159
+ const fieldPath = parentTokens.join(".");
2982
3160
  const id = Mongo._unquoteBracketId(lastToken, path);
2983
3161
  if (!removesByField.has(fieldPath))
2984
3162
  removesByField.set(fieldPath, []);
@@ -2993,7 +3171,10 @@ export class Mongo extends Db {
2993
3171
  update.$unset = remaining;
2994
3172
  if (Object.keys(remaining).length === 0)
2995
3173
  delete update.$unset;
2996
- return Array.from(removesByField.entries()).map(([field, ids]) => ({ field, ids }));
3174
+ return Array.from(removesByField.entries()).map(([field, ids]) => ({
3175
+ field,
3176
+ ids,
3177
+ }));
2997
3178
  }
2998
3179
  /**
2999
3180
  * Extracts SINGLE-bracket bracket-by-_id paths from `$set`/`$unset`, grouped
@@ -3029,11 +3210,11 @@ export class Mongo extends Db {
3029
3210
  };
3030
3211
  const processOp = (opName) => {
3031
3212
  const op = update[opName];
3032
- if (!op || typeof op !== 'object')
3213
+ if (!op || typeof op !== "object")
3033
3214
  return;
3034
3215
  let hasBracket = false;
3035
3216
  for (const k of Object.keys(op)) {
3036
- if (k.indexOf('[') >= 0) {
3217
+ if (k.indexOf("[") >= 0) {
3037
3218
  hasBracket = true;
3038
3219
  break;
3039
3220
  }
@@ -3048,18 +3229,20 @@ export class Mongo extends Db {
3048
3229
  let bracketIdx = -1;
3049
3230
  for (let i = 0; i < tokens.length; i++) {
3050
3231
  const t = tokens[i];
3051
- if (t.length >= 2 && t.charCodeAt(0) === 91 /* [ */ && t.charCodeAt(t.length - 1) === 93 /* ] */) {
3232
+ if (t.length >= 2 &&
3233
+ t.charCodeAt(0) === 91 /* [ */ &&
3234
+ t.charCodeAt(t.length - 1) === 93 /* ] */) {
3052
3235
  bracketCount++;
3053
3236
  bracketIdx = i;
3054
3237
  }
3055
3238
  }
3056
3239
  if (bracketCount === 1 && bracketIdx > 0) {
3057
- const parentField = tokens.slice(0, bracketIdx).join('.');
3240
+ const parentField = tokens.slice(0, bracketIdx).join(".");
3058
3241
  const id = Mongo._unquoteBracketId(tokens[bracketIdx], path);
3059
- const restPath = tokens.slice(bracketIdx + 1).join('.');
3242
+ const restPath = tokens.slice(bracketIdx + 1).join(".");
3060
3243
  const elOps = ensureEntry(parentField, id);
3061
- if (opName === '$set') {
3062
- if (restPath === '') {
3244
+ if (opName === "$set") {
3245
+ if (restPath === "") {
3063
3246
  // `arr[id]: <obj>` — whole-element replace.
3064
3247
  elOps.replace = op[path];
3065
3248
  }
@@ -3070,7 +3253,7 @@ export class Mongo extends Db {
3070
3253
  else {
3071
3254
  // `$unset arr[id].field` — sub-field unset. Terminal `$unset arr[id]`
3072
3255
  // is already extracted by `_extractArrayRemoves`.
3073
- if (restPath === '') {
3256
+ if (restPath === "") {
3074
3257
  remaining[path] = op[path];
3075
3258
  continue;
3076
3259
  }
@@ -3088,8 +3271,8 @@ export class Mongo extends Db {
3088
3271
  delete update[opName];
3089
3272
  }
3090
3273
  };
3091
- processOp('$set');
3092
- processOp('$unset');
3274
+ processOp("$set");
3275
+ processOp("$unset");
3093
3276
  return extractedAny ? result : undefined;
3094
3277
  }
3095
3278
  /**
@@ -3108,8 +3291,8 @@ export class Mongo extends Db {
3108
3291
  const filteredInput = {
3109
3292
  $filter: {
3110
3293
  input: { $ifNull: [baseInputPath, []] },
3111
- as: 'el',
3112
- cond: { $not: { $in: ['$$el._id', dedupedRemoveIds] } },
3294
+ as: "el",
3295
+ cond: { $not: { $in: ["$$el._id", dedupedRemoveIds] } },
3113
3296
  },
3114
3297
  };
3115
3298
  const concatExpr = {
@@ -3120,15 +3303,15 @@ export class Mongo extends Db {
3120
3303
  const branches = [];
3121
3304
  for (const [id, elOps] of ops.elementOps.entries()) {
3122
3305
  branches.push({
3123
- case: { $eq: ['$$el._id', Mongo._normalizeBracketId(id)] },
3124
- then: Mongo._buildElementMergeExpr('$$el', elOps),
3306
+ case: { $eq: ["$$el._id", Mongo._normalizeBracketId(id)] },
3307
+ then: Mongo._buildElementMergeExpr("$$el", elOps),
3125
3308
  });
3126
3309
  }
3127
3310
  return {
3128
3311
  $map: {
3129
3312
  input: concatExpr,
3130
- as: 'el',
3131
- in: { $switch: { branches, default: '$$el' } },
3313
+ as: "el",
3314
+ in: { $switch: { branches, default: "$$el" } },
3132
3315
  },
3133
3316
  };
3134
3317
  }
@@ -3211,13 +3394,13 @@ export class Mongo extends Db {
3211
3394
  return {
3212
3395
  $let: {
3213
3396
  vars: { replaced: replaceExpr },
3214
- in: wrapWithNestedArrays('$$replaced', '$$replaced'),
3397
+ in: wrapWithNestedArrays("$$replaced", "$$replaced"),
3215
3398
  },
3216
3399
  };
3217
3400
  }
3218
3401
  const root = { directs: {}, nested: {}, unsets: [] };
3219
3402
  const walkInsert = (path, isUnset, value) => {
3220
- const parts = path.split('.');
3403
+ const parts = path.split(".");
3221
3404
  let node = root;
3222
3405
  for (let i = 0; i < parts.length - 1; i++) {
3223
3406
  const key = parts[i];
@@ -3255,15 +3438,17 @@ export class Mongo extends Db {
3255
3438
  overlay[k] = buildOverlay(sub, subPath);
3256
3439
  }
3257
3440
  // Merge sets/nested onto the existing object (or {} if absent).
3258
- let merged = { $mergeObjects: [{ $ifNull: [basePath, {}] }, overlay] };
3441
+ let merged = {
3442
+ $mergeObjects: [{ $ifNull: [basePath, {}] }, overlay],
3443
+ };
3259
3444
  // Drop unset top-level keys at this level via kv-filter.
3260
3445
  if (node.unsets.length > 0) {
3261
3446
  merged = {
3262
3447
  $arrayToObject: {
3263
3448
  $filter: {
3264
3449
  input: { $objectToArray: merged },
3265
- as: 'kv',
3266
- cond: { $not: { $in: ['$$kv.k', node.unsets] } },
3450
+ as: "kv",
3451
+ cond: { $not: { $in: ["$$kv.k", node.unsets] } },
3267
3452
  },
3268
3453
  },
3269
3454
  };
@@ -3273,11 +3458,11 @@ export class Mongo extends Db {
3273
3458
  // If a replace is also requested, treat replacement as the new base.
3274
3459
  // Wrap with `$let` since a literal object isn't addressable by string field path.
3275
3460
  if (hasReplace) {
3276
- const overlayExpr = buildOverlay(root, '$$replaced');
3461
+ const overlayExpr = buildOverlay(root, "$$replaced");
3277
3462
  return {
3278
3463
  $let: {
3279
3464
  vars: { replaced: { $literal: ops.replace } },
3280
- in: wrapWithNestedArrays(overlayExpr, '$$replaced'),
3465
+ in: wrapWithNestedArrays(overlayExpr, "$$replaced"),
3281
3466
  },
3282
3467
  };
3283
3468
  }
@@ -3298,7 +3483,7 @@ export class Mongo extends Db {
3298
3483
  static _drainIncAndCurrentDateToPipelineStages(update) {
3299
3484
  const stages = [];
3300
3485
  const inc = update.$inc;
3301
- if (inc && typeof inc === 'object') {
3486
+ if (inc && typeof inc === "object") {
3302
3487
  const setObj = {};
3303
3488
  for (const [k, v] of Object.entries(inc)) {
3304
3489
  setObj[k] = { $add: [{ $ifNull: [`$${k}`, 0] }, v] };
@@ -3308,13 +3493,15 @@ export class Mongo extends Db {
3308
3493
  delete update.$inc;
3309
3494
  }
3310
3495
  const cd = update.$currentDate;
3311
- if (cd && typeof cd === 'object') {
3496
+ if (cd && typeof cd === "object") {
3312
3497
  const setObj = {};
3313
3498
  for (const [k, spec] of Object.entries(cd)) {
3314
3499
  let isTimestamp = false;
3315
- if (spec && typeof spec === 'object' && spec.$type === 'timestamp')
3500
+ if (spec &&
3501
+ typeof spec === "object" &&
3502
+ spec.$type === "timestamp")
3316
3503
  isTimestamp = true;
3317
- setObj[k] = isTimestamp ? '$$CLUSTER_TIME' : '$$NOW';
3504
+ setObj[k] = isTimestamp ? "$$CLUSTER_TIME" : "$$NOW";
3318
3505
  }
3319
3506
  if (Object.keys(setObj).length > 0)
3320
3507
  stages.push({ $set: setObj });
@@ -3370,14 +3557,18 @@ export class Mongo extends Db {
3370
3557
  continue;
3371
3558
  let bracketCount = 0;
3372
3559
  for (const t of tokens) {
3373
- if (t.length >= 2 && t.charCodeAt(0) === 91 && t.charCodeAt(t.length - 1) === 93) {
3560
+ if (t.length >= 2 &&
3561
+ t.charCodeAt(0) === 91 &&
3562
+ t.charCodeAt(t.length - 1) === 93) {
3374
3563
  bracketCount++;
3375
3564
  }
3376
3565
  }
3377
3566
  if (bracketCount < 2)
3378
3567
  continue;
3379
3568
  const last = tokens[tokens.length - 1];
3380
- if (last.length >= 2 && last.charCodeAt(0) === 91 && last.charCodeAt(last.length - 1) === 93) {
3569
+ if (last.length >= 2 &&
3570
+ last.charCodeAt(0) === 91 &&
3571
+ last.charCodeAt(last.length - 1) === 93) {
3381
3572
  return true;
3382
3573
  }
3383
3574
  }
@@ -3385,13 +3576,51 @@ export class Mongo extends Db {
3385
3576
  };
3386
3577
  const $setEarlyForNested = update.$set;
3387
3578
  const $unsetEarlyForNested = update.$unset;
3388
- const hasNestedTerminal = hasNestedTerminalBracket($setEarlyForNested) || hasNestedTerminalBracket($unsetEarlyForNested);
3579
+ const hasNestedTerminal = hasNestedTerminalBracket($setEarlyForNested) ||
3580
+ hasNestedTerminalBracket($unsetEarlyForNested);
3389
3581
  // Pure sub-field updates only (no inserts, no removes, no nested-terminal) —
3390
3582
  // keep on legacy arrayFilters path (faster, smaller payload, doesn't fight
3391
3583
  // $inc/$currentDate). Nested sub-field paths like `arr[A].sub[B].field`
3392
3584
  // ARE supported via nested arrayFilters here.
3393
3585
  if (!inserts && !removes && !hasNestedTerminal) {
3394
3586
  const arrayFilters = this._extractArrayFilters(update);
3587
+ // Detect conflict: bare-field `$set` with array value alongside a
3588
+ // bracket-transformed sub-path on the same field (`postavke: [...]` +
3589
+ // `postavke.$[f0].nbc`). MongoDB silently drops the sub-field update
3590
+ // in this case — throw so the caller gets an error instead of data loss.
3591
+ if (arrayFilters) {
3592
+ // Collect bare-field array keys and sub-paths from BOTH
3593
+ // $set AND $unset — $set.postavke conflicts with both
3594
+ // $set.postavke.$[f0].nbc AND $unset.postavke.$[f0].nbc.
3595
+ const $setCheck = update.$set;
3596
+ const $unsetCheck = update.$unset;
3597
+ const bareFields = [];
3598
+ const subPaths = [];
3599
+ if ($setCheck) {
3600
+ for (const k of Object.keys($setCheck)) {
3601
+ (k.includes(".") || k.includes("[") ? subPaths : bareFields).push(k);
3602
+ }
3603
+ }
3604
+ if ($unsetCheck) {
3605
+ for (const k of Object.keys($unsetCheck)) {
3606
+ (k.includes(".") || k.includes("[") ? subPaths : bareFields).push(k);
3607
+ }
3608
+ }
3609
+ for (const bare of bareFields) {
3610
+ // Only $set bare fields with array values cause conflicts.
3611
+ if ($setCheck && Array.isArray($setCheck[bare])) {
3612
+ for (const sub of subPaths) {
3613
+ if (sub.startsWith(bare + ".") || sub.startsWith(bare + "[")) {
3614
+ throw new Error(`cry-db: bare-field array replacement "${bare}" conflicts ` +
3615
+ `with bracket-by-_id sub-field path "${sub}" on the same ` +
3616
+ `array. Replace the bare-field assignment with a ` +
3617
+ `terminal-bracket form (e.g. \`${bare}[<id>]: [...]\`) ` +
3618
+ `when combining array updates with bracket-by-_id paths.`);
3619
+ }
3620
+ }
3621
+ }
3622
+ }
3623
+ }
3395
3624
  return arrayFilters ? { update, arrayFilters } : { update };
3396
3625
  }
3397
3626
  // Removes-only fast path: `$pull` on update doc. Coexists fine with `$set` on
@@ -3412,15 +3641,14 @@ export class Mongo extends Db {
3412
3641
  for (const k of Object.keys($setEarly)) {
3413
3642
  if (k === field)
3414
3643
  return true;
3415
- if (k.startsWith(field + '.'))
3644
+ if (k.startsWith(field + "."))
3416
3645
  return true;
3417
- if (k.startsWith(field + '['))
3646
+ if (k.startsWith(field + "["))
3418
3647
  return true;
3419
3648
  }
3420
3649
  return false;
3421
3650
  };
3422
- const removesOnlyNoSetConflict = removes && !inserts
3423
- && !removes.some(rm => setTargetsField(rm.field));
3651
+ const removesOnlyNoSetConflict = removes && !inserts && !removes.some((rm) => setTargetsField(rm.field));
3424
3652
  if (removesOnlyNoSetConflict) {
3425
3653
  const pullOp = (update.$pull || {});
3426
3654
  for (const rm of removes) {
@@ -3465,12 +3693,20 @@ export class Mongo extends Db {
3465
3693
  const fieldOps = new Map();
3466
3694
  const ensureField = (container, field) => {
3467
3695
  if (!container.has(field))
3468
- container.set(field, { removeIds: [], insertElements: [], elementOps: new Map() });
3696
+ container.set(field, {
3697
+ removeIds: [],
3698
+ insertElements: [],
3699
+ elementOps: new Map(),
3700
+ });
3469
3701
  return container.get(field);
3470
3702
  };
3471
3703
  const ensureElement = (fops, id) => {
3472
3704
  if (!fops.elementOps.has(id))
3473
- fops.elementOps.set(id, { sets: {}, unsets: [], nestedArrayOps: new Map() });
3705
+ fops.elementOps.set(id, {
3706
+ sets: {},
3707
+ unsets: [],
3708
+ nestedArrayOps: new Map(),
3709
+ });
3474
3710
  const elOps = fops.elementOps.get(id);
3475
3711
  if (!elOps.nestedArrayOps)
3476
3712
  elOps.nestedArrayOps = new Map();
@@ -3514,7 +3750,7 @@ export class Mongo extends Db {
3514
3750
  return;
3515
3751
  const remaining = {};
3516
3752
  for (const path of Object.keys(op)) {
3517
- if (path.indexOf('[') < 0) {
3753
+ if (path.indexOf("[") < 0) {
3518
3754
  remaining[path] = op[path];
3519
3755
  continue;
3520
3756
  }
@@ -3522,14 +3758,16 @@ export class Mongo extends Db {
3522
3758
  const brackets = [];
3523
3759
  for (let i = 0; i < tokens.length; i++) {
3524
3760
  const t = tokens[i];
3525
- if (t.length >= 2 && t.charCodeAt(0) === 91 && t.charCodeAt(t.length - 1) === 93) {
3761
+ if (t.length >= 2 &&
3762
+ t.charCodeAt(0) === 91 &&
3763
+ t.charCodeAt(t.length - 1) === 93) {
3526
3764
  brackets.push({ idx: i, id: Mongo._unquoteBracketId(t, path) });
3527
3765
  }
3528
3766
  }
3529
3767
  if (brackets.length < 2) {
3530
3768
  // Single-bracket: extractors above should have handled it; if it
3531
3769
  // remained, it's malformed (e.g. empty parent). Drop with warning.
3532
- warnings.push({ path, value: op[path], op: opName, kind: 'dropped' });
3770
+ warnings.push({ path, value: op[path], op: opName, kind: "dropped" });
3533
3771
  continue;
3534
3772
  }
3535
3773
  // Walk all but the innermost bracket — descend through nestedArrayOps.
@@ -3538,7 +3776,7 @@ export class Mongo extends Db {
3538
3776
  for (let bi = 0; bi < brackets.length - 1; bi++) {
3539
3777
  const bracket = brackets[bi];
3540
3778
  const fieldStart = bi === 0 ? 0 : brackets[bi - 1].idx + 1;
3541
- const fieldName = tokens.slice(fieldStart, bracket.idx).join('.');
3779
+ const fieldName = tokens.slice(fieldStart, bracket.idx).join(".");
3542
3780
  if (!fieldName) {
3543
3781
  ok = false;
3544
3782
  break;
@@ -3548,21 +3786,21 @@ export class Mongo extends Db {
3548
3786
  currentMap = elOps.nestedArrayOps;
3549
3787
  }
3550
3788
  if (!ok) {
3551
- warnings.push({ path, value: op[path], op: opName, kind: 'dropped' });
3789
+ warnings.push({ path, value: op[path], op: opName, kind: "dropped" });
3552
3790
  continue;
3553
3791
  }
3554
3792
  const lastB = brackets[brackets.length - 1];
3555
3793
  const fieldStart = brackets[brackets.length - 2].idx + 1;
3556
- const innerFieldName = tokens.slice(fieldStart, lastB.idx).join('.');
3557
- const restPath = tokens.slice(lastB.idx + 1).join('.');
3794
+ const innerFieldName = tokens.slice(fieldStart, lastB.idx).join(".");
3795
+ const restPath = tokens.slice(lastB.idx + 1).join(".");
3558
3796
  if (!innerFieldName) {
3559
- warnings.push({ path, value: op[path], op: opName, kind: 'dropped' });
3797
+ warnings.push({ path, value: op[path], op: opName, kind: "dropped" });
3560
3798
  continue;
3561
3799
  }
3562
3800
  const innerFOps = ensureField(currentMap, innerFieldName);
3563
3801
  const value = op[path];
3564
- if (opName === '$set') {
3565
- if (restPath === '') {
3802
+ if (opName === "$set") {
3803
+ if (restPath === "") {
3566
3804
  if (Array.isArray(value)) {
3567
3805
  innerFOps.removeIds.push(lastB.id);
3568
3806
  innerFOps.insertElements.push(...value);
@@ -3580,7 +3818,7 @@ export class Mongo extends Db {
3580
3818
  }
3581
3819
  else {
3582
3820
  // $unset
3583
- if (restPath === '') {
3821
+ if (restPath === "") {
3584
3822
  innerFOps.removeIds.push(lastB.id);
3585
3823
  }
3586
3824
  else {
@@ -3593,8 +3831,8 @@ export class Mongo extends Db {
3593
3831
  if (Object.keys(remaining).length === 0)
3594
3832
  delete update[opName];
3595
3833
  };
3596
- processNestedPaths(update.$set, '$set');
3597
- processNestedPaths(update.$unset, '$unset');
3834
+ processNestedPaths(update.$set, "$set");
3835
+ processNestedPaths(update.$unset, "$unset");
3598
3836
  // Detect same-id overlap at NESTED levels: a "new base" (terminal-array
3599
3837
  // insert OR whole-element replace) targeting the same `_id` as a
3600
3838
  // sub-field set/unset on the same element. Both apply — new base goes
@@ -3614,7 +3852,7 @@ export class Mongo extends Db {
3614
3852
  const detectOverlaps = (container, parentPathRepr) => {
3615
3853
  for (const [field, fops] of container.entries()) {
3616
3854
  const fullField = parentPathRepr ? `${parentPathRepr}.${field}` : field;
3617
- const isNested = parentPathRepr !== '';
3855
+ const isNested = parentPathRepr !== "";
3618
3856
  // Flavor 1: terminal-array insert + sub-field on same id.
3619
3857
  const removeIdSet = new Set(fops.removeIds);
3620
3858
  if (isNested) {
@@ -3622,16 +3860,16 @@ export class Mongo extends Db {
3622
3860
  const elOps = fops.elementOps.get(id);
3623
3861
  if (!elOps)
3624
3862
  continue;
3625
- const hasOps = Object.keys(elOps.sets).length > 0
3626
- || elOps.unsets.length > 0
3627
- || elOps.replace !== undefined;
3863
+ const hasOps = Object.keys(elOps.sets).length > 0 ||
3864
+ elOps.unsets.length > 0 ||
3865
+ elOps.replace !== undefined;
3628
3866
  if (hasOps) {
3629
3867
  const insertedEl = fops.insertElements.find((e) => String(e._id) === id);
3630
3868
  warnings.push({
3631
3869
  path: `${fullField}[${id}]`,
3632
3870
  value: insertedEl,
3633
- op: '$set',
3634
- kind: 'overlap',
3871
+ op: "$set",
3872
+ kind: "overlap",
3635
3873
  });
3636
3874
  }
3637
3875
  }
@@ -3641,14 +3879,13 @@ export class Mongo extends Db {
3641
3879
  for (const [id, elOps] of fops.elementOps.entries()) {
3642
3880
  if (isNested && !removeIdSet.has(id)) {
3643
3881
  const hasReplace = elOps.replace !== undefined;
3644
- const hasSetsOrUnsets = Object.keys(elOps.sets).length > 0
3645
- || elOps.unsets.length > 0;
3882
+ const hasSetsOrUnsets = Object.keys(elOps.sets).length > 0 || elOps.unsets.length > 0;
3646
3883
  if (hasReplace && hasSetsOrUnsets) {
3647
3884
  warnings.push({
3648
3885
  path: `${fullField}[${id}]`,
3649
3886
  value: elOps.replace,
3650
- op: '$set',
3651
- kind: 'overlap',
3887
+ op: "$set",
3888
+ kind: "overlap",
3652
3889
  });
3653
3890
  }
3654
3891
  }
@@ -3658,19 +3895,21 @@ export class Mongo extends Db {
3658
3895
  }
3659
3896
  }
3660
3897
  };
3661
- detectOverlaps(fieldOps, '');
3898
+ detectOverlaps(fieldOps, "");
3662
3899
  if (warnings.length > 0) {
3663
- fjLog.warn('cry-db: bracket-by-_id warnings:', warnings);
3900
+ fjLog.warn("cry-db: bracket-by-_id warnings:", warnings);
3664
3901
  }
3665
3902
  if (update.$set && Object.keys(update.$set).length === 0)
3666
3903
  delete update.$set;
3667
- if (update.$unset && Object.keys(update.$unset).length === 0)
3904
+ if (update.$unset &&
3905
+ Object.keys(update.$unset).length === 0)
3668
3906
  delete update.$unset;
3669
3907
  const pipeline = [];
3670
3908
  if (update.$set && Object.keys(update.$set).length > 0) {
3671
3909
  pipeline.push({ $set: update.$set });
3672
3910
  }
3673
- if (update.$unset && Object.keys(update.$unset).length > 0) {
3911
+ if (update.$unset &&
3912
+ Object.keys(update.$unset).length > 0) {
3674
3913
  pipeline.push({ $unset: Object.keys(update.$unset) });
3675
3914
  }
3676
3915
  // Translate $inc / $currentDate so revisions (_rev/_ts) still update in pipeline form.
@@ -3686,7 +3925,9 @@ export class Mongo extends Db {
3686
3925
  },
3687
3926
  });
3688
3927
  }
3689
- return warnings.length > 0 ? { update: pipeline, warnings } : { update: pipeline };
3928
+ return warnings.length > 0
3929
+ ? { update: pipeline, warnings }
3930
+ : { update: pipeline };
3690
3931
  }
3691
3932
  async _processHashedKeys(obj) {
3692
3933
  const hashedKeys = Object.keys(obj).filter(startsWithHashedPrefix);
@@ -3742,10 +3983,10 @@ export class Mongo extends Db {
3742
3983
  }
3743
3984
  else {
3744
3985
  for (let key in ret) {
3745
- if (startsWithHashedPrefix(key)
3746
- || startsWithDoubleUnderscore(key)
3747
- || removeFields.has(key)
3748
- || this._removeFieldsAlways.has(key))
3986
+ if (startsWithHashedPrefix(key) ||
3987
+ startsWithDoubleUnderscore(key) ||
3988
+ removeFields.has(key) ||
3989
+ this._removeFieldsAlways.has(key))
3749
3990
  delete ret[key];
3750
3991
  }
3751
3992
  }